https://github.com/python/cpython/commit/e66bec09b722b8955d34f51f2c4b63793d59f9cf
commit: e66bec09b722b8955d34f51f2c4b63793d59f9cf
branch: main
author: Shamil <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-09-14T12:13:40Z
summary:

gh-157378: Fix SyntaxError.offset for "Non-UTF-8 code" error (#157412)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-12-46-10.gh-issue-157378.Rg7Tq2.rst
M Lib/test/test_exceptions.py
M Parser/tokenizer/helpers.c

diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 0c02b38dd3c0a89..750e45bb1644686 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -250,6 +250,16 @@ def testSyntaxErrorRange(self):
                 self.assertEqual(cm.exception.offset, offset)
                 self.assertEqual(cm.exception.end_offset, end_offset)
 
+    def testSyntaxErrorNonUTF8Offset(self):
+        # gh-157378: the position was reported one column short for each
+        # multi-byte character preceding the invalid byte on the same line
+        check = self.check
+        check(b'X\x80', 1, 2, 1, 2)
+        check(b'\xc3\xa9X\x80', 1, 3, 1, 3)
+        check(b'\t\xc3\xa9X\x80', 1, 4, 1, 4)
+        check(b'a\xc3\xa9b\x80c', 1, 4, 1, 4)
+        check(b'a\n\xc3\xa9X\x80', 2, 3, 2, 3)
+
     def testSyntaxErrorOffset(self):
         check = self.check
         check('def fact(x):\n\treturn x!\n', 2, 10)
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-12-46-10.gh-issue-157378.Rg7Tq2.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-12-46-10.gh-issue-157378.Rg7Tq2.rst
new file mode 100644
index 000000000000000..569642492992d3a
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-13-12-46-10.gh-issue-157378.Rg7Tq2.rst
@@ -0,0 +1,3 @@
+Fix ``SyntaxError.offset`` and ``SyntaxError.end_offset`` for the
+"Non-UTF-8 code starting with ..." error when a non-ASCII character precedes
+the invalid byte on the same line. Patch by Shamil Abdulaev.
diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c
index c803b787d9dae68..d0ada5ac1131a71 100644
--- a/Parser/tokenizer/helpers.c
+++ b/Parser/tokenizer/helpers.c
@@ -329,17 +329,14 @@ _PyTokenizer_ensure_utf8(const char *line, struct 
tok_state *tok, int lineno)
     const char *badchar = NULL;
     const char *c;
     int length;
-    int col_offset = 0;
     const char *line_start = line;
     for (c = line; *c; c += length) {
         if (!(length = valid_utf8((const unsigned char *)c))) {
             badchar = c;
             break;
         }
-        col_offset++;
         if (*c == '\n') {
             lineno++;
-            col_offset = 0;
             line_start = c + 1;
         }
     }
@@ -348,7 +345,8 @@ _PyTokenizer_ensure_utf8(const char *line, struct tok_state 
*tok, int lineno)
         tok->line_start = _PyLexer_BufferOffset(tok, line_start);
         tok->cur = _PyLexer_BufferOffset(tok, badchar);
         _PyTokenizer_syntaxerror_known_range(tok,
-                col_offset + 1, col_offset + 1,
+                (int)(badchar - line_start) + 1,
+                (int)(badchar - line_start) + 1,
                 "Non-UTF-8 code starting with '\\x%.2x'"
                 "%s%V on line %i, "
                 "but no encoding declared; "

_______________________________________________
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