diff options
author | Marti Maria <info@littlecms.com> | 2016-12-06 22:13:35 +0100 |
---|---|---|
committer | Marti Maria <info@littlecms.com> | 2016-12-06 22:13:50 +0100 |
commit | a3def7562bd72961b8dffb1aa601e304952a778c (patch) | |
tree | 709d51b767ed8b61782ec5a0c81b047e572eac19 | |
parent | 422f50dd6e3bff83be6f4b2c6ed0f1a0524abd6d (diff) | |
download | lcms2-a3def7562bd72961b8dffb1aa601e304952a778c.tar.gz |
non-happy path fixes
Fix leak from named color list error recovery
Sanitize maximum string in CGATS parser
-rw-r--r-- | src/cmscgats.c | 106 | ||||
-rw-r--r-- | src/cmsnamed.c | 13 |
2 files changed, 63 insertions, 56 deletions
diff --git a/src/cmscgats.c b/src/cmscgats.c index a68a84c..5fd80c8 100644 --- a/src/cmscgats.c +++ b/src/cmscgats.c @@ -871,7 +871,7 @@ void InSymbol(cmsIT8* it8) k = 0; NextCh(it8); - while (k < MAXSTR && it8->ch != sng) { + while (k < (MAXSTR-1) && it8->ch != sng) { if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1; else { @@ -1944,67 +1944,67 @@ cmsBool HeaderSection(cmsIT8* it8) case SIDENT: - strncpy(VarName, it8->id, MAXID-1); - VarName[MAXID-1] = 0; + strncpy(VarName, it8->id, MAXID - 1); + VarName[MAXID - 1] = 0; - if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) { + if (!IsAvailableOnList(it8->ValidKeywords, VarName, NULL, &Key)) { #ifdef CMS_STRICT_CGATS - return SynError(it8, "Undefined keyword '%s'", VarName); + return SynError(it8, "Undefined keyword '%s'", VarName); #else - Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); - if (Key == NULL) return FALSE; + Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); + if (Key == NULL) return FALSE; #endif - } + } - InSymbol(it8); - if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE; + InSymbol(it8); + if (!GetVal(it8, Buffer, MAXSTR - 1, "Property data expected")) return FALSE; - if(Key->WriteAs != WRITE_PAIR) { - AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, - (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); - } - else { - const char *Subkey; - char *Nextkey; - if (it8->sy != SSTRING) - return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); - - // chop the string as a list of "subkey, value" pairs, using ';' as a separator - for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) - { - char *Value, *temp; - - // identify token pair boundary - Nextkey = (char*) strchr(Subkey, ';'); - if(Nextkey) - *Nextkey++ = '\0'; - - // for each pair, split the subkey and the value - Value = (char*) strrchr(Subkey, ','); - if(Value == NULL) - return SynError(it8, "Invalid value for property '%s'.", VarName); - - // gobble the spaces before the coma, and the coma itself - temp = Value++; - do *temp-- = '\0'; while(temp >= Subkey && *temp == ' '); - - // gobble any space at the right - temp = Value + strlen(Value) - 1; - while(*temp == ' ') *temp-- = '\0'; - - // trim the strings from the left - Subkey += strspn(Subkey, " "); - Value += strspn(Value, " "); - - if(Subkey[0] == 0 || Value[0] == 0) - return SynError(it8, "Invalid value for property '%s'.", VarName); - AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); - } + if (Key->WriteAs != WRITE_PAIR) { + AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, + (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); + } + else { + const char *Subkey; + char *Nextkey; + if (it8->sy != SSTRING) + return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); + + // chop the string as a list of "subkey, value" pairs, using ';' as a separator + for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) + { + char *Value, *temp; + + // identify token pair boundary + Nextkey = (char*)strchr(Subkey, ';'); + if (Nextkey) + *Nextkey++ = '\0'; + + // for each pair, split the subkey and the value + Value = (char*)strrchr(Subkey, ','); + if (Value == NULL) + return SynError(it8, "Invalid value for property '%s'.", VarName); + + // gobble the spaces before the coma, and the coma itself + temp = Value++; + do *temp-- = '\0'; while (temp >= Subkey && *temp == ' '); + + // gobble any space at the right + temp = Value + strlen(Value) - 1; + while (*temp == ' ') *temp-- = '\0'; + + // trim the strings from the left + Subkey += strspn(Subkey, " "); + Value += strspn(Value, " "); + + if (Subkey[0] == 0 || Value[0] == 0) + return SynError(it8, "Invalid value for property '%s'.", VarName); + AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); } + } - InSymbol(it8); - break; + InSymbol(it8); + break; case SEOLN: break; diff --git a/src/cmsnamed.c b/src/cmsnamed.c index 9b27ca0..a8ed7ff 100644 --- a/src/cmsnamed.c +++ b/src/cmsnamed.c @@ -517,7 +517,11 @@ cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v) size = v ->Allocated * 2; // Keep a maximum color lists can grow, 100K entries seems reasonable - if (size > 1024*100) return FALSE; + if (size > 1024 * 100) { + _cmsFree(v->ContextID, (void*) v->List); + v->List = NULL; + return FALSE; + } NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR)); if (NewPtr == NULL) @@ -539,8 +543,11 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn v ->nColors = 0; v ->ContextID = ContextID; - while (v -> Allocated < n){ - if (!GrowNamedColorList(v)) return NULL; + while (v -> Allocated < n) { + if (!GrowNamedColorList(v)) { + _cmsFree(ContextID, (void*) v); + return NULL; + } } strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1); |