[php-src] master: json: Report unterminated JSON strings as syntax errors (#22528)
Tim Düsterhus via GitHub <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Tim Düsterhus (TimWolla)
Committer: GitHub (web-flow)
Pusher: TimWolla
Date: 2026-07-12T21:05:09+02:00
Commit: https://github.com/php/php-src/commit/68d0f569144e5fbcc33fc9def4d8a9c3f6e0a828
Raw diff: https://github.com/php/php-src/commit/68d0f569144e5fbcc33fc9def4d8a9c3f6e0a828.diff
json: Report unterminated JSON strings as syntax errors (#22528)
Fixes php/php-src#22527.
Changed paths:
A ext/json/tests/gh22527.phpt
M NEWS
M ext/json/json_scanner.re
M ext/json/tests/json_last_error_msg_error_location_001.phpt
M ext/json/tests/json_last_error_msg_error_location_002.phpt
M ext/json/tests/json_last_error_msg_error_location_004.phpt
M ext/json/tests/json_last_error_msg_error_location_005.phpt
M ext/json/tests/json_last_error_msg_error_location_006.phpt
M ext/json/tests/json_last_error_msg_error_location_007.phpt
M ext/json/tests/json_last_error_msg_error_location_008.phpt
M ext/json/tests/json_last_error_msg_error_location_009.phpt
M ext/json/tests/json_last_error_msg_error_location_010.phpt
Diff:
diff --git a/NEWS b/NEWS
index 48b13b5bc90a..0459373092ff 100644
--- a/NEWS
+++ b/NEWS
@@ -58,6 +58,9 @@ PHP NEWS
IntlDateFormatter::localtime()/datefmt_localtime() now raise TypeError
when the offset argument is not of type int. (Weilin Du)
+- JSON:
+ . Report unterminated JSON strings as syntax errors. (timwolla)
+
- Opcache:
. Fixed bug GH-21770 (Infinite recursion in property hook getter in opcache
preloaded trait). (iliaal)
diff --git a/ext/json/json_scanner.re b/ext/json/json_scanner.re
index e4d25009132a..0c64a6423baf 100644
--- a/ext/json/json_scanner.re
+++ b/ext/json/json_scanner.re
@@ -262,7 +262,14 @@ std:
s->errcode = PHP_JSON_ERROR_UTF8;
return PHP_JSON_T_ERROR;
}
-
+ <STR_P1>EOI {
+ if (s->limit < s->cursor) {
+ s->errcode = PHP_JSON_ERROR_SYNTAX;
+ } else {
+ s->errcode = PHP_JSON_ERROR_CTRL_CHAR;
+ }
+ return PHP_JSON_T_ERROR;
+ }
<STR_P1>CTRL {
s->errcode = PHP_JSON_ERROR_CTRL_CHAR;
return PHP_JSON_T_ERROR;
diff --git a/ext/json/tests/gh22527.phpt b/ext/json/tests/gh22527.phpt
new file mode 100644
index 000000000000..cb0dd982d50b
--- /dev/null
+++ b/ext/json/tests/gh22527.phpt
@@ -0,0 +1,31 @@
+--TEST--
+GH-22527: Unterminated JSON strings are misleadingly reported as “Control character error”
+--FILE--
+<?php
+
+var_dump(json_decode('"'));
+var_dump(json_last_error(), json_last_error_msg());
+
+var_dump(json_decode('"123'));
+var_dump(json_last_error(), json_last_error_msg());
+
+var_dump(json_decode('{"123": "'));
+var_dump(json_last_error(), json_last_error_msg());
+
+var_dump(json_decode('"' . chr(0)));
+var_dump(json_last_error(), json_last_error_msg());
+
+?>
+--EXPECT--
+NULL
+int(4)
+string(30) "Syntax error near location 1:1"
+NULL
+int(4)
+string(30) "Syntax error near location 1:1"
+NULL
+int(4)
+string(30) "Syntax error near location 1:9"
+NULL
+int(3)
+string(71) "Control character error, possibly incorrectly encoded near location 1:1"
diff --git a/ext/json/tests/json_last_error_msg_error_location_001.phpt b/ext/json/tests/json_last_error_msg_error_location_001.phpt
index e0553f9f7d65..72cb1c42f23f 100644
--- a/ext/json/tests/json_last_error_msg_error_location_001.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_001.phpt
@@ -66,8 +66,8 @@ string(30) "Syntax error near location 1:1"
Error at position 1:10:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error at position 1:9:
bool(false)
@@ -118,4 +118,3 @@ Error at position 1:10:
bool(false)
int(3)
string(72) "Control character error, possibly incorrectly encoded near location 1:10"
-
diff --git a/ext/json/tests/json_last_error_msg_error_location_002.phpt b/ext/json/tests/json_last_error_msg_error_location_002.phpt
index df7fc981ccba..31438255b31a 100644
--- a/ext/json/tests/json_last_error_msg_error_location_002.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_002.phpt
@@ -53,51 +53,50 @@ Testing error locations with Unicode UTF-8 characters
Error after Japanese characters:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:12"
+int(4)
+string(31) "Syntax error near location 1:12"
Error after Russian characters:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error after Chinese characters:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:8"
+int(4)
+string(30) "Syntax error near location 1:8"
Error after Arabic characters:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error after Emoji:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:11"
+int(4)
+string(31) "Syntax error near location 1:11"
Error in mixed ASCII and UTF-8:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:27"
+int(4)
+string(31) "Syntax error near location 1:27"
Error with UTF-8 escaped sequences:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error in object with multiple UTF-8 keys:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:22"
+int(4)
+string(31) "Syntax error near location 1:22"
Error in array with UTF-8 strings:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:18"
+int(4)
+string(31) "Syntax error near location 1:18"
Error in nested object with UTF-8:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:15"
-
+int(4)
+string(31) "Syntax error near location 1:15"
diff --git a/ext/json/tests/json_last_error_msg_error_location_004.phpt b/ext/json/tests/json_last_error_msg_error_location_004.phpt
index 165449600fb3..fcde3faa38a3 100644
--- a/ext/json/tests/json_last_error_msg_error_location_004.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_004.phpt
@@ -53,8 +53,8 @@ Testing error locations in deeply nested structures
Error in deeply nested object:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:31"
+int(4)
+string(31) "Syntax error near location 1:31"
Error in deeply nested array:
bool(true)
@@ -78,16 +78,15 @@ string(31) "Syntax error near location 1:21"
Error in complex structure:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:93"
+int(4)
+string(31) "Syntax error near location 1:93"
Error in array of objects:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:68"
+int(4)
+string(31) "Syntax error near location 1:68"
Error in object with array values:
bool(false)
int(2)
string(61) "State mismatch (invalid or malformed JSON) near location 1:82"
-
diff --git a/ext/json/tests/json_last_error_msg_error_location_005.phpt b/ext/json/tests/json_last_error_msg_error_location_005.phpt
index d12ce387e73e..ee1800eb8273 100644
--- a/ext/json/tests/json_last_error_msg_error_location_005.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_005.phpt
@@ -53,51 +53,50 @@ Testing error locations with UTF-16 surrogate pairs and escape sequences
Error after UTF-16 escaped emoji:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:11"
+int(4)
+string(31) "Syntax error near location 1:11"
Error after multiple UTF-16 pairs:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with mixed UTF-8 and UTF-16:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:11"
+int(4)
+string(31) "Syntax error near location 1:11"
Error with UTF-16 in key:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error with multiple UTF-16 keys:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:22"
+int(4)
+string(31) "Syntax error near location 1:22"
Error with BMP characters:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with supplementary plane:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:11"
+int(4)
+string(31) "Syntax error near location 1:11"
Error in array with UTF-16:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:12"
+int(4)
+string(31) "Syntax error near location 1:12"
Error in nested structure with UTF-16:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:18"
+int(4)
+string(31) "Syntax error near location 1:18"
Error with UTF-16 and control chars:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
-
+int(4)
+string(31) "Syntax error near location 1:10"
diff --git a/ext/json/tests/json_last_error_msg_error_location_006.phpt b/ext/json/tests/json_last_error_msg_error_location_006.phpt
index e6aab1af8f27..4a6c221c8f92 100644
--- a/ext/json/tests/json_last_error_msg_error_location_006.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_006.phpt
@@ -107,8 +107,8 @@ string(33) "Syntax error near location 1:1011"
Error with very long key:
bool(false)
-int(3)
-string(73) "Control character error, possibly incorrectly encoded near location 1:506"
+int(4)
+string(32) "Syntax error near location 1:506"
Error after empty object:
bool(false)
@@ -149,4 +149,3 @@ Error with mixed whitespace:
bool(false)
int(3)
string(71) "Control character error, possibly incorrectly encoded near location 3:2"
-
diff --git a/ext/json/tests/json_last_error_msg_error_location_007.phpt b/ext/json/tests/json_last_error_msg_error_location_007.phpt
index 0e24889bbbbe..168afc4dbfe2 100644
--- a/ext/json/tests/json_last_error_msg_error_location_007.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_007.phpt
@@ -118,8 +118,8 @@ string(30) "Syntax error near location 1:9"
Unclosed string:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Invalid escape sequence:
bool(false)
@@ -175,4 +175,3 @@ Missing comma between object properties:
bool(false)
int(4)
string(30) "Syntax error near location 1:9"
-
diff --git a/ext/json/tests/json_last_error_msg_error_location_008.phpt b/ext/json/tests/json_last_error_msg_error_location_008.phpt
index 4d8a1012316b..60dd9513472b 100644
--- a/ext/json/tests/json_last_error_msg_error_location_008.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_008.phpt
@@ -82,101 +82,100 @@ Testing error locations with various UTF-8 multi-byte character widths
Error with 2-byte UTF-8 (Latin Extended):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with 2-byte UTF-8 (Greek):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:14"
+int(4)
+string(31) "Syntax error near location 1:14"
Error with 2-byte UTF-8 (Cyrillic):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:12"
+int(4)
+string(31) "Syntax error near location 1:12"
Error with 3-byte UTF-8 (Chinese):
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:8"
+int(4)
+string(30) "Syntax error near location 1:8"
Error with 3-byte UTF-8 (Japanese Hiragana):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with 3-byte UTF-8 (Japanese Katakana):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with 3-byte UTF-8 (Korean):
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:8"
+int(4)
+string(30) "Syntax error near location 1:8"
Error with 4-byte UTF-8 (Emoji faces):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:11"
+int(4)
+string(31) "Syntax error near location 1:11"
Error with 4-byte UTF-8 (Emoji objects):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:13"
+int(4)
+string(31) "Syntax error near location 1:13"
Error with 4-byte UTF-8 (Mathematical symbols):
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with mixed 1-2-3 byte UTF-8:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error with mixed 2-3-4 byte UTF-8:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error with all byte widths:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error with UTF-8 key at start:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:7"
+int(4)
+string(30) "Syntax error near location 1:7"
Error with multiple UTF-8 keys:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:35"
+int(4)
+string(31) "Syntax error near location 1:35"
Error in array with mixed UTF-8:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:25"
+int(4)
+string(31) "Syntax error near location 1:25"
Error in nested structure with various UTF-8:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:22"
+int(4)
+string(31) "Syntax error near location 1:22"
Error with combining diacritical marks:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with Hebrew:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
+int(4)
+string(31) "Syntax error near location 1:10"
Error with Arabic with diacritics:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:11"
-
+int(4)
+string(31) "Syntax error near location 1:11"
diff --git a/ext/json/tests/json_last_error_msg_error_location_009.phpt b/ext/json/tests/json_last_error_msg_error_location_009.phpt
index 406179693ef6..9d4403838f63 100644
--- a/ext/json/tests/json_last_error_msg_error_location_009.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_009.phpt
@@ -75,18 +75,18 @@ string(46) "Maximum stack depth exceeded near location 1:7"
Syntax error at deep nesting level:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:31"
+int(4)
+string(31) "Syntax error near location 1:31"
Syntax error in deep array:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:6"
+int(4)
+string(30) "Syntax error near location 1:6"
Error after valid deep structure:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:48"
+int(4)
+string(31) "Syntax error near location 1:48"
Error in middle of nested structure:
bool(false)
@@ -95,16 +95,15 @@ string(31) "Syntax error near location 1:29"
Error in array with nested objects:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:30"
+int(4)
+string(31) "Syntax error near location 1:30"
Error in deep UTF-8 structure:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:16"
+int(4)
+string(31) "Syntax error near location 1:16"
Valid deep structure within limit:
bool(true)
int(0)
string(8) "No error"
-
diff --git a/ext/json/tests/json_last_error_msg_error_location_010.phpt b/ext/json/tests/json_last_error_msg_error_location_010.phpt
index 108570205838..d187afff86cc 100644
--- a/ext/json/tests/json_last_error_msg_error_location_010.phpt
+++ b/ext/json/tests/json_last_error_msg_error_location_010.phpt
@@ -119,13 +119,13 @@ string(30) "Syntax error near location 4:2"
Error in string with spaces:
bool(false)
-int(3)
-string(71) "Control character error, possibly incorrectly encoded near location 1:9"
+int(4)
+string(30) "Syntax error near location 1:9"
Error with whitespace around colon:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:12"
+int(4)
+string(31) "Syntax error near location 1:12"
Error with whitespace around comma:
bool(true)
@@ -154,11 +154,10 @@ string(72) "Control character error, possibly incorrectly encoded near location
Error in compact JSON:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:22"
+int(4)
+string(31) "Syntax error near location 1:22"
Error with regular spaces:
bool(false)
-int(3)
-string(72) "Control character error, possibly incorrectly encoded near location 1:10"
-
+int(4)
+string(31) "Syntax error near location 1:10"