Skip to content

Commit 696c81f

Browse files
committed
fix(tokenizer): correct offset of Non-UTF-8 syntax error
1 parent fde6296 commit 696c81f

3 files changed

Lines changed: 15 additions & 4 deletions

File tree

Lib/test/test_exceptions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,16 @@ def testSyntaxErrorRange(self):
250250
self.assertEqual(cm.exception.offset, offset)
251251
self.assertEqual(cm.exception.end_offset, end_offset)
252252

253+
def testSyntaxErrorNonUTF8Offset(self):
254+
# gh-157378: the position was reported one column short for each
255+
# multi-byte character preceding the invalid byte on the same line
256+
check = self.check
257+
check(b'X\x80', 1, 2, 1, 2)
258+
check(b'\xc3\xa9X\x80', 1, 3, 1, 3)
259+
check(b'\t\xc3\xa9X\x80', 1, 4, 1, 4)
260+
check(b'a\xc3\xa9b\x80c', 1, 4, 1, 4)
261+
check(b'a\n\xc3\xa9X\x80', 2, 3, 2, 3)
262+
253263
def testSyntaxErrorOffset(self):
254264
check = self.check
255265
check('def fact(x):\n\treturn x!\n', 2, 10)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix ``SyntaxError.offset`` and ``SyntaxError.end_offset`` for the
2+
"Non-UTF-8 code starting with ..." error when a non-ASCII character precedes
3+
the invalid byte on the same line. Patch by Shamil Abdulaev.

Parser/tokenizer/helpers.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,17 +329,14 @@ _PyTokenizer_ensure_utf8(const char *line, struct tok_state *tok, int lineno)
329329
const char *badchar = NULL;
330330
const char *c;
331331
int length;
332-
int col_offset = 0;
333332
const char *line_start = line;
334333
for (c = line; *c; c += length) {
335334
if (!(length = valid_utf8((const unsigned char *)c))) {
336335
badchar = c;
337336
break;
338337
}
339-
col_offset++;
340338
if (*c == '\n') {
341339
lineno++;
342-
col_offset = 0;
343340
line_start = c + 1;
344341
}
345342
}
@@ -348,7 +345,8 @@ _PyTokenizer_ensure_utf8(const char *line, struct tok_state *tok, int lineno)
348345
tok->line_start = _PyLexer_BufferOffset(tok, line_start);
349346
tok->cur = _PyLexer_BufferOffset(tok, badchar);
350347
_PyTokenizer_syntaxerror_known_range(tok,
351-
col_offset + 1, col_offset + 1,
348+
(int)(badchar - line_start) + 1,
349+
(int)(badchar - line_start) + 1,
352350
"Non-UTF-8 code starting with '\\x%.2x'"
353351
"%s%V on line %i, "
354352
"but no encoding declared; "

0 commit comments

Comments
 (0)