@@ -285,7 +285,7 @@ struct LodePNGICC {
285285
286286 // Parameters of a tone reproduction curve, either with a power law formulaa or with a lookup table.
287287 struct Curve {
288- int type; // 0=linear, 1=lut, 2 = simple gamma, 3-6 = parametric (matches ICC parametric types 1-4)
288+ unsigned type; // 0=linear, 1=lut, 2 = simple gamma, 3-6 = parametric (matches ICC parametric types 1-4)
289289 std::vector<float > lut; // for type 1
290290 float gamma; // for type 2 and more
291291 float a, b, c, d, e, f; // for type 3-7
@@ -419,7 +419,9 @@ static unsigned parseICC(LodePNGICC* icc, const unsigned char* data, size_t size
419419 pos += 4 ;
420420 size_t offset = decodeICCUint32 (data, size, &pos);
421421 unsigned tagsize = decodeICCUint32 (data, size, &pos);
422- if (pos >= size || offset + tagsize > size) return 1 ;
422+ if (pos >= size || offset >= size) return 1 ;
423+ if (offset + tagsize > size) return 1 ;
424+ if (tagsize < 8 ) return 1 ;
423425
424426 if (isICCword (data, size, namepos, " wtpt" )) {
425427 offset += 8 ; // skip tag and reserved
@@ -455,12 +457,12 @@ static unsigned parseICC(LodePNGICC* icc, const unsigned char* data, size_t size
455457 isICCword (data, size, namepos, " gTRC" ) ||
456458 isICCword (data, size, namepos, " bTRC" ) ||
457459 isICCword (data, size, namepos, " kTRC" )) {
460+ char c = (char )data[namepos];
461+ int channel = (c == ' b' ) ? 2 : (c == ' g' ? 1 : 0 );
462+ // "curv": linear, gamma power or LUT
458463 if (isICCword (data, size, offset, " curv" )) {
459464 icc->has_trc = true ;
460- char c = (char )data[namepos];
461- int channel = (c == ' b' ) ? 2 : (c == ' g' ? 1 : 0 );
462465 LodePNGICC::Curve* trc = &icc->trc [channel];
463- // TODO: set type to other things if it's not LUT
464466 offset += 8 ; // skip tag "curv" and reserved
465467 size_t count = decodeICCUint32 (data, size, &offset);
466468 if (count == 0 ) {
@@ -477,7 +479,37 @@ static unsigned parseICC(LodePNGICC* icc, const unsigned char* data, size_t size
477479 }
478480 }
479481 }
482+ // "para": parametric formula with gamma power, multipliers, biases and comparison point
483+ // TODO: test this on a realistic sample
484+ if (isICCword (data, size, offset, " para" )) {
485+ icc->has_trc = true ;
486+ LodePNGICC::Curve* trc = &icc->trc [channel];
487+ offset += 8 ; // skip tag "para" and reserved
488+ unsigned type = decodeICCUint16 (data, size, &offset);
489+ offset += 2 ;
490+ if (type > 4 ) return 1 ; // unknown parametric curve type
491+ trc->type = type + 2 ;
492+ trc->gamma = decodeICC15Fixed16 (data, size, &offset);
493+ if (type >= 1 ) {
494+ trc->a = decodeICC15Fixed16 (data, size, &offset);
495+ trc->b = decodeICC15Fixed16 (data, size, &offset);
496+ }
497+ if (type >= 2 ) {
498+ trc->c = decodeICC15Fixed16 (data, size, &offset);
499+ }
500+ if (type >= 3 ) {
501+ trc->d = decodeICC15Fixed16 (data, size, &offset);
502+ }
503+ if (type == 4 ) {
504+ trc->e = decodeICC15Fixed16 (data, size, &offset);
505+ trc->f = decodeICC15Fixed16 (data, size, &offset);
506+ }
507+ }
508+ // TODO: verify: does the "chrm" tag participate in computation so should be parsed?
480509 }
510+ // Return error if any parse went beyond the filesize. Note that the
511+ // parsing itself was always safe since it bound-checks inside.
512+ if (offset > size) return 1 ;
481513 }
482514
483515 return 0 ;
0 commit comments