diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 8e7611344b9150..5d5538c373fec8 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -3263,6 +3263,14 @@ def test_sre_template_invalid_group_index(self): _sre.template("", ["", (), ""]) self.assertIn("an integer is required", str(cm.exception)) + @cpython_only + def test_sre_IN_invalid_skip(self): + # gh-160814: the validator must reject the IN opcode with skip < 2. + import _sre + for skip in (0, 1): + with self.assertRaises(RuntimeError): + _sre.compile("x", 0, [13, skip, 1], 0, {}, ()) + class ExternalTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2026-10-28-13-49-42.gh-issue-160814.DwqVVi.rst b/Misc/NEWS.d/next/Library/2026-10-28-13-49-42.gh-issue-160814.DwqVVi.rst new file mode 100644 index 00000000000000..df50ecd73c0931 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-28-13-49-42.gh-issue-160814.DwqVVi.rst @@ -0,0 +1,2 @@ +Fix crash in :meth:`!_sre.compile` with an ``IN`` opcode whose ``skip`` value +is smaller than 2. diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 47c2c4abc3ef24..1c810a419b7a29 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -2212,6 +2212,8 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) case SRE_OP_IN_UNI_IGNORE: case SRE_OP_IN_LOC_IGNORE: GET_SKIP; + if (skip < 2) + FAIL; /* Stop 1 before the end; we check the FAILURE below */ if (_validate_charset(code, code+skip-2)) FAIL;