diff options
| -rwxr-xr-x | numpy/f2py/crackfortran.py | 2 | ||||
| -rw-r--r-- | numpy/f2py/tests/test_crackfortran.py | 11 |
2 files changed, 10 insertions, 3 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index b831697d8..901be1a83 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -935,7 +935,7 @@ typedefpattern = re.compile( r'(?:,(?P<attributes>[\w(),]+))?(::)?(?P<name>\b[a-z$_][\w$]*\b)' r'(?:\((?P<params>[\w,]*)\))?\Z', re.I) nameargspattern = re.compile( - r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P<bind>.*)\s*@\)@))*\s*\Z', re.I) + r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P<bind>[^\s@]*)\s*@\)@))*\s*\Z', re.I) operatorpattern = re.compile( r'\s*(?P<scheme>(operator|assignment))' r'@\(@\s*(?P<name>[^)]+)\s*@\)@\s*\Z', re.I) diff --git a/numpy/f2py/tests/test_crackfortran.py b/numpy/f2py/tests/test_crackfortran.py index fc3ab561e..b577eaf38 100644 --- a/numpy/f2py/tests/test_crackfortran.py +++ b/numpy/f2py/tests/test_crackfortran.py @@ -279,7 +279,9 @@ class TestUnicodeComment(util.F2PyTest): self.module.foo(3) class TestNameArgsPatternBacktracking: - def test_nameargspattern_backtracking(): + def test_nameargspattern_backtracking(self): + '''address ReDOS vulnerability: + https://github.com/numpy/numpy/issues/23338''' last_time = 0. trials_per_count = 32 start_reps, end_reps = 10, 16 @@ -291,5 +293,10 @@ class TestNameArgsPatternBacktracking: crackfortran.nameargspattern.search(atbindat) total_time += (time.perf_counter() - t0) if ii > start_reps: - assert total_time < 1.9 * last_time, f'Going from {ii - 1} to {ii} approximately doubled time' + # the hallmark of exponentially catastrophic backtracking + # is that runtime doubles for every added instance of + # the problematic pattern. + assert total_time < 1.9 * last_time + # also try to rule out non-exponential but still bad cases + assert total_time < 1 last_time = total_time
\ No newline at end of file |
