From be25a63be953dbfeef41cfec42550739ba74ea63 Mon Sep 17 00:00:00 2001 From: Marti Maria Date: Wed, 7 Sep 2022 19:03:11 +0200 Subject: sanitize cgats parser I don't know why people keeps fuzzing this code, but they do, and then they make a lot of noise. So let's make it less permissive and abort early when some wrong characters are found. I apologize if someone got hurt in the process. Otherwise this is harmless because is not used on ICC profile handling. --- src/cmscgats.c | 79 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/src/cmscgats.c b/src/cmscgats.c index b59eafd..845c18a 100644 --- a/src/cmscgats.c +++ b/src/cmscgats.c @@ -839,6 +839,7 @@ void InSymbol(cmsIT8* it8) if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0) { SynError(it8, "Invalid hexadecimal number"); + it8->sy = SEOF; return; } @@ -860,6 +861,7 @@ void InSymbol(cmsIT8* it8) if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0) { SynError(it8, "Invalid binary number"); + it8->sy = SEOF; return; } @@ -928,13 +930,9 @@ void InSymbol(cmsIT8* it8) } else switch ((int) it8->ch) { - - // EOF marker -- ignore it - case '\x1a': - NextCh(it8); - break; - + // Eof stream markers + case '\x1a': case 0: case -1: it8->sy = SEOF; @@ -974,6 +972,7 @@ void InSymbol(cmsIT8* it8) default: SynError(it8, "Unrecognized character: 0x%x", it8 ->ch); + it8->sy = SEOF; return; } @@ -988,11 +987,16 @@ void InSymbol(cmsIT8* it8) if(it8 -> IncludeSP >= (MAXINCLUDE-1)) { SynError(it8, "Too many recursion levels"); + it8->sy = SEOF; return; } InStringSymbol(it8); - if (!Check(it8, SSTRING, "Filename expected")) return; + if (!Check(it8, SSTRING, "Filename expected")) + { + it8->sy = SEOF; + return; + } FileNest = it8 -> FileStack[it8 -> IncludeSP + 1]; if(FileNest == NULL) { @@ -1000,6 +1004,7 @@ void InSymbol(cmsIT8* it8) FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX)); if (FileNest == NULL) { SynError(it8, "Out of memory"); + it8->sy = SEOF; return; } } @@ -1008,6 +1013,7 @@ void InSymbol(cmsIT8* it8) it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName, cmsMAX_PATH-1) == FALSE) { SynError(it8, "File path too long"); + it8->sy = SEOF; return; } @@ -1015,6 +1021,7 @@ void InSymbol(cmsIT8* it8) if (FileNest->Stream == NULL) { SynError(it8, "File %s not found", FileNest->FileName); + it8->sy = SEOF; return; } it8->IncludeSP++; @@ -1178,7 +1185,8 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size) it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize); } - if (it8->Allocator.Block == NULL) return NULL; + if (it8->Allocator.Block == NULL) + return NULL; ptr = it8 ->Allocator.Block + it8 ->Allocator.Used; it8 ->Allocator.Used += size; @@ -1537,26 +1545,28 @@ cmsInt32Number satoi(const char* b) static -void AllocateDataFormat(cmsIT8* it8) +cmsBool AllocateDataFormat(cmsIT8* it8) { TABLE* t = GetTable(it8); - if (t -> DataFormat) return; // Already allocated + if (t -> DataFormat) return TRUE; // Already allocated t -> nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); if (t -> nSamples <= 0) { SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS"); - t -> nSamples = 10; + return FALSE; } t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *)); if (t->DataFormat == NULL) { SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array"); + return FALSE; } + return TRUE; } static @@ -1575,8 +1585,11 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label) { TABLE* t = GetTable(it8); - if (!t->DataFormat) - AllocateDataFormat(it8); + if (!t->DataFormat) { + + if (!AllocateDataFormat(it8)) + return FALSE; + } if (n > t -> nSamples) { SynError(it8, "More than NUMBER_OF_FIELDS fields."); @@ -1585,6 +1598,7 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label) if (t->DataFormat) { t->DataFormat[n] = AllocString(it8, label); + if (t->DataFormat[n] == NULL) return FALSE; } return TRUE; @@ -1617,11 +1631,11 @@ const char* satob(const char* v) static -void AllocateDataSet(cmsIT8* it8) +cmsBool AllocateDataSet(cmsIT8* it8) { TABLE* t = GetTable(it8); - if (t -> Data) return; // Already allocated + if (t -> Data) return TRUE; // Already allocated t-> nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); t-> nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); @@ -1629,6 +1643,7 @@ void AllocateDataSet(cmsIT8* it8) if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe) { SynError(it8, "AllocateDataSet: too much data"); + return FALSE; } else { // Some dumb analizers warns of possible overflow here, just take a look couple of lines above. @@ -1636,9 +1651,11 @@ void AllocateDataSet(cmsIT8* it8) if (t->Data == NULL) { SynError(it8, "AllocateDataSet: Unable to allocate data array"); + return FALSE; } } + return TRUE; } static @@ -1660,8 +1677,9 @@ cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val) { TABLE* t = GetTable(it8); - if (!t->Data) - AllocateDataSet(it8); + if (!t->Data) { + if (!AllocateDataSet(it8)) return FALSE; + } if (!t->Data) return FALSE; @@ -2004,8 +2022,9 @@ cmsBool DataSection (cmsIT8* it8) InSymbol(it8); // Eats "BEGIN_DATA" CheckEOLN(it8); - if (!t->Data) - AllocateDataSet(it8); + if (!t->Data) { + if (!AllocateDataSet(it8)) return FALSE; + } while (it8->sy != SEND_DATA && it8->sy != SEOF) { @@ -2338,19 +2357,19 @@ void CookPointers(cmsIT8* it8) snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type); SetData(it8, i, idField, Buffer); - } - } + } + } - } + } - } + } - } + } - } - } + } + } it8 ->nTable = nOldTable; } @@ -2778,8 +2797,12 @@ cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* if (t-> nPatches == 0) { - AllocateDataFormat(it8); - AllocateDataSet(it8); + if (!AllocateDataFormat(it8)) + return FALSE; + + if (!AllocateDataSet(it8)) + return FALSE; + CookPointers(it8); } -- cgit v1.2.3