Skip to content

Commit 2c4473b

Browse files
committed
Fix integer overflow in the JSON scanner string length adjustments
The scanner accumulates escape shrinkage and invalid-UTF-8 adjustment in int fields, so a string carrying more than 2^31 escape sequences or ignored invalid bytes wraps the counter and makes the first pass reserve a result several gigabytes longer than the second pass writes. json_decode() of a 2 GiB run of invalid bytes with JSON_INVALID_UTF8_IGNORE returns a 4 GiB string instead of an empty one. Widen both counters to ptrdiff_t, which is what the token length they adjust is already measured in.
1 parent 5226e2f commit 2c4473b

2 files changed

Lines changed: 3 additions & 3 deletions

File tree

ext/json/json_scanner.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ std:
295295
<STR_P1>ANY {
296296
if (s->options & (PHP_JSON_INVALID_UTF8_IGNORE | PHP_JSON_INVALID_UTF8_SUBSTITUTE)) {
297297
if (s->options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) {
298-
if (s->utf8_invalid_count > INT_MAX - 2) {
298+
if (s->utf8_invalid_count > PTRDIFF_MAX - 2) {
299299
s->errcode = PHP_JSON_ERROR_UTF8;
300300
return PHP_JSON_T_ERROR;
301301
}

ext/json/php_json_scanner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ typedef struct _php_json_scanner {
3131
php_json_ctype *line_start; /* start position of the current line */
3232
uint64_t line; /* current line number (1-based) */
3333
zval value; /* value */
34-
int str_esc; /* number of extra characters for escaping */
34+
ptrdiff_t str_esc; /* number of extra characters for escaping */
3535
int state; /* condition state */
3636
int options; /* options */
3737
php_json_error_code errcode; /* error type if there is an error */
3838
int utf8_invalid; /* whether utf8 is invalid */
39-
int utf8_invalid_count; /* number of extra character for invalid utf8 */
39+
ptrdiff_t utf8_invalid_count; /* number of extra character for invalid utf8 */
4040
} php_json_scanner;
4141

4242
void php_json_scanner_init(php_json_scanner *scanner, const char *str, size_t str_len, int options);

0 commit comments

Comments
 (0)