Skip to content

Commit d7a6ab7

Browse files
authored
Merge pull request #49 from lordnn/master
Fixed some CVEs
2 parents 6534ee5 + 57e6f6e commit d7a6ab7

5 files changed

Lines changed: 71 additions & 82 deletions

File tree

3rdParty/LibJXR/jxrgluelib/JXRMeta.c

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -246,33 +246,35 @@ ERR BufferCalcIFDSize(const U8* pbdata, size_t cbdata, U32 ofsifd, U8 endian, U3
246246
}
247247

248248

249-
ERR StreamCalcIFDSize(struct WMPStream* pWS, U32 uIFDOfs, U32 *pcbifd)
249+
static ERR StreamCalcIFDSizePrivate(struct WMPStream* pWS, U32 uIFDOfs, U32 *pcbifd, U32 rcnt)
250250
{
251251
ERR err = WMP_errSuccess;
252252
size_t offCurPos = 0;
253253
Bool GetPosOK = FALSE;
254-
U16 cDir;
255-
U32 i;
256-
U32 ofsdir;
257-
U32 cbifd = 0;
254+
U16 cDir = 0;
258255
U32 cbEXIFIFD = 0;
259256
U32 cbGPSInfoIFD = 0;
260257
U32 cbInteroperabilityIFD = 0;
261258

259+
// sanity check: avoid infinite recursion
260+
if (rcnt > 10) {
261+
Call(WMP_errFail);
262+
}
263+
262264
*pcbifd = 0;
263265
Call(pWS->GetPos(pWS, &offCurPos));
264266
GetPosOK = TRUE;
265267

266268
Call(GetUShort(pWS, uIFDOfs, &cDir));
267-
cbifd = sizeof(U16) + cDir * SizeofIFDEntry + sizeof(U32);
268-
ofsdir = uIFDOfs + sizeof(U16);
269-
for ( i = 0; i < cDir; i++ )
269+
U32 cbifd = sizeof(U16) + cDir * SizeofIFDEntry + sizeof(U32);
270+
U32 ofsdir = uIFDOfs + sizeof(U16);
271+
for (U16 i = 0; i < cDir; i++ )
270272
{
271-
U16 tag;
272-
U16 type;
273-
U32 count;
274-
U32 value;
275-
U32 datasize;
273+
U16 tag = 0;
274+
U16 type = 0;
275+
U32 count = 0;
276+
U32 value = 0;
277+
U32 datasize = 0;
276278

277279
Call(GetUShort(pWS, ofsdir, &tag));
278280
Call(GetUShort(pWS, ofsdir + sizeof(U16), &type));
@@ -281,39 +283,48 @@ ERR StreamCalcIFDSize(struct WMPStream* pWS, U32 uIFDOfs, U32 *pcbifd)
281283
FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errUnsupportedFormat);
282284
if ( tag == WMP_tagEXIFMetadata )
283285
{
284-
Call(StreamCalcIFDSize(pWS, value, &cbEXIFIFD));
286+
Call(StreamCalcIFDSizePrivate(pWS, value, &cbEXIFIFD, rcnt + 1));
285287
}
286288
else if ( tag == WMP_tagGPSInfoMetadata )
287289
{
288-
Call(StreamCalcIFDSize(pWS, value, &cbGPSInfoIFD));
290+
Call(StreamCalcIFDSizePrivate(pWS, value, &cbGPSInfoIFD, rcnt + 1));
289291
}
290292
else if ( tag == WMP_tagInteroperabilityIFD )
291293
{
292-
Call(StreamCalcIFDSize(pWS, value, &cbInteroperabilityIFD));
294+
Call(StreamCalcIFDSizePrivate(pWS, value, &cbInteroperabilityIFD, rcnt + 1));
293295
}
294296
else
295297
{
296298
datasize = IFDEntryTypeSizes[type] * count;
297-
if ( datasize > 4 )
299+
if (datasize > 4) {
298300
cbifd += datasize;
301+
}
299302
}
300303
ofsdir += SizeofIFDEntry;
301304
}
302-
if ( cbEXIFIFD != 0 )
303-
cbifd += ( cbifd & 1 ) + cbEXIFIFD;
304-
if ( cbGPSInfoIFD != 0 )
305-
cbifd += ( cbifd & 1 ) + cbGPSInfoIFD;
306-
if ( cbInteroperabilityIFD != 0 )
307-
cbifd += ( cbifd & 1 ) + cbInteroperabilityIFD;
305+
if (cbEXIFIFD != 0) {
306+
cbifd += (cbifd & 1) + cbEXIFIFD;
307+
}
308+
if (cbGPSInfoIFD != 0) {
309+
cbifd += (cbifd & 1) + cbGPSInfoIFD;
310+
}
311+
if (cbInteroperabilityIFD != 0) {
312+
cbifd += (cbifd & 1) + cbInteroperabilityIFD;
313+
}
308314
*pcbifd = cbifd;
309315

