https://github.com/python/cpython/commit/dbcc05334ea994b21b023f0ded141fd81604987b
commit: dbcc05334ea994b21b023f0ded141fd81604987b
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-06-26T15:28:53Z
summary:

[3.14] gh-152052: Fix misleading `json` error for `\uXXXX` escape at the end of 
input (GH-152053) (#152284)

(cherry picked from commit 588be7af08c04d63c1a920539c64885fbc4c6d38)

Co-authored-by: tonghuaroot (童话) <[email protected]>
Co-authored-by: Stan Ulbrych <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-06-24-12-00-00.gh-issue-152052.yBssDE.rst
M Lib/test/test_json/test_fail.py
M Lib/test/test_json/test_scanstring.py
M Modules/_json.c

diff --git a/Lib/test/test_json/test_fail.py b/Lib/test/test_json/test_fail.py
index 79c44af2fbf0e1f..7f99a6331d36251 100644
--- a/Lib/test/test_json/test_fail.py
+++ b/Lib/test/test_json/test_fail.py
@@ -144,6 +144,13 @@ def test_truncated_input(self):
             ('"', 'Unterminated string starting at', 0),
             ('"spam', 'Unterminated string starting at', 0),
         ]
+        # A complete \uXXXX escape at end of input leaves it unterminated.
+        test_cases += [
+            (r'"\u0041', 'Unterminated string starting at', 0),
+            (r'"\ud834', 'Unterminated string starting at', 0),
+            (r'"\ud834\udd1e', 'Unterminated string starting at', 0),
+            (r'{"a": "\u0041', 'Unterminated string starting at', 6),
+        ]
         for data, msg, idx in test_cases:
             with self.assertRaises(self.JSONDecodeError) as cm:
                 self.loads(data)
diff --git a/Lib/test/test_json/test_scanstring.py 
b/Lib/test/test_json/test_scanstring.py
index 9a6cdfe12d266c0..a52b01c71130d8c 100644
--- a/Lib/test/test_json/test_scanstring.py
+++ b/Lib/test/test_json/test_scanstring.py
@@ -137,6 +137,9 @@ def test_bad_escapes(self):
             '"\\ud834\\u-123"',
             '"\\ud834\\u+123"',
             '"\\ud834\\u1_23"',
+            # Truncated or non-hex \uXXXX escape at end of input.
+            '"\\u004',
+            '"\\uXYZW',
         ]
         for s in bad_escapes:
             with self.assertRaises(self.JSONDecodeError, msg=s):
diff --git 
a/Misc/NEWS.d/next/Library/2026-06-24-12-00-00.gh-issue-152052.yBssDE.rst 
b/Misc/NEWS.d/next/Library/2026-06-24-12-00-00.gh-issue-152052.yBssDE.rst
new file mode 100644
index 000000000000000..f9ffbbd342fc81a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-24-12-00-00.gh-issue-152052.yBssDE.rst
@@ -0,0 +1,2 @@
+The :mod:`json` C accelerator now correctly reports an unterminated string for 
a
+``\uXXXX`` escape at the end of the input.
diff --git a/Modules/_json.c b/Modules/_json.c
index 39cdb9fd4f40c84..250dd67d2a9687c 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -474,7 +474,7 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int 
strict, Py_ssize_t *next
             c = 0;
             next++;
             end = next + 4;
-            if (end >= len) {
+            if (end > len) {
                 raise_errmsg("Invalid \\uXXXX escape", pystr, next - 1);
                 goto bail;
             }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to