Commit e9c8771cec5 for php
commit e9c8771cec5440574df84d3b6e36ed420811a55b
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Sat Oct 31 09:22:30 2026 -0400
Fix integer overflow in the JSON scanner string length adjustments (#22920)
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
diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re
index 91c5c002439..a43544cd067 100644
--- a/ext/json/json_scanner.re
+++ b/ext/json/json_scanner.re
@@ -299,7 +299,7 @@ std:
<STR_P1>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 f432f66b6d7..ff603fad26e 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);