From 06eda501078b3e15ee1156ade9a5a83bbf11c445 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 29 Jul 2026 07:30:41 -0400 Subject: [PATCH] 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. Closes GH-22920 --- ext/json/json_scanner.re | 2 +- ext/json/php_json_scanner.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re index be62875a00e0..fbbc6883b854 100644 --- a/ext/json/json_scanner.re +++ b/ext/json/json_scanner.re @@ -295,7 +295,7 @@ std: ANY { if (s->options & (PHP_JSON_INVALID_UTF8_IGNORE | PHP_JSON_INVALID_UTF8_SUBSTITUTE)) { if (s->options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) { - if (s->utf8_invalid_count > INT_MAX - 2) { + if (s->utf8_invalid_count > PTRDIFF_MAX - 2) { s->errcode = PHP_JSON_ERROR_UTF8; return PHP_JSON_T_ERROR; } diff --git a/ext/json/php_json_scanner.h b/ext/json/php_json_scanner.h index f432f66b6d78..ff603fad26e7 100644 --- a/ext/json/php_json_scanner.h +++ b/ext/json/php_json_scanner.h @@ -31,12 +31,12 @@ typedef struct _php_json_scanner { php_json_ctype *line_start; /* start position of the current line */ uint64_t line; /* current line number (1-based) */ zval value; /* value */ - int str_esc; /* number of extra characters for escaping */ + ptrdiff_t str_esc; /* number of extra characters for escaping */ int state; /* condition state */ int options; /* options */ php_json_error_code errcode; /* error type if there is an error */ int utf8_invalid; /* whether utf8 is invalid */ - int utf8_invalid_count; /* number of extra character for invalid utf8 */ + ptrdiff_t utf8_invalid_count; /* number of extra character for invalid utf8 */ } php_json_scanner; void php_json_scanner_init(php_json_scanner *scanner, const char *str, size_t str_len, int options);