Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit edeff24

Browse files
committedNov 30, 2022
gh-99891: Fix infinite recursion in the tokenizer when showing warnings
1 parent 05dfc53 commit edeff24

File tree

4 files changed

+25
-0
lines changed

4 files changed

+25
-0
lines changed
 

‎Lib/test/test_source_encoding.py

+13
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,19 @@ def test_file_parse_error_multiline(self):
160160
finally:
161161
os.unlink(TESTFN)
162162

163+
def test_tokenizer_fstring_warning_in_first_line(self):
164+
source = "0b1and 2"
165+
with open(TESTFN, "w") as fd:
166+
fd.write("{}".format(source))
167+
try:
168+
retcode, stdout, stderr = script_helper.assert_python_failure(TESTFN, PYTHONWARNINGS="error")
169+
self.assertGreater(retcode, 0)
170+
self.assertIn(b"SyntaxError: invalid binary litera", stderr)
171+
self.assertEqual(stderr.count(source.encode()), 1)
172+
finally:
173+
os.unlink(TESTFN)
174+
175+
163176
class AbstractSourceEncodingTest:
164177

165178
def test_default_coding(self):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a bug in the tokenizer that could cause infinite recursion when showing
2+
syntax warnings that happen in the first line of the source. Patch by Pablo
3+
Galindo

‎Parser/tokenizer.c

+8
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ tok_new(void)
9797
tok->async_def_nl = 0;
9898
tok->interactive_underflow = IUNDERFLOW_NORMAL;
9999
tok->str = NULL;
100+
tok->report_warnings = 1;
100101
#ifdef Py_DEBUG
101102
tok->debug = _Py_GetConfig()->parser_debug;
102103
#endif
@@ -1201,6 +1202,10 @@ indenterror(struct tok_state *tok)
12011202
static int
12021203
parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...)
12031204
{
1205+
if (!tok->report_warnings) {
1206+
return 0;
1207+
}
1208+
12041209
PyObject *errmsg;
12051210
va_list vargs;
12061211
va_start(vargs, format);
@@ -2239,6 +2244,9 @@ _PyTokenizer_FindEncodingFilename(int fd, PyObject *filename)
22392244
}
22402245
}
22412246
struct token token;
2247+
// We don't want to report warnings here because it could cause infinite recursion
2248+
// if fetching the encoding shows a warning.
2249+
tok->report_warnings = 0;
22422250
while (tok->lineno < 2 && tok->done == E_OK) {
22432251
_PyTokenizer_Get(tok, &token);
22442252
}

‎Parser/tokenizer.h

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct tok_state {
9292
NEWLINE token after it. */
9393
/* How to proceed when asked for a new token in interactive mode */
9494
enum interactive_underflow_t interactive_underflow;
95+
int report_warnings;
9596
#ifdef Py_DEBUG
9697
int debug;
9798
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.