From bd69a0ddef30af30f82dc99946bf0c66beaa8e51 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 8 Apr 2026 16:33:27 -0500 Subject: [PATCH] lib/re1.5: Check stack during compilecode. Otherwise, a very deeply nested regular expression like re.compile("(" * 65536) can exhaust the host stack during the compile phase. This turns that into a `RuntimeError: maximum recursion depth exceeded` instead. This crash was found via fuzzing. Signed-off-by: Jeff Epler --- lib/re1.5/compilecode.c | 2 ++ tests/extmod/re_stack_overflow2.py | 25 +++++++++++++++++++++++++ tests/run-tests.py | 1 + 3 files changed, 28 insertions(+) create mode 100644 tests/extmod/re_stack_overflow2.py diff --git a/lib/re1.5/compilecode.c b/lib/re1.5/compilecode.c index 513a155970..fade45324d 100644 --- a/lib/re1.5/compilecode.c +++ b/lib/re1.5/compilecode.c @@ -29,6 +29,8 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) int term = PC; int alt_label = 0; + re1_5_stack_chk(); + for (; *re && *re != ')'; re++) { switch (*re) { case '\\': diff --git a/tests/extmod/re_stack_overflow2.py b/tests/extmod/re_stack_overflow2.py new file mode 100644 index 0000000000..c5ddd012b3 --- /dev/null +++ b/tests/extmod/re_stack_overflow2.py @@ -0,0 +1,25 @@ +# Test overflow in re.compile output code. + +try: + import re +except ImportError: + print("SKIP") + raise SystemExit + + +def test_re(r): + try: + re.compile(r) + except: + print("Error") + + +try: + r = "(" * 65536 + ")" * 65536 +except MemoryError: + print("SKIP") + raise SystemExit + +# This happens to trigger RecursionError on current versions of CPython +# (tested with 3.13.5) as well, so no .exp file is needed. +test_re(r) diff --git a/tests/run-tests.py b/tests/run-tests.py index 6a9f10fc32..c5c5dc740b 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -178,6 +178,7 @@ platform_tests_to_skip = { "extmod/binascii_a2b_base64.py", "extmod/deflate_compress_memory_error.py", # tries to allocate unlimited memory "extmod/re_stack_overflow.py", + "extmod/re_stack_overflow2.py", "extmod/time_res.py", "extmod/vfs_posix.py", "extmod/vfs_posix_enoent.py",