summaryrefslogtreecommitdiffstats
path: root/src/jplist.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2022-02-07 01:12:58 +0100
committerGravatar Nikias Bassen2022-02-07 01:12:58 +0100
commita5316629a34ec5e1cd0cf76b4cb1625c5a6f3f88 (patch)
tree6df952a29aa05a1730c3306fe6022c07c6a9f84e /src/jplist.c
parent7bc4d2f14e5a0bb80fd7342f954554947b9fee01 (diff)
downloadlibplist-a5316629a34ec5e1cd0cf76b4cb1625c5a6f3f88.tar.gz
libplist-a5316629a34ec5e1cd0cf76b4cb1625c5a6f3f88.tar.bz2
jplist: Prevent integer overflow when parsing numerical values
Credit to OSS-Fuzz
Diffstat (limited to 'src/jplist.c')
-rw-r--r--src/jplist.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/src/jplist.c b/src/jplist.c
index 7264da2..6c6e331 100644
--- a/src/jplist.c
+++ b/src/jplist.c
@@ -266,7 +266,7 @@ static int num_digits_i(int64_t i)
266 int64_t po10; 266 int64_t po10;
267 n=1; 267 n=1;
268 if (i < 0) { 268 if (i < 0) {
269 i = -i; 269 i = (i == INT64_MIN) ? INT64_MAX : -i;
270 n++; 270 n++;
271 } 271 }
272 po10=10; 272 po10=10;
@@ -423,9 +423,10 @@ typedef struct {
423 int count; 423 int count;
424} jsmntok_info_t; 424} jsmntok_info_t;
425 425
426static long long parse_decimal(const char* str, const char* str_end, char** endp) 426static int64_t parse_decimal(const char* str, const char* str_end, char** endp)
427{ 427{
428 long long x = 0; 428 uint64_t MAX = INT64_MAX;
429 uint64_t x = 0;
429 int is_neg = 0; 430 int is_neg = 0;
430 *endp = (char*)str; 431 *endp = (char*)str;
431 432
@@ -433,14 +434,36 @@ static long long parse_decimal(const char* str, const char* str_end, char** endp
433 is_neg = 1; 434 is_neg = 1;
434 (*endp)++; 435 (*endp)++;
435 } 436 }
437 if (is_neg) {
438 MAX++;
439 }
436 while (*endp < str_end && isdigit(**endp)) { 440 while (*endp < str_end && isdigit(**endp)) {
437 x = x * 10 + (**endp - '0'); 441 if (x > PO10i_LIMIT) {
442 x = MAX;
443 break;
444 }
445 x = x * 10;
446 unsigned int add = (**endp - '0');
447 if (x + add > MAX) {
448 x = MAX;
449 break;
450 }
451 x += add;
438 (*endp)++; 452 (*endp)++;
439 } 453 }
454
455 // swallow the rest of the digits in case we dropped out early
456 while (*endp < str_end && isdigit(**endp)) (*endp)++;
457
458 int64_t result = x;
440 if (is_neg) { 459 if (is_neg) {
441 x = -x; 460 if (x == MAX) {
461 result = INT64_MIN;
462 } else {
463 result = -(int64_t)x;
464 }
442 } 465 }
443 return x; 466 return result;
444} 467}
445 468
446static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) 469static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index)