diff options
| author | 2022-02-07 01:12:58 +0100 | |
|---|---|---|
| committer | 2022-02-07 01:12:58 +0100 | |
| commit | a5316629a34ec5e1cd0cf76b4cb1625c5a6f3f88 (patch) | |
| tree | 6df952a29aa05a1730c3306fe6022c07c6a9f84e | |
| parent | 7bc4d2f14e5a0bb80fd7342f954554947b9fee01 (diff) | |
| download | libplist-a5316629a34ec5e1cd0cf76b4cb1625c5a6f3f88.tar.gz libplist-a5316629a34ec5e1cd0cf76b4cb1625c5a6f3f88.tar.bz2 | |
jplist: Prevent integer overflow when parsing numerical values
Credit to OSS-Fuzz
| -rw-r--r-- | src/jplist.c | 35 |
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 | ||
| 426 | static long long parse_decimal(const char* str, const char* str_end, char** endp) | 426 | static 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 | ||
| 446 | static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) | 469 | static plist_t parse_primitive(const char* js, jsmntok_info_t* ti, int* index) |
