diff --git a/DesktopEditor/common/File.cpp b/DesktopEditor/common/File.cpp index e0518f13da..eeebe8b305 100644 --- a/DesktopEditor/common/File.cpp +++ b/DesktopEditor/common/File.cpp @@ -159,60 +159,90 @@ namespace NSFile else if (0x00 == (byteMain & 0x20)) { // 2 byte - int val = (int)(((byteMain & 0x1F) << 6) | - (pBuffer[lIndex + 1] & 0x3F)); + int val = 0; + if ((lIndex + 1) < lCount) + { + val = (int)(((byteMain & 0x1F) << 6) | + (pBuffer[lIndex + 1] & 0x3F)); + } + pUnicodeString[lIndexUnicode++] = (WCHAR)(val); lIndex += 2; } else if (0x00 == (byteMain & 0x10)) { // 3 byte - int val = (int)(((byteMain & 0x0F) << 12) | - ((pBuffer[lIndex + 1] & 0x3F) << 6) | - (pBuffer[lIndex + 2] & 0x3F)); + int val = 0; + if ((lIndex + 2) < lCount) + { + val = (int)(((byteMain & 0x0F) << 12) | + ((pBuffer[lIndex + 1] & 0x3F) << 6) | + (pBuffer[lIndex + 2] & 0x3F)); + } + pUnicodeString[lIndexUnicode++] = (WCHAR)(val); lIndex += 3; } else if (0x00 == (byteMain & 0x0F)) { // 4 byte - int val = (int)(((byteMain & 0x07) << 18) | - ((pBuffer[lIndex + 1] & 0x3F) << 12) | - ((pBuffer[lIndex + 2] & 0x3F) << 6) | - (pBuffer[lIndex + 3] & 0x3F)); + int val = 0; + if ((lIndex + 3) < lCount) + { + val = (int)(((byteMain & 0x07) << 18) | + ((pBuffer[lIndex + 1] & 0x3F) << 12) | + ((pBuffer[lIndex + 2] & 0x3F) << 6) | + (pBuffer[lIndex + 3] & 0x3F)); + } + pUnicodeString[lIndexUnicode++] = (WCHAR)(val); lIndex += 4; } else if (0x00 == (byteMain & 0x08)) { // 4 byte - int val = (int)(((byteMain & 0x07) << 18) | - ((pBuffer[lIndex + 1] & 0x3F) << 12) | - ((pBuffer[lIndex + 2] & 0x3F) << 6) | - (pBuffer[lIndex + 3] & 0x3F)); + int val = 0; + if ((lIndex + 3) < lCount) + { + val = (int)(((byteMain & 0x07) << 18) | + ((pBuffer[lIndex + 1] & 0x3F) << 12) | + ((pBuffer[lIndex + 2] & 0x3F) << 6) | + (pBuffer[lIndex + 3] & 0x3F)); + } + pUnicodeString[lIndexUnicode++] = (WCHAR)(val); lIndex += 4; } else if (0x00 == (byteMain & 0x04)) { // 5 byte - int val = (int)(((byteMain & 0x03) << 24) | - ((pBuffer[lIndex + 1] & 0x3F) << 18) | - ((pBuffer[lIndex + 2] & 0x3F) << 12) | - ((pBuffer[lIndex + 3] & 0x3F) << 6) | - (pBuffer[lIndex + 4] & 0x3F)); + int val = 0; + if ((lIndex + 4) < lCount) + { + val = (int)(((byteMain & 0x03) << 24) | + ((pBuffer[lIndex + 1] & 0x3F) << 18) | + ((pBuffer[lIndex + 2] & 0x3F) << 12) | + ((pBuffer[lIndex + 3] & 0x3F) << 6) | + (pBuffer[lIndex + 4] & 0x3F)); + } + pUnicodeString[lIndexUnicode++] = (WCHAR)(val); lIndex += 5; } else { // 6 byte - int val = (int)(((byteMain & 0x01) << 30) | - ((pBuffer[lIndex + 1] & 0x3F) << 24) | - ((pBuffer[lIndex + 2] & 0x3F) << 18) | - ((pBuffer[lIndex + 3] & 0x3F) << 12) | - ((pBuffer[lIndex + 4] & 0x3F) << 6) | - (pBuffer[lIndex + 5] & 0x3F)); + int val = 0; + if ((lIndex + 5) < lCount) + { + val = (int)(((byteMain & 0x01) << 30) | + ((pBuffer[lIndex + 1] & 0x3F) << 24) | + ((pBuffer[lIndex + 2] & 0x3F) << 18) | + ((pBuffer[lIndex + 3] & 0x3F) << 12) | + ((pBuffer[lIndex + 4] & 0x3F) << 6) | + (pBuffer[lIndex + 5] & 0x3F)); + } + pUnicodeString[lIndexUnicode++] = (WCHAR)(val); lIndex += 5; } @@ -242,17 +272,26 @@ namespace NSFile else if (0x00 == (byteMain & 0x20)) { // 2 byte - int val = (int)(((byteMain & 0x1F) << 6) | - (pBuffer[lIndex + 1] & 0x3F)); + int val = 0; + if ((lIndex + 1) < lCount) + { + val = (int)(((byteMain & 0x1F) << 6) | + (pBuffer[lIndex + 1] & 0x3F)); + } + *pUnicodeString++ = (WCHAR)(val); lIndex += 2; } else if (0x00 == (byteMain & 0x10)) { // 3 byte - int val = (int)(((byteMain & 0x0F) << 12) | - ((pBuffer[lIndex + 1] & 0x3F) << 6) | - (pBuffer[lIndex + 2] & 0x3F)); + int val = 0; + if ((lIndex + 2) < lCount) + { + val = (int)(((byteMain & 0x0F) << 12) | + ((pBuffer[lIndex + 1] & 0x3F) << 6) | + (pBuffer[lIndex + 2] & 0x3F)); + } WriteUtf16_WCHAR(val, pUnicodeString); lIndex += 3; @@ -260,10 +299,14 @@ namespace NSFile else if (0x00 == (byteMain & 0x0F)) { // 4 byte - int val = (int)(((byteMain & 0x07) << 18) | - ((pBuffer[lIndex + 1] & 0x3F) << 12) | - ((pBuffer[lIndex + 2] & 0x3F) << 6) | - (pBuffer[lIndex + 3] & 0x3F)); + int val = 0; + if ((lIndex + 3) < lCount) + { + val = (int)(((byteMain & 0x07) << 18) | + ((pBuffer[lIndex + 1] & 0x3F) << 12) | + ((pBuffer[lIndex + 2] & 0x3F) << 6) | + (pBuffer[lIndex + 3] & 0x3F)); + } WriteUtf16_WCHAR(val, pUnicodeString); lIndex += 4; @@ -271,10 +314,14 @@ namespace NSFile else if (0x00 == (byteMain & 0x08)) { // 4 byte - int val = (int)(((byteMain & 0x07) << 18) | - ((pBuffer[lIndex + 1] & 0x3F) << 12) | - ((pBuffer[lIndex + 2] & 0x3F) << 6) | - (pBuffer[lIndex + 3] & 0x3F)); + int val = 0; + if ((lIndex + 3) < lCount) + { + val = (int)(((byteMain & 0x07) << 18) | + ((pBuffer[lIndex + 1] & 0x3F) << 12) | + ((pBuffer[lIndex + 2] & 0x3F) << 6) | + (pBuffer[lIndex + 3] & 0x3F)); + } WriteUtf16_WCHAR(val, pUnicodeString); lIndex += 4; @@ -282,11 +329,15 @@ namespace NSFile else if (0x00 == (byteMain & 0x04)) { // 5 byte - int val = (int)(((byteMain & 0x03) << 24) | - ((pBuffer[lIndex + 1] & 0x3F) << 18) | - ((pBuffer[lIndex + 2] & 0x3F) << 12) | - ((pBuffer[lIndex + 3] & 0x3F) << 6) | - (pBuffer[lIndex + 4] & 0x3F)); + int val = 0; + if ((lIndex + 4) < lCount) + { + val = (int)(((byteMain & 0x03) << 24) | + ((pBuffer[lIndex + 1] & 0x3F) << 18) | + ((pBuffer[lIndex + 2] & 0x3F) << 12) | + ((pBuffer[lIndex + 3] & 0x3F) << 6) | + (pBuffer[lIndex + 4] & 0x3F)); + } WriteUtf16_WCHAR(val, pUnicodeString); lIndex += 5; @@ -294,12 +345,16 @@ namespace NSFile else { // 6 byte - int val = (int)(((byteMain & 0x01) << 30) | - ((pBuffer[lIndex + 1] & 0x3F) << 24) | - ((pBuffer[lIndex + 2] & 0x3F) << 18) | - ((pBuffer[lIndex + 3] & 0x3F) << 12) | - ((pBuffer[lIndex + 4] & 0x3F) << 6) | - (pBuffer[lIndex + 5] & 0x3F)); + int val = 0; + if ((lIndex + 5) < lCount) + { + val = (int)(((byteMain & 0x01) << 30) | + ((pBuffer[lIndex + 1] & 0x3F) << 24) | + ((pBuffer[lIndex + 2] & 0x3F) << 18) | + ((pBuffer[lIndex + 3] & 0x3F) << 12) | + ((pBuffer[lIndex + 4] & 0x3F) << 6) | + (pBuffer[lIndex + 5] & 0x3F)); + } WriteUtf16_WCHAR(val, pUnicodeString); lIndex += 5; diff --git a/DesktopEditor/cximage/CxImage/xfile.h b/DesktopEditor/cximage/CxImage/xfile.h index 78482cce45..1e84f1c156 100644 --- a/DesktopEditor/cximage/CxImage/xfile.h +++ b/DesktopEditor/cximage/CxImage/xfile.h @@ -49,11 +49,11 @@ class DLL_EXP CxFile { public: - CxFile(void) { }; - virtual ~CxFile() { }; + CxFile(void) { } + virtual ~CxFile() { } virtual bool Close() = 0; - virtual size_t Read(void *buffer, size_t size, size_t count) = 0; + virtual size_t Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL) = 0; virtual size_t Write(const void *buffer, size_t size, size_t count) = 0; virtual bool Seek(int32_t offset, int32_t origin) = 0; virtual int32_t Tell() = 0; @@ -72,4 +72,27 @@ public: virtual int32_t Scanf(const char *format, void* output) = 0; }; +static void clamp_buffer(void*& buffer, size_t& size, void* limit_start, void* limit_end) +{ + if (NULL == limit_start || NULL == limit_end) + return; + + uint8_t* _buffer = (uint8_t*)buffer; + uint8_t* _limit_start = (uint8_t*)limit_start; + uint8_t* _limit_end = (uint8_t*)limit_end; + + if (_buffer > _limit_end) + { + buffer = limit_end; + size = 0; + return; + } + + if (_buffer < _limit_start) + _buffer = _limit_start; + + if ((_buffer + size) > _limit_end) + size = (_limit_end - _buffer); +} + #endif //__xfile_h diff --git a/DesktopEditor/cximage/CxImage/ximabmp.cpp b/DesktopEditor/cximage/CxImage/ximabmp.cpp index d03d97d78e..cd8b2743e7 100644 --- a/DesktopEditor/cximage/CxImage/ximabmp.cpp +++ b/DesktopEditor/cximage/CxImage/ximabmp.cpp @@ -133,7 +133,7 @@ bool CxImageBMP::Decode(CxFile * hFile) if (bIsOldBmp){ // convert a old color table (3 byte entries) to a new // color table (4 byte entries) - hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1); + hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1,GetDIB(),GetDIBLimit()); for (int32_t i=DibNumColors(&head)-1; i>=0; i--){ pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed; pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue; @@ -141,7 +141,7 @@ bool CxImageBMP::Decode(CxFile * hFile) pRgb[i].rgbReserved = (uint8_t)0; } } else { - hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1); + hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1,GetDIB(),GetDIBLimit()); //force rgbReserved=0, to avoid problems with some WinXp bitmaps for (uint32_t i=0; iRead(buff32, imagesize,1); // read in the pixels + hFile->Read(buff32, imagesize,1,GetDIB(),GetDIBLimit()); // read in the pixels #if CXIMAGE_SUPPORT_ALPHA if (dwCompression == BI_RGB){ @@ -195,7 +195,7 @@ bool CxImageBMP::Decode(CxFile * hFile) case 24 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); if (dwCompression == BI_RGB){ - hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels + hFile->Read(info.pImage, head.biSizeImage,1,GetDIB(),GetDIBLimit()); // read in the pixels } else cx_throw("unknown compression"); break; case 16 : @@ -210,7 +210,7 @@ bool CxImageBMP::Decode(CxFile * hFile) // bf.bfOffBits required after the bitfield mask if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); // read in the pixels - hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1); + hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1,GetDIB(),GetDIBLimit()); // transform into RGB Bitfield2RGB(info.pImage,bfmask[0],bfmask[1],bfmask[2],16); break; @@ -229,7 +229,7 @@ bool CxImageBMP::Decode(CxFile * hFile) } switch (dwCompression) { case BI_RGB : - hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels + hFile->Read(info.pImage, head.biSizeImage,1,GetDIB(),GetDIBLimit()); // read in the pixels break; case BI_RLE4 : { @@ -355,7 +355,7 @@ bool CxImageBMP::Decode(CxFile * hFile) break; } default : - hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1); + hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1,GetDIB(),GetDIBLimit()); // align run length to even number of bytes if ((status_byte & 1) == 1) hFile->Read(&second_byte, sizeof(uint8_t), 1); diff --git a/DesktopEditor/cximage/CxImage/ximaexif.cpp b/DesktopEditor/cximage/CxImage/ximaexif.cpp index e93ec53eaa..d5cd21cc3d 100644 --- a/DesktopEditor/cximage/CxImage/ximaexif.cpp +++ b/DesktopEditor/cximage/CxImage/ximaexif.cpp @@ -165,7 +165,7 @@ bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int32_t nReadMode) // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. - if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ + if ((nReadMode & EXIF_READ_EXIF) && itemlen >= 6 && memcmp(Data+2, "Exif", 4) == 0){ m_exifinfo->IsExif = process_EXIF((uint8_t *)Data+2, itemlen-2); }else{ // Discard this section. @@ -187,6 +187,8 @@ bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int32_t nReadMode) case M_SOF13: case M_SOF14: case M_SOF15: + if (itemlen < 8) + return false; process_SOFn(Data, marker); break; default: @@ -208,6 +210,9 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length) /* If it's from a digicam, and it used flash, it says so. */ m_exifinfo->Comments[0] = '\0'; /* Initial value - null string */ + if (length < 6) + return false; + ExifImageWidth = 0; { /* Check the EXIF header component */ @@ -218,6 +223,9 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length) } } + if (length < 8) + return false; + if (memcmp(CharBuf+6,"II",2) == 0){ MotorolaOrder = 0; }else{ @@ -229,6 +237,9 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length) } } + if (length < 14) + return false; + /* Check the next two values for correctness. */ if (Get16u(CharBuf+8) != 0x2a){ strcpy(m_szLastError,"Invalid Exif start (1)"); @@ -246,6 +257,7 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length) uint8_t * LastExifRefd = CharBuf; +#if 0 /* First directory starts 16 bytes in. Offsets start at 8 bytes in. */ if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd)) return false; @@ -255,6 +267,18 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length) if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd)) return false; } +#else + CSafeReader reader(CharBuf, length); + /* First directory starts 16 bytes in. Offsets start at 8 bytes in. */ + if (!ProcessExifDir2(reader.Offset(14), reader.Offset(6), length-6, m_exifinfo, &LastExifRefd)) + return false; + + /* give a chance for a second directory */ + if (FirstOffset > 8) { + if (!ProcessExifDir2(reader.Offset(14+FirstOffset-8), reader.Offset(6), length-6, m_exifinfo, &LastExifRefd)) + return false; + } +#endif /* This is how far the interesting (non thumbnail) part of the exif went. */ // int32_t ExifSettingsLength = LastExifRefd - CharBuf; @@ -692,6 +716,322 @@ bool CxImageJPG::CxExifInfo::ProcessExifDir(uint8_t * DirStart, uint8_t * Offset return true; } +bool CxImageJPG::CxExifInfo::ProcessExifDir2(CSafeReader DirStart, CSafeReader OffsetBase, unsigned ExifLength, + EXIFINFO * const m_exifinfo, uint8_t ** const LastExifRefdP, int32_t NestingLevel) +{ + int32_t de; + int32_t a; + int32_t NumDirEntries; + unsigned ThumbnailOffset = 0; + unsigned ThumbnailSize = 0; + + if (NestingLevel > 4){ + strcpy(m_szLastError,"Maximum directory nesting exceeded (corrupt exif header)"); + return false; + } + + NumDirEntries = DirStart.Check(2) ? Get16u(DirStart.GetData(0)) : 0; + + if ((DirStart.GetData(2+NumDirEntries*12+2)) > (OffsetBase.GetData(ExifLength))){ + strcpy(m_szLastError,"Illegally sized directory"); + return false; + } + + for (de=0;de= NUM_FORMATS) { + /* (-1) catches illegal zero case as unsigned underflows to positive large */ + strcpy(m_szLastError,"Illegal format code in EXIF dir"); + return false; + } + + ByteCount = Components * BytesPerFormat[Format]; + + if (ByteCount > 4){ + unsigned OffsetVal; + OffsetVal = DirEntry.Check(8, 4) ? Get32u(DirEntry.GetData(8)) : 0; + /* If its bigger than 4 bytes, the dir entry contains an offset.*/ + if (OffsetVal+ByteCount > ExifLength){ + /* Bogus pointer offset and / or bytecount value */ + strcpy(m_szLastError,"Illegal pointer offset value in EXIF."); + return false; + } + ValuePtr = OffsetBase.Offset(OffsetVal); + }else{ + /* 4 bytes or less and value is in the dir entry itself */ + ValuePtr = DirEntry.Offset(8); + } + + if (*LastExifRefdP < ValuePtr.GetData(ByteCount)){ + /* Keep track of last byte in the exif header that was + actually referenced. That way, we know where the + discardable thumbnail data begins. + */ + *LastExifRefdP = ValuePtr.GetData(ByteCount); + } + + /* Extract useful components of tag */ + switch(Tag){ + + case TAG_MAKE: + if (ValuePtr.Check(31)) strncpy(m_exifinfo->CameraMake, (char*)ValuePtr.GetData(0), 31); + break; + + case TAG_MODEL: + if (ValuePtr.Check(39)) strncpy(m_exifinfo->CameraModel, (char*)ValuePtr.GetData(0), 39); + break; + + case TAG_EXIF_VERSION: + if (ValuePtr.Check(4)) strncpy(m_exifinfo->Version,(char*)ValuePtr.GetData(0), 4); + break; + + case TAG_DATETIME_ORIGINAL: + if (ValuePtr.Check(19)) strncpy(m_exifinfo->DateTime, (char*)ValuePtr.GetData(0), 19); + break; + + case TAG_USERCOMMENT: + // Olympus has this padded with trailing spaces. Remove these first. + if (ValuePtr.Check(ByteCount)) + { + for (a=ByteCount;;){ + a--; + if (*((char*)ValuePtr.GetData(a)) == ' '){ + *((char*)ValuePtr.GetData(a)) = '\0'; + }else{ + break; + } + if (a == 0) break; + } + } + + /* Copy the comment */ + if (ValuePtr.Check(5) && memcmp(ValuePtr.GetData(0), "ASCII",5) == 0){ + for (a=5;a<10;a++){ + char c; + c = *((char*)ValuePtr.GetData(a)); + if (c != '\0' && c != ' '){ + if (ValuePtr.Check(a, 199)) + strncpy(m_exifinfo->Comments, (char*)ValuePtr.GetData(a), 199); + break; + } + } + + }else{ + if (ValuePtr.Check(199)) + strncpy(m_exifinfo->Comments, (char*)ValuePtr.GetData(0), 199); + } + break; + + case TAG_FNUMBER: + /* Simplest way of expressing aperture, so I trust it the most. + (overwrite previously computd value if there is one) + */ + m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_APERTURE: + case TAG_MAXAPERTURE: + /* More relevant info always comes earlier, so only + use this field if we don't have appropriate aperture + information yet. + */ + if (m_exifinfo->ApertureFNumber == 0){ + m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat2(ValuePtr, Format)*log(2.0f)*0.5); + } + break; + + case TAG_BRIGHTNESS: + m_exifinfo->Brightness = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_FOCALLENGTH: + /* Nice digital cameras actually save the focal length + as a function of how farthey are zoomed in. + */ + + m_exifinfo->FocalLength = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_SUBJECT_DISTANCE: + /* Inidcates the distacne the autofocus camera is focused to. + Tends to be less accurate as distance increases. + */ + m_exifinfo->Distance = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_EXPOSURETIME: + /* Simplest way of expressing exposure time, so I + trust it most. (overwrite previously computd value + if there is one) + */ + m_exifinfo->ExposureTime = + (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_SHUTTERSPEED: + /* More complicated way of expressing exposure time, + so only use this value if we don't already have it + from somewhere else. + */ + if (m_exifinfo->ExposureTime == 0){ + m_exifinfo->ExposureTime = (float) + (1/exp(ConvertAnyFormat2(ValuePtr, Format)*log(2.0f))); + } + break; + + case TAG_FLASH: + if ((int32_t)ConvertAnyFormat2(ValuePtr, Format) & 7){ + m_exifinfo->FlashUsed = 1; + }else{ + m_exifinfo->FlashUsed = 0; + } + break; + + case TAG_ORIENTATION: + m_exifinfo->Orientation = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){ + strcpy(m_szLastError,"Undefined rotation value"); + m_exifinfo->Orientation = 0; + } + break; + + case TAG_EXIF_IMAGELENGTH: + case TAG_EXIF_IMAGEWIDTH: + /* Use largest of height and width to deal with images + that have been rotated to portrait format. + */ + a = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + if (ExifImageWidth < a) ExifImageWidth = a; + break; + + case TAG_FOCALPLANEXRES: + m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_FOCALPLANEYRES: + m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_RESOLUTIONUNIT: + switch((int32_t)ConvertAnyFormat2(ValuePtr, Format)){ + case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */ + case 2: m_exifinfo->ResolutionUnit = 1.0f; break; + case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/ + case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/ + case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/ + } + break; + + case TAG_FOCALPLANEUNITS: + switch((int32_t)ConvertAnyFormat2(ValuePtr, Format)){ + case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */ + case 2: m_exifinfo->FocalplaneUnits = 1.0f; break; + case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/ + case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/ + case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/ + } + break; + + // Remaining cases contributed by: Volker C. Schoech + + case TAG_EXPOSURE_BIAS: + m_exifinfo->ExposureBias = (float) ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_WHITEBALANCE: + m_exifinfo->Whitebalance = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_METERING_MODE: + m_exifinfo->MeteringMode = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_EXPOSURE_PROGRAM: + m_exifinfo->ExposureProgram = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_ISO_EQUIVALENT: + m_exifinfo->ISOequivalent = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200; + break; + + case TAG_COMPRESSION_LEVEL: + m_exifinfo->CompressionLevel = (int32_t)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_XRESOLUTION: + m_exifinfo->Xresolution = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + case TAG_YRESOLUTION: + m_exifinfo->Yresolution = (float)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_THUMBNAIL_OFFSET: + ThumbnailOffset = (unsigned)ConvertAnyFormat2(ValuePtr, Format); + break; + + case TAG_THUMBNAIL_LENGTH: + ThumbnailSize = (unsigned)ConvertAnyFormat2(ValuePtr, Format); + break; + + } + + if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){ + unsigned Offset = ValuePtr.Check(4) ? Get32u(ValuePtr.GetData(0)) : 0; + if (Offset>8){ + if (!OffsetBase.Check(Offset)) + { + strcpy(m_szLastError,"Illegal subdirectory link"); + return false; + } + ProcessExifDir2(OffsetBase.Offset(Offset), OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel+1); + } + continue; + } + } + + + { + /* In addition to linking to subdirectories via exif tags, + there's also a potential link to another directory at the end + of each directory. This has got to be the result of a + committee! + */ + unsigned Offset; + Offset = DirStart.Check(2+12*NumDirEntries, 2) ? Get16u(DirStart.GetData(2+12*NumDirEntries)) : 0; + if (Offset){ + if (!OffsetBase.Check(Offset)) + { + strcpy(m_szLastError,"Illegal subdirectory link"); + return false; + } + ProcessExifDir2(OffsetBase.Offset(Offset), OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel+1); + } + } + + + if (ThumbnailSize && ThumbnailOffset){ + if (ThumbnailSize + ThumbnailOffset <= ExifLength){ + /* The thumbnail pointer appears to be valid. Store it. */ + m_exifinfo->ThumbnailPointer = OffsetBase.GetData(ThumbnailOffset); + m_exifinfo->ThumbnailSize = ThumbnailSize; + } + } + + return true; +} //////////////////////////////////////////////////////////////////////////////// /*-------------------------------------------------------------------------- Evaluate number, be it int32_t, rational, or float from directory. @@ -732,6 +1072,58 @@ double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int32_t Format) } return Value; } +double CxImageJPG::CxExifInfo::ConvertAnyFormat2(CSafeReader& reader, int32_t Format) +{ + double Value; + Value = 0; + + switch(Format){ + case FMT_SBYTE: + case FMT_BYTE: if (!reader.Check(1)) {return Value;} break; + case FMT_USHORT: + case FMT_SSHORT: if (!reader.Check(2)) {return Value;} break; + case FMT_ULONG: + case FMT_SLONG: if (!reader.Check(4)) {return Value;} break; + case FMT_URATIONAL: + case FMT_SRATIONAL: if (!reader.Check(8)) {return Value;} break; + case FMT_SINGLE: if (!reader.Check(sizeof(float))) {return Value;} break; + case FMT_DOUBLE: if (!reader.Check(sizeof(double))) {return Value;} break; + default: + break; + } + + void * ValuePtr = (void*)reader.GetData(0); + switch(Format){ + case FMT_SBYTE: Value = *(signed char *)ValuePtr; break; + case FMT_BYTE: Value = *(uint8_t *)ValuePtr; break; + + case FMT_USHORT: Value = Get16u(ValuePtr); break; + case FMT_ULONG: Value = Get32u(ValuePtr); break; + + case FMT_URATIONAL: + case FMT_SRATIONAL: + { + int32_t Num,Den; + Num = Get32s(ValuePtr); + Den = Get32s(4+(char *)ValuePtr); + if (Den == 0){ + Value = 0; + }else{ + Value = (double)Num/Den; + } + break; + } + + case FMT_SSHORT: Value = (int16_t)Get16u(ValuePtr); break; + case FMT_SLONG: Value = Get32s(ValuePtr); break; + + /* Not sure if this is correct (never seen float used in Exif format) + */ + case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break; + case FMT_DOUBLE: Value = *(double *)ValuePtr; break; + } + return Value; +} //////////////////////////////////////////////////////////////////////////////// void CxImageJPG::CxExifInfo::process_COM (const uint8_t * Data, int32_t length) { @@ -747,7 +1139,7 @@ void CxImageJPG::CxExifInfo::process_COM (const uint8_t * Data, int32_t length) for (a=2;a 0xFFFFFFFF) + return 0xFFFFFFFF; + return (uint32_t)size64; } //////////////////////////////////////////////////////////////////////////////// /** @@ -324,13 +328,14 @@ bool CxImage::Transfer(CxImage &from, bool bTransferFrames /*=true*/) memcpy(&info,&from.info,sizeof(CXIMAGEINFO)); pDib = from.pDib; + pDibLimit = from.pDibLimit; pSelection = from.pSelection; pAlpha = from.pAlpha; ppLayers = from.ppLayers; memset(&from.head,0,sizeof(BITMAPINFOHEADER)); memset(&from.info,0,sizeof(CXIMAGEINFO)); - from.pDib = from.pSelection = from.pAlpha = NULL; + from.pDib = from.pDibLimit = from.pSelection = from.pAlpha = NULL; from.ppLayers = NULL; if (bTransferFrames){ @@ -352,6 +357,7 @@ void CxImage::Ghost(const CxImage *from) memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER)); memcpy(&info,&from->info,sizeof(CXIMAGEINFO)); pDib = from->pDib; + pDibLimit = from->pDibLimit; pSelection = from->pSelection; pAlpha = from->pAlpha; ppLayers = from->ppLayers; diff --git a/DesktopEditor/cximage/CxImage/ximage.h b/DesktopEditor/cximage/CxImage/ximage.h index 61f8f4aa53..599ecf1af9 100644 --- a/DesktopEditor/cximage/CxImage/ximage.h +++ b/DesktopEditor/cximage/CxImage/ximage.h @@ -289,10 +289,11 @@ public: //@} /** \addtogroup Attributes */ //@{ - int32_t GetSize(); + uint32_t GetSize(); uint8_t* GetBits(uint32_t row = 0); uint8_t GetColorType(); void* GetDIB() const; + void* GetDIBLimit() const; uint32_t GetHeight() const; uint32_t GetWidth() const; uint32_t GetEffWidth() const; @@ -796,6 +797,8 @@ protected: void bihtoh(BITMAPINFOHEADER* bih); void* pDib; //contains the header, the palette, the pixels + void* pDibLimit; + BITMAPINFOHEADER head; //standard header CXIMAGEINFO info; //extended information uint8_t* pSelection; //selected region diff --git a/DesktopEditor/cximage/CxImage/ximaico.cpp b/DesktopEditor/cximage/CxImage/ximaico.cpp index 4fed96cdbc..b8729e0d60 100644 --- a/DesktopEditor/cximage/CxImage/ximaico.cpp +++ b/DesktopEditor/cximage/CxImage/ximaico.cpp @@ -95,9 +95,15 @@ bool CxImageICO::Decode(CxFile *hFile) // read the palette RGBQUAD pal[256]; if (bih.biClrUsed) - hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1); + { + uint32_t _count = bih.biClrUsed; if (_count > 256) _count = 256; + hFile->Read(pal,_count*sizeof(RGBQUAD), 1); + } else - hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1); + { + uint32_t _count = head.biClrUsed; if (_count > 256) _count = 256; + hFile->Read(pal,_count*sizeof(RGBQUAD), 1); + } SetPalette(pal,head.biClrUsed); //palette assign diff --git a/DesktopEditor/cximage/CxImage/ximainfo.cpp b/DesktopEditor/cximage/CxImage/ximainfo.cpp index e3a278c0c0..9ebd904e89 100644 --- a/DesktopEditor/cximage/CxImage/ximainfo.cpp +++ b/DesktopEditor/cximage/CxImage/ximainfo.cpp @@ -181,6 +181,10 @@ void* CxImage::GetDIB() const { return pDib; } +void* CxImage::GetDIBLimit() const +{ + return pDibLimit; +} //////////////////////////////////////////////////////////////////////////////// uint32_t CxImage::GetHeight() const { diff --git a/DesktopEditor/cximage/CxImage/ximajpg.h b/DesktopEditor/cximage/CxImage/ximajpg.h index 4cb2484a8b..418dc6ca55 100644 --- a/DesktopEditor/cximage/CxImage/ximajpg.h +++ b/DesktopEditor/cximage/CxImage/ximajpg.h @@ -101,6 +101,55 @@ typedef struct tag_Section_t{ unsigned Size; } Section_t; +public: + class CSafeReader + { + private: + uint8_t* data; + unsigned int len; + + public: + CSafeReader(uint8_t* _data = NULL, unsigned int _len = 0) + { + data = _data; + len = _len; + } + CSafeReader(const CSafeReader& src) + { + data = src.data; + len = src.len; + } + CSafeReader& operator=(const CSafeReader& src) + { + data = src.data; + len = src.len; + return *this; + } + CSafeReader Offset(unsigned int offset) + { + if (offset > len) + offset = len; + CSafeReader reader(data, len); + reader.data += offset; + reader.len -= offset; + return reader; + } + bool Check(unsigned int size) + { + if (len >= size) + return true; + return false; + } + bool Check(unsigned int offset, unsigned int size) + { + return Check(offset + size); + } + uint8_t* GetData(unsigned int offset) + { + return data + offset; + } + }; + public: EXIFINFO* m_exifinfo; char m_szLastError[256]; @@ -118,9 +167,12 @@ protected: int32_t Get32s(void * Long); uint32_t Get32u(void * Long); double ConvertAnyFormat(void * ValuePtr, int32_t Format); + double ConvertAnyFormat2(CSafeReader& reader, int32_t Format); void* FindSection(int32_t SectionType); bool ProcessExifDir(uint8_t * DirStart, uint8_t * OffsetBase, unsigned ExifLength, EXIFINFO * const pInfo, uint8_t ** const LastExifRefdP, int32_t NestingLevel=0); + bool ProcessExifDir2(CSafeReader DirStart, CSafeReader OffsetBase, unsigned ExifLength, + EXIFINFO * const pInfo, uint8_t ** const LastExifRefdP, int32_t NestingLevel=0); int32_t ExifImageWidth; int32_t MotorolaOrder; Section_t Sections[MAX_SECTIONS]; diff --git a/DesktopEditor/cximage/CxImage/ximapcx.cpp b/DesktopEditor/cximage/CxImage/ximapcx.cpp index 0a96c33ab4..b233557e02 100644 --- a/DesktopEditor/cximage/CxImage/ximapcx.cpp +++ b/DesktopEditor/cximage/CxImage/ximapcx.cpp @@ -50,6 +50,9 @@ bool CxImagePCX::Decode(CxFile *hFile) info.xDPI = pcxHeader.Hres; info.yDPI = pcxHeader.Vres; + if (Width <= 0 || Height <= 0) + cx_throw("Error: Not a PCX file"); + if (info.nEscape == -1){ head.biWidth = Width; head.biHeight= Height; @@ -76,7 +79,11 @@ bool CxImagePCX::Decode(CxFile *hFile) //Read the image and check if it's ok nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height; + uint32_t pcximage_size = nbytes; lpHead1 = pcximage = (uint8_t*)malloc(nbytes); + if (!pcximage) + cx_throw("Cancelled"); + while (nbytes > 0){ if (hFile == NULL || hFile->Eof()) cx_throw("corrupted PCX"); @@ -119,6 +126,9 @@ bool CxImagePCX::Decode(CxFile *hFile) for (uint32_t idx=0; idx127) a-=256; if (b>127) b-=256; // lab to xyz diff --git a/DesktopEditor/cximage/CxImage/xiofile.h b/DesktopEditor/cximage/CxImage/xiofile.h index 8ab5f1bfaf..e6b8334c08 100644 --- a/DesktopEditor/cximage/CxImage/xiofile.h +++ b/DesktopEditor/cximage/CxImage/xiofile.h @@ -59,9 +59,10 @@ public: return (bool)(iErr==0); } ////////////////////////////////////////////////////////// - virtual size_t Read(void *buffer, size_t size, size_t count) + virtual size_t Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL) { if (!m_fp) return 0; + clamp_buffer(buffer, size, limit_start, limit_end); return fread(buffer, size, count, m_fp); } ////////////////////////////////////////////////////////// diff --git a/DesktopEditor/cximage/CxImage/xmemfile.cpp b/DesktopEditor/cximage/CxImage/xmemfile.cpp index 42dfadef35..180184db22 100644 --- a/DesktopEditor/cximage/CxImage/xmemfile.cpp +++ b/DesktopEditor/cximage/CxImage/xmemfile.cpp @@ -45,7 +45,7 @@ uint8_t* CxMemFile::GetBuffer(bool bDetachBuffer) return m_pBuffer; } ////////////////////////////////////////////////////////// -size_t CxMemFile::Read(void *buffer, size_t size, size_t count) +size_t CxMemFile::Read(void *buffer, size_t size, size_t count, void* limit_start, void* limit_end) { if (buffer==NULL) return 0; @@ -53,7 +53,7 @@ size_t CxMemFile::Read(void *buffer, size_t size, size_t count) if (m_Position >= (int32_t)m_Size){ m_bEOF = true; return 0; - } + } int32_t nCount = (int32_t)(count*size); if (nCount == 0) return 0; diff --git a/DesktopEditor/cximage/CxImage/xmemfile.h b/DesktopEditor/cximage/CxImage/xmemfile.h index 71e00eb069..385d16b30e 100644 --- a/DesktopEditor/cximage/CxImage/xmemfile.h +++ b/DesktopEditor/cximage/CxImage/xmemfile.h @@ -14,7 +14,7 @@ public: uint8_t* GetBuffer(bool bDetachBuffer = true); virtual bool Close(); - virtual size_t Read(void *buffer, size_t size, size_t count); + virtual size_t Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL); virtual size_t Write(const void *buffer, size_t size, size_t count); virtual bool Seek(int32_t offset, int32_t origin); virtual int32_t Tell(); diff --git a/DesktopEditor/cximage/jasper/jpc/jpc_dec.c b/DesktopEditor/cximage/jasper/jpc/jpc_dec.c index fa72a0e82c..df986bcc66 100644 --- a/DesktopEditor/cximage/jasper/jpc/jpc_dec.c +++ b/DesktopEditor/cximage/jasper/jpc/jpc_dec.c @@ -2171,7 +2171,12 @@ int jpc_ppxstab_insert(jpc_ppxstab_t *tab, jpc_ppxstabent_t *ent) int inspt; int i; - for (i = 0; i < tab->numents; ++i) { + // check on MAX_INT + int correct_num_ents = tab->numents; + if (correct_num_ents > 0x7FFFFFFE) + correct_num_ents = 0x7FFFFFFE; + + for (i = 0; i < correct_num_ents; ++i) { if (tab->ents[i]->ind > ent->ind) { break; } diff --git a/DesktopEditor/cximage/raw/libdcr.c b/DesktopEditor/cximage/raw/libdcr.c index e671e47c66..73f4ab3758 100644 --- a/DesktopEditor/cximage/raw/libdcr.c +++ b/DesktopEditor/cximage/raw/libdcr.c @@ -3518,20 +3518,21 @@ void DCR_CLASS dcr_cam_xyz_coeff (DCRAW* p, double cam_xyz[4][3]) { double cam_rgb[4][3], inverse[4][3], num; int i, j, k; - - for (i=0; i < p->colors; i++) /* Multiply out XYZ colorspace */ + int max_colors = p->colors; + if (max_colors > 4) max_colors = 4; + for (i=0; i < max_colors; i++) /* Multiply out XYZ colorspace */ for (j=0; j < 3; j++) for (cam_rgb[i][j] = k=0; k < 3; k++) cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j]; - for (i=0; i < p->colors; i++) { /* Normalize cam_rgb so that */ + for (i=0; i < max_colors; i++) { /* Normalize cam_rgb so that */ for (num=j=0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */ num += cam_rgb[i][j]; for (j=0; j < 3; j++) cam_rgb[i][j] /= num; p->pre_mul[i] = 1 / (float)num; } - dcr_pseudoinverse (cam_rgb, inverse, p->colors); + dcr_pseudoinverse (cam_rgb, inverse, max_colors); for (p->raw_color = i=0; i < 3; i++) for (j=0; j < p->colors; j++) p->rgb_cam[i][j] = (float)inverse[j][i]; @@ -5391,9 +5392,12 @@ void DCR_CLASS dcr_parse_tiff (DCRAW* p, int base) p->tiff_ifd[raw].phint == 1) p->is_raw = 0; if (p->tiff_bps == 8 && p->tiff_samples == 4) p->is_raw = 0; for (i=0; i < (int)p->tiff_nifds; i++) + { + int sqr_1 = SQR(p->tiff_ifd[i].bps+1); if (sqr_1 == 0) sqr_1 = 1; + int sqr_2 = SQR(p->thumb_misc+1); if (sqr_2 == 0) sqr_2 = 1; if (i != raw && p->tiff_ifd[i].samples == max_samp && - p->tiff_ifd[i].width * p->tiff_ifd[i].height / SQR(p->tiff_ifd[i].bps+1) > - (int)(p->thumb_width * p->thumb_height / SQR(p->thumb_misc+1))) { + p->tiff_ifd[i].width * p->tiff_ifd[i].height / sqr_1 > + (int)(p->thumb_width * p->thumb_height / sqr_2)) { p->thumb_width = p->tiff_ifd[i].width; p->thumb_height = p->tiff_ifd[i].height; p->thumb_offset = p->tiff_ifd[i].offset; @@ -5401,6 +5405,7 @@ void DCR_CLASS dcr_parse_tiff (DCRAW* p, int base) p->thumb_misc = p->tiff_ifd[i].bps; thm = i; } + } if (thm >= 0) { p->thumb_misc |= p->tiff_ifd[thm].samples << 5; switch (p->tiff_ifd[thm].comp) { @@ -5845,10 +5850,16 @@ void DCR_CLASS dcr_parse_riff(DCRAW* p) { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; struct tm t; + if (dcr_feof(p->obj_)) + { + fprintf (stderr,_("Unexpected end of file\n")); + return; + } + p->order = 0x4949; dcr_fread(p->obj_, tag, 4, 1); size = dcr_get4(p); - end = dcr_ftell(p->obj_) + size; + end = dcr_ftell(p->obj_) + size; if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) { dcr_get4(p); while (dcr_ftell(p->obj_)+7 < (long)end) diff --git a/DesktopEditor/cximage/tiff/tif_dirread.c b/DesktopEditor/cximage/tiff/tif_dirread.c index 907b53188c..51d20a3b96 100644 --- a/DesktopEditor/cximage/tiff/tif_dirread.c +++ b/DesktopEditor/cximage/tiff/tif_dirread.c @@ -205,7 +205,7 @@ TIFFReadDirectory(TIFF* tif) && fix < tif->tif_nfields) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; - fip = tif->tif_fieldinfo[++fix]; + ++fix; fip = (fix >= tif->tif_nfields) ? 0 : tif->tif_fieldinfo[fix]; if (fix >= tif->tif_nfields || fip->field_tag != dp->tdir_tag) { TIFFWarningExt(tif->tif_clientdata, module, @@ -333,7 +333,7 @@ TIFFReadDirectory(TIFF* tif) && fix < tif->tif_nfields) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; - fip = tif->tif_fieldinfo[++fix]; + ++fix; fip = (fix >= tif->tif_nfields) ? 0 : tif->tif_fieldinfo[fix]; if (fix >= tif->tif_nfields || fip->field_tag != dp->tdir_tag) { TIFFWarningExt(tif->tif_clientdata, module, @@ -887,7 +887,7 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, && fix < tif->tif_nfields) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; - fip = tif->tif_fieldinfo[++fix]; + ++fix; fip = (fix >= tif->tif_nfields) ? 0 : tif->tif_fieldinfo[fix]; if (fix >= tif->tif_nfields || fip->field_tag != dp->tdir_tag) { TIFFWarningExt(tif->tif_clientdata, module, diff --git a/DesktopEditor/cximage/tiff/tif_ojpeg.c b/DesktopEditor/cximage/tiff/tif_ojpeg.c index 793de83616..dea897484f 100644 --- a/DesktopEditor/cximage/tiff/tif_ojpeg.c +++ b/DesktopEditor/cximage/tiff/tif_ojpeg.c @@ -1920,7 +1920,9 @@ OJPEGReadBufferFill(OJPEGState* sp) sp->in_buffer_file_pos=0; else { - sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile]; + sp->in_buffer_file_togo=0; + if (sp->tif->tif_dir.td_stripbytecount) + sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile]; if (sp->in_buffer_file_togo==0) sp->in_buffer_file_pos=0; else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) diff --git a/DesktopEditor/fontengine/fontconverter/FontFileBase.h b/DesktopEditor/fontengine/fontconverter/FontFileBase.h index f0e4299dbd..6089793d0c 100644 --- a/DesktopEditor/fontengine/fontconverter/FontFileBase.h +++ b/DesktopEditor/fontengine/fontconverter/FontFileBase.h @@ -61,9 +61,9 @@ namespace NSFontConverter CFontFileBase(char *sFile, int nLen, bool bFreeFileData) { m_sFileData = m_sFile = (unsigned char *)sFile; - m_nLen = nLen; - m_bFreeFileData = bFreeFileData; + m_nLen = (nLen > 0) ? 0 : (unsigned int)nLen; m_nPos = 0; + m_bFreeFileData = bFreeFileData; } void Reset() @@ -94,11 +94,11 @@ namespace NSFontConverter // S = signed / U = unsigned // 8/16/32/Var = word length, in bytes // BE = big endian - int GetS8 (int nPos, bool *pbSuccess) + int GetS8 (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos >= m_nLen ) + if ( nPos >= m_nLen ) { *pbSuccess = false; return 0; @@ -109,10 +109,10 @@ namespace NSFontConverter return nRes; } - int GetU8 (int nPos, bool *pbSuccess) + int GetU8 (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos >= m_nLen ) + if ( nPos >= m_nLen ) { *pbSuccess = false; return 0; @@ -120,11 +120,11 @@ namespace NSFontConverter return m_sFile[ nPos ]; } - int GetS16BE (int nPos, bool *pbSuccess) + int GetS16BE (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos + 1 >= m_nLen ) + if ( m_nLen < 2 || nPos > (m_nLen - 2) ) { *pbSuccess = false; return 0; @@ -136,11 +136,11 @@ namespace NSFontConverter return nRes; } - int GetU16BE (int nPos, bool *pbSuccess) + int GetU16BE (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos + 1 >= m_nLen) + if ( m_nLen < 2 || nPos > (m_nLen - 2) ) { *pbSuccess = false; return 0; @@ -150,11 +150,11 @@ namespace NSFontConverter return nRes; } - int GetS32BE (int nPos, bool *pbSuccess) + int GetS32BE (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos + 3 >= m_nLen ) + if ( m_nLen < 4 || nPos > (m_nLen - 4) ) { *pbSuccess = false; return 0; @@ -169,11 +169,11 @@ namespace NSFontConverter return nRes; } - unsigned int GetU32BE (int nPos, bool *pbSuccess) + unsigned int GetU32BE (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos + 3 >= m_nLen ) + if ( m_nLen < 4 || nPos > (m_nLen - 4) ) { *pbSuccess = false; return 0; @@ -184,11 +184,11 @@ namespace NSFontConverter nRes = (nRes << 8) + m_sFile[nPos + 3]; return nRes; } - unsigned int GetU32LE (int nPos, bool *pbSuccess) + unsigned int GetU32LE (const unsigned int& nPos, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos + 3 >= m_nLen ) + if ( m_nLen < 4 || nPos > (m_nLen - 4) ) { *pbSuccess = false; return 0; @@ -199,11 +199,11 @@ namespace NSFontConverter nRes = (nRes << 8) + m_sFile[nPos + 0]; return nRes; } - unsigned int GetUVarBE(int nPos, int nSize, bool *pbSuccess) + unsigned int GetUVarBE(const unsigned int& nPos, const unsigned int& nSize, bool *pbSuccess) { //*pbSuccess = true; - if ( nPos < 0 || nPos + nSize > m_nLen ) + if ( m_nLen < nSize || nPos > (m_nLen - nSize) ) { *pbSuccess = false; return 0; @@ -215,9 +215,9 @@ namespace NSFontConverter return nRes; } - bool CheckRegion(int nPos, int nSize) + bool CheckRegion(const unsigned int& nPos, const unsigned int& nSize) { - return (nPos >= 0 && nPos + nSize >= nPos && nPos + nSize <= m_nLen); + return (m_nLen >= nSize && nPos <= (m_nLen - nSize)); } int ReadS8 (bool *pbSuccess) { @@ -239,10 +239,15 @@ namespace NSFontConverter m_nPos += 4; return unResult; } - int Read(void* pDestBuffer, int nSize) + int Read(void* pDestBuffer, unsigned int nSize) { - if ( m_nPos + nSize >= m_nLen ) - nSize = m_nLen - m_nPos - 1; + if (m_nPos >= m_nLen) + nSize = 0; + else if (nSize > (m_nLen - m_nPos)) + nSize = m_nLen - m_nPos; + + if (0 == nSize) + return nSize; memcpy( pDestBuffer, (m_sFile + m_nPos), nSize ); m_nPos += nSize; @@ -254,10 +259,9 @@ namespace NSFontConverter unsigned char *m_sFileData; unsigned char *m_sFile; - int m_nLen; + unsigned int m_nLen; + unsigned int m_nPos; bool m_bFreeFileData; - int m_nPos; - }; } diff --git a/DesktopEditor/fontengine/fontconverter/FontFileType1.cpp b/DesktopEditor/fontengine/fontconverter/FontFileType1.cpp index fb9d062a62..b2df678b14 100644 --- a/DesktopEditor/fontengine/fontconverter/FontFileType1.cpp +++ b/DesktopEditor/fontengine/fontconverter/FontFileType1.cpp @@ -397,6 +397,7 @@ namespace NSFontConverter char nChar = *pTemp; *pTemp = '\0'; nCode = atoi( pCur ); + if (nCode < 0) nCode = 0; *pTemp = nChar; if ( nCode == 8 && *pTemp == '#') { @@ -612,7 +613,7 @@ namespace NSFontConverter sToken.clear(); sGlyph.clear(); - while ( ( nChar = sEexec[++nIndex] ) != ' ' ) + while ( nIndex < nEexecLen && ( nChar = sEexec[++nIndex] ) != ' ' ) sGlyph.push_back( (wchar_t)nChar ); } } @@ -632,13 +633,16 @@ namespace NSFontConverter // (пробел, таб, перенос каретки или перенос строки). unsigned char *sCur = (unsigned char*)(*ppEexecBuffer); while( sCur < (unsigned char*)(*ppEexecBuffer) + nLen && ( ' ' == *sCur || '\t' == *sCur || '\r' == *sCur || '\n' == *sCur ) ) + { ++sCur; + --nLen; + } // Теперь нам надо определить в каком формате у нас данные: ASKII или бинарные данные. // Если первые четыре байта являются шестнадцатиричными символами, значит, кодировка ASCII. bool bASCII = false; - if ( isxdigit( sCur[0] ) && isxdigit( sCur[1] ) && isxdigit( sCur[2] ) && isxdigit( sCur[3] ) ) + if ( nLen > 3 && isxdigit( sCur[0] ) && isxdigit( sCur[1] ) && isxdigit( sCur[2] ) && isxdigit( sCur[3] ) ) bASCII = true; if ( bASCII ) @@ -656,7 +660,7 @@ namespace NSFontConverter int nChar = 0; unsigned char *sBuffer = NULL; - int nBufLen = 0; + unsigned int nBufLen = 0; while ( nBlockType != PFB_DONE ) { diff --git a/DesktopEditor/fontengine/fontconverter/FontFileType1.h b/DesktopEditor/fontengine/fontconverter/FontFileType1.h index 7f2aa71230..a126b91a15 100644 --- a/DesktopEditor/fontengine/fontconverter/FontFileType1.h +++ b/DesktopEditor/fontengine/fontconverter/FontFileType1.h @@ -259,6 +259,8 @@ namespace NSFontConverter } sBuffer[nBufPos++] = unChar; + if (nBufPos >= c_nNumLimit) + break; } if ( 0 != sBuffer[0] && nCount > 0 ) diff --git a/DesktopEditor/fontengine/fontconverter/FontFileType1C.cpp b/DesktopEditor/fontengine/fontconverter/FontFileType1C.cpp index 7165e48fdd..620aa073fc 100644 --- a/DesktopEditor/fontengine/fontconverter/FontFileType1C.cpp +++ b/DesktopEditor/fontengine/fontconverter/FontFileType1C.cpp @@ -2888,15 +2888,21 @@ namespace NSFontConverter if (m_oTopDict.nCharsetOffset == 0) { m_pnCharset = c_arrnFontFileType1CISOAdobeCharset; + if (m_nGlyphsCount > 229) + m_nGlyphsCount = 229; } else if (m_oTopDict.nCharsetOffset == 1) { m_pnCharset = c_arrnFontFileType1CExpertCharset; - } + if (m_nGlyphsCount > 166) + m_nGlyphsCount = 166; + } else if (m_oTopDict.nCharsetOffset == 2) { m_pnCharset = c_arrnFontFileType1CExpertSubsetCharset; - } + if (m_nGlyphsCount > 87) + m_nGlyphsCount = 87; + } else { m_pnCharset = (unsigned short *)MemUtilsMallocArray( m_nGlyphsCount, sizeof(unsigned short));