summaryrefslogtreecommitdiff
path: root/numpy/f2py
diff options
context:
space:
mode:
authormolsonkiko <46202915+molsonkiko@users.noreply.github.com>2023-03-26 17:45:01 -0700
committermolsonkiko <46202915+molsonkiko@users.noreply.github.com>2023-03-26 17:45:01 -0700
commit09c23ef73c839d3a7f31e755f40f2f06b9791b7f (patch)
tree526f251000553c4c6fb242b9842b79520f945b89 /numpy/f2py
parentfd0f29de9365dcceec26d6a2a7539f61b0b037cf (diff)
downloadnumpy-09c23ef73c839d3a7f31e755f40f2f06b9791b7f.tar.gz
make regex still match cases where OG fix failed
My first replacement regex would have failed to match cases like '@)@bind foo bar baz@(@@)@' which should apparently be matched. Added a test to make sure the regex does this.
Diffstat (limited to 'numpy/f2py')
-rwxr-xr-xnumpy/f2py/crackfortran.py2
-rw-r--r--numpy/f2py/tests/test_crackfortran.py25
2 files changed, 20 insertions, 7 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index 901be1a83..36a913047 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*@\)@))*\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*\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 67693b019..449251435 100644
--- a/numpy/f2py/tests/test_crackfortran.py
+++ b/numpy/f2py/tests/test_crackfortran.py
@@ -4,7 +4,7 @@ import time
import unicodedata
import pytest
import numpy as np
-from numpy.f2py.crackfortran import markinnerspaces
+from numpy.f2py.crackfortran import markinnerspaces, nameargspattern
from . import util
from numpy.f2py import crackfortran
import textwrap
@@ -279,19 +279,32 @@ class TestUnicodeComment(util.F2PyTest):
self.module.foo(3)
class TestNameArgsPatternBacktracking:
- def test_nameargspattern_backtracking(self):
+ @pytest.mark.parametrize(
+ ['adversary'],
+ [
+ ('@)@bind@(@',),
+ ('@)@bind @(@',),
+ ('@)@bind foo bar baz@(@',)
+ ]
+ )
+ def test_nameargspattern_backtracking(self, adversary):
'''address ReDOS vulnerability:
https://github.com/numpy/numpy/issues/23338'''
last_time = 0.
- trials_per_count = 32
- start_reps, end_reps = 10, 16
+ trials_per_count = 128
+ start_reps, end_reps = 15, 25
for ii in range(start_reps, end_reps):
- atbindat = '@)@bind@(@' * ii
+ repeated_adversary = adversary * ii
total_time = 0
for _ in range(trials_per_count):
t0 = time.perf_counter()
- crackfortran.nameargspattern.search(atbindat)
+ mtch = nameargspattern.search(repeated_adversary)
total_time += (time.perf_counter() - t0)
+ assert not mtch
+ # if the adversary is capped with @)@, it becomes acceptable.
+ # that should still be true.
+ good_version_of_adversary = repeated_adversary + '@)@'
+ assert nameargspattern.search(good_version_of_adversary)
if ii > start_reps:
# the hallmark of exponentially catastrophic backtracking
# is that runtime doubles for every added instance of