Skip to content

Commit

Permalink
pythongh-99891: Fix infinite recursion in the tokenizer when showing …
Browse files Browse the repository at this point in the history
…warnings
  • Loading branch information
pablogsal committed Nov 30, 2022
1 parent 05dfc53 commit edeff24
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Lib/test/test_source_encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,19 @@ def test_file_parse_error_multiline(self):
finally:
os.unlink(TESTFN)

def test_tokenizer_fstring_warning_in_first_line(self):
source = "0b1and 2"
with open(TESTFN, "w") as fd:
fd.write("{}".format(source))
try:
retcode, stdout, stderr = script_helper.assert_python_failure(TESTFN, PYTHONWARNINGS="error")
self.assertGreater(retcode, 0)
self.assertIn(b"SyntaxError: invalid binary litera", stderr)
self.assertEqual(stderr.count(source.encode()), 1)
finally:
os.unlink(TESTFN)


class AbstractSourceEncodingTest:

def test_default_coding(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix a bug in the tokenizer that could cause infinite recursion when showing
syntax warnings that happen in the first line of the source. Patch by Pablo
Galindo
8 changes: 8 additions & 0 deletions Parser/tokenizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ tok_new(void)
tok->async_def_nl = 0;
tok->interactive_underflow = IUNDERFLOW_NORMAL;
tok->str = NULL;
tok->report_warnings = 1;
#ifdef Py_DEBUG
tok->debug = _Py_GetConfig()->parser_debug;
#endif
Expand Down Expand Up @@ -1201,6 +1202,10 @@ indenterror(struct tok_state *tok)
static int
parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...)
{
if (!tok->report_warnings) {
return 0;
}

PyObject *errmsg;
va_list vargs;
va_start(vargs, format);
Expand Down Expand Up @@ -2239,6 +2244,9 @@ _PyTokenizer_FindEncodingFilename(int fd, PyObject *filename)
}
}
struct token token;
// We don't want to report warnings here because it could cause infinite recursion
// if fetching the encoding shows a warning.
tok->report_warnings = 0;
while (tok->lineno < 2 && tok->done == E_OK) {
_PyTokenizer_Get(tok, &token);
}
Expand Down
1 change: 1 addition & 0 deletions Parser/tokenizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct tok_state {
NEWLINE token after it. */
/* How to proceed when asked for a new token in interactive mode */
enum interactive_underflow_t interactive_underflow;
int report_warnings;
#ifdef Py_DEBUG
int debug;
#endif
Expand Down

0 comments on commit edeff24

Please sign in to comment.