310316
Cleanup:
311-
if ( GetPosOK )
312-
Call(pWS->SetPos(pWS, offCurPos));
317+
if (GetPosOK && WMP_errSuccess == err) {
318+
err = pWS->SetPos(pWS, offCurPos);
319+
}
313320
return ( err );
314321
}
315322

316323

324+
ERR StreamCalcIFDSize(struct WMPStream *pWS, U32 uIFDOfs, U32 *pcbifd)
325+
{
326+
return StreamCalcIFDSizePrivate(pWS, uIFDOfs, pcbifd, 0);
327+
}
317328

318329
// src IFD copied to dst IFD with any nested IFD's
319330
// src IFD is arbitrary endian, arbitrary data arrangement
@@ -322,28 +333,23 @@ ERR StreamCalcIFDSize(struct WMPStream* pWS, U32 uIFDOfs, U32 *pcbifd)
322333
ERR BufferCopyIFD(const U8* pbsrc, U32 cbsrc, U32 ofssrc, U8 endian, U8* pbdst, U32 cbdst, U32* pofsdst)
323334
{
324335
ERR err = WMP_errSuccess;
325-
U16 cDir;
326-
U16 i;
336+
U16 cDir = 0;
327337
U16 ofsEXIFIFDEntry = 0;
328338
U16 ofsGPSInfoIFDEntry = 0;
329339
U16 ofsInteroperabilityIFDEntry = 0;
330340
U32 ofsEXIFIFD = 0;
331341
U32 ofsGPSInfoIFD = 0;
332342
U32 ofsInteroperabilityIFD = 0;
333-
U32 ofsdstnextdata;
334343
U32 ofsdst = *pofsdst;
335-
U32 ofssrcdir;
336-
U32 ofsdstdir;
337-
U32 ofsnextifd;
338344

339345
Call(getbfwe(pbsrc, cbsrc, ofssrc, &cDir, endian));
340346
Call(setbfw(pbdst, cbdst, ofsdst, cDir));
341-
ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir;
342-
ofsdstnextdata = ofsnextifd + sizeof(U32);
347+
U32 ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir;
348+
U32 ofsdstnextdata = ofsnextifd + sizeof(U32);
343349

344-
ofssrcdir = ofssrc + sizeof(U16);
345-
ofsdstdir = ofsdst + sizeof(U16);
346-
for ( i = 0; i < cDir; i++ )
350+
U32 ofssrcdir = ofssrc + sizeof(U16);
351+
U32 ofsdstdir = ofsdst + sizeof(U16);
352+
for (U16 i = 0; i < cDir; i++ )
347353
{
348354
U16 tag;
349355
U16 type;
@@ -476,32 +482,27 @@ ERR StreamCopyIFD(struct WMPStream* pWS, U32 ofssrc, U8* pbdst, U32 cbdst, U32*
476482
ERR err = WMP_errSuccess;
477483
size_t offCurPos = 0;
478484
Bool GetPosOK = FALSE;
479-
U16 cDir;
480-
U16 i;
485+
U16 cDir = 0;
481486
U16 ofsEXIFIFDEntry = 0;
482487
U16 ofsGPSInfoIFDEntry = 0;
483488
U16 ofsInteroperabilityIFDEntry = 0;
484489
U32 ofsEXIFIFD = 0;
485490
U32 ofsGPSInfoIFD = 0;
486491
U32 ofsInteroperabilityIFD = 0;
487-
U32 ofsdstnextdata;
488492
U32 ofsdst = *pofsdst;
489-
U32 ofssrcdir;
490-
U32 ofsdstdir;
491-
U32 ofsnextifd;
492493

493494
Call(pWS->GetPos(pWS, &offCurPos));
494495
GetPosOK = TRUE;
495496

496497
Call(GetUShort(pWS, ofssrc, &cDir));
497498
Call(setbfw(pbdst, cbdst, ofsdst, cDir));
498499

499-
ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir;
500-
ofsdstnextdata = ofsnextifd + sizeof(U32);
500+
U32 ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir;
501+
U32 ofsdstnextdata = ofsnextifd + sizeof(U32);
501502

502-
ofssrcdir = ofssrc + sizeof(U16);
503-
ofsdstdir = ofsdst + sizeof(U16);
504-
for ( i = 0; i < cDir; i++ )
503+
U32 ofssrcdir = ofssrc + sizeof(U16);
504+
U32 ofsdstdir = ofsdst + sizeof(U16);
505+
for (U16 i = 0; i < cDir; i++ )
505506
{
506507
U16 tag;
507508
U16 type;
@@ -579,8 +580,9 @@ ERR StreamCopyIFD(struct WMPStream* pWS, U32 ofssrc, U8* pbdst, U32 cbdst, U32*
579580
*pofsdst = ofsdstnextdata;
580581

581582
Cleanup:
582-
if ( GetPosOK )
583+
if (GetPosOK) {
583584
Call(pWS->SetPos(pWS, offCurPos));
585+
}
584586
return err;
585587
}
586588

Source/Plugins/PSDParser.cpp

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,41 +1319,36 @@ void psdParser::ReadImageLine(uint8_t* dst, const uint8_t* src, unsigned lineSiz
13191319
}
13201320
}
13211321

1322-
void psdParser::UnpackRLE(uint8_t* line, const uint8_t* rle_line, const uint8_t* line_end, unsigned srcSize) {
1323-
while (srcSize > 1) {
1324-
if (line >= line_end) {
1325-
return;
1326-
}
1322+
static void UnpackRLE(uint8_t* line, const uint8_t* rle_line, unsigned dstSize, unsigned srcSize) {
1323+
while (srcSize > 1 && dstSize > 0) {
13271324

1328-
const uint8_t len_byte = *rle_line++;
1329-
srcSize--;
1325+
unsigned len = *rle_line++;
1326+
--srcSize;
13301327

13311328
// NOTE len is signed byte in PackBits RLE
13321329

1333-
if ( len_byte < 128 ) { //<- MSB is not set
1330+
if (len < 128) { //<- MSB is not set
13341331
// uncompressed packet
13351332

1336-
// (len + 1) bytes of data are copied
1337-
const uint32_t len = std::min(static_cast<uint32_t>(len_byte + 1), srcSize);
1338-
1339-
// assert we don't write beyound eol
1340-
memcpy(line, rle_line, line + len > line_end ? line_end - line : len);
1333+
// assert we don't write beyound eol
1334+
len = std::min({ len + 1, dstSize, srcSize });
1335+
memcpy(line, rle_line, len);
13411336
line += len;
13421337
rle_line += len;
13431338
srcSize -= len;
1339+
dstSize -= len;
13441340
}
1345-
else if ( len_byte > 128 ) { //< MSB is set
1341+
else if (len > 128 ) { //< MSB is set
13461342
// RLE compressed packet
13471343

13481344
// One byte of data is repeated (-len + 1) times
13491345

1350-
// same as (-len + 1) & 0xFF
1351-
const uint32_t len = (len_byte ^ 0xFF) + 2;
1352-
1353-
// assert we don't write beyound eol
1354-
memset(line, *rle_line++, line + len > line_end ? line_end - line : len);
1346+
// assert we don't write beyound eol
1347+
len = std::min((len ^ 0xFF) + 2, dstSize);
1348+
memset(line, *rle_line++, len);
13551349
line += len;
1356-
srcSize--;
1350+
--srcSize;
1351+
dstSize -= len;
13571352
}
13581353
else {
13591354
// 128 == len
@@ -1553,16 +1548,7 @@ FIBITMAP* psdParser::ReadImageData(FreeImageIO* io, fi_handle handle) {
15531548
#endif
15541549
}
15551550

1556-
uint32_t largestRLELine = 0;
1557-
for (unsigned ch = 0; ch < nChannels; ++ch) {
1558-
for (unsigned h = 0; h < nHeight; ++h) {
1559-
const unsigned index = ch * nHeight + h;
1560-
1561-
if (largestRLELine < rleLineSizeList[index]) {
1562-
largestRLELine = rleLineSizeList[index];
1563-
}
1564-
}
1565-
}
1551+
const auto largestRLELine = *std::max_element(rleLineSizeList.get(), rleLineSizeList.get() + nChannels * nHeight);
15661552

15671553
auto rle_line_start = std::make_unique<uint8_t[]>(largestRLELine);
15681554

@@ -1572,7 +1558,6 @@ FIBITMAP* psdParser::ReadImageData(FreeImageIO* io, fi_handle handle) {
15721558
// @todo write to extra channels
15731559
break;
15741560
}
1575-
const uint8_t* const line_end = line_start.get() + lineSize;
15761561

15771562
const unsigned channelOffset = GetChannelOffset(bitmap, ch) * bytes;
15781563

@@ -1588,7 +1573,7 @@ FIBITMAP* psdParser::ReadImageData(FreeImageIO* io, fi_handle handle) {
15881573

15891574
// - write line to destination -
15901575

1591-
UnpackRLE(line_start.get(), rle_line_start.get(), line_end, rleLineSize);
1576+
UnpackRLE(line_start.get(), rle_line_start.get(), lineSize, rleLineSize);
15921577
ReadImageLine(dst_line_start, line_start.get(), lineSize, dstBpp, bytes);
15931578
}//< h
15941579
}//< ch

Source/Plugins/PSDParser.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,6 @@ class psdParser {
316316
/** Actually ignore it */
317317
bool ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle);
318318
void ReadImageLine(uint8_t* dst, const uint8_t* src, unsigned lineSize, unsigned dstBpp, unsigned bytes);
319-
void UnpackRLE(uint8_t* dst, const uint8_t* src, const uint8_t* dst_end, unsigned srcSize);
320319
FIBITMAP* ReadImageData(FreeImageIO *io, fi_handle handle);
321320
bool WriteLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle);
322321
void WriteImageLine(uint8_t* dst, const uint8_t* src, unsigned lineSize, unsigned srcBpp, unsigned bytes);

Source/Plugins/PluginHDR.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,9 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
630630
if (!rgbe_ReadHeader(io, handle, &width, &height, &header_info)) {
631631
return nullptr;
632632
}
633+
if (width > 65500 || height > 65500) {
634+
throw FI_MSG_ERROR_DIB_MEMORY;
635+
}
633636

634637
// allocate a RGBF image
635638
std::unique_ptr<FIBITMAP, decltype(&FreeImage_Unload)> dib(FreeImage_AllocateHeaderT(header_only, FIT_RGBF, width, height), &FreeImage_Unload);

Source/Plugins/PluginTIFF.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ static FIBITMAP*
386386
CreateImageType(FIBOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16_t bitspersample, uint16_t samplesperpixel) {
387387
FIBITMAP *dib{};
388388

389-
if ((width < 0) || (height < 0)) {
389+
if ((width < 0) || (height < 0) || (4 < samplesperpixel)) {
390390
// check for malicious images
391391
return nullptr;
392392
}

0 commit comments

Comments
 (0)