From 8ea84caa3cba801c4f240648a6b7919e9b3e0b0d Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Mon, 31 Jan 2022 03:27:42 +0100 Subject: jplist: Fix OOB read in parse_primitive caused by missing 0-termination In parse_primitive, integer and double values are parsed by using strtoll and atof, which both expect the string to be 0-terminated. While this is not a problem in well-formed JSON files, it can be if the JSON data is not, possibly leading to a crash due to OOB memory access. This commit fixes it by copying the value data in question to a stack buffer and 0-terminate it, and use that buffer instead. Credit to OSS-Fuzz --- src/jplist.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/jplist.c b/src/jplist.c index 2182079..827b367 100644 --- a/src/jplist.c +++ b/src/jplist.c @@ -443,7 +443,13 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) val = plist_new_node(data); } else if (str_val[0] == '-' || isdigit(str_val[0])) { char* endp = NULL; - long long intpart = strtol(str_val, &endp, 10); + char cbuf[48]; + size_t maxlen = str_end-str_val; + if (maxlen >= sizeof(cbuf)) maxlen = sizeof(cbuf)-1; + strncpy(cbuf, str_val, maxlen); + cbuf[maxlen] = '\0'; + long long intpart = strtoll(cbuf, &endp, 10); + endp = (char*)str_val + (endp-&cbuf[0]); if (endp >= str_end) { /* integer */ val = plist_new_uint((uint64_t)intpart); @@ -452,7 +458,7 @@ static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) char* fendp = endp+1; while (isdigit(*fendp) && fendp < str_end) fendp++; if ((fendp > endp+1 && fendp >= str_end) || (fendp+2 < str_end && (*fendp == 'e' || *fendp == 'E') && (*(fendp+1) == '+' || *(fendp+1) == '-') && isdigit(*(fendp+2)))) { - double dval = atof(str_val); + double dval = atof(cbuf); val = plist_new_real(dval); } else { PLIST_JSON_ERR("%s: invalid character at offset %d when parsing floating point value\n", __func__, (int)(fendp - js)); -- cgit v1.1-32-gdbae