From 9cd92ad636ec22a517d45b39856bf8ddfa3a31dd Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Thu, 12 Oct 2023 10:43:57 +0200 Subject: [PATCH 1/3] gh-107450: Raise MemoryError when parser column offset overflows --- Parser/pegen_errors.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 2baae5289b5667..cdd50a8ceb84b3 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -235,6 +235,12 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, int use_mark, const char *err col_offset = 0; } else { const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; + if (p->tok->cur - start > INT_MAX) { + PyErr_SetString(PyExc_MemoryError, + "Parser column offset overflow - source line is too big"); + p->error_indicator = 1; + return NULL; + } col_offset = Py_SAFE_DOWNCAST(p->tok->cur - start, intptr_t, int); } } else { From 50186785463c7d0e57c59a07ac1f1ea62118463e Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Thu, 12 Oct 2023 11:04:50 +0200 Subject: [PATCH 2/3] Add test --- Lib/test/test_exceptions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 05a89e7705e90f..037fb5320b7e1a 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -318,6 +318,10 @@ def baz(): check('(yield i) = 2', 1, 2) check('def f(*):\n pass', 1, 7) + def testMemoryErrorBigSource(self): + with self.assertRaises(MemoryError): + exec(f"if True:\n {' ' * 2**31}print('hello world')") + @cpython_only def testSettingException(self): # test that setting an exception at the C level works even if the From f87e527e25f80eef7a35ed8119e3e0e74e7ac1e9 Mon Sep 17 00:00:00 2001 From: Lysandros Nikolaou Date: Thu, 12 Oct 2023 11:08:45 +0200 Subject: [PATCH 3/3] Raise overflowerror instead of memoryerror --- Lib/test/test_exceptions.py | 2 +- Parser/pegen_errors.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 037fb5320b7e1a..bba2eeb8877730 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -319,7 +319,7 @@ def baz(): check('def f(*):\n pass', 1, 7) def testMemoryErrorBigSource(self): - with self.assertRaises(MemoryError): + with self.assertRaisesRegex(OverflowError, "column offset overflow"): exec(f"if True:\n {' ' * 2**31}print('hello world')") @cpython_only diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index cdd50a8ceb84b3..15e99e23d8490f 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -236,7 +236,7 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, int use_mark, const char *err } else { const char* start = p->tok->buf ? p->tok->line_start : p->tok->buf; if (p->tok->cur - start > INT_MAX) { - PyErr_SetString(PyExc_MemoryError, + PyErr_SetString(PyExc_OverflowError, "Parser column offset overflow - source line is too big"); p->error_indicator = 1; return NULL;