Skip to content

Commit 74fc8cd

Browse files
committed
Add test suite for ReDoS attacks
1 parent 034d126 commit 74fc8cd

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

.github/workflows/python.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ jobs:
2727
- name: Test
2828
run: |
2929
make testone
30+
- name: Test ReDoS
31+
run: |
32+
make testredos

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ test:
1212
testone:
1313
cd test && python test.py -- -knownfailure
1414

15+
.PHONY: testredos
16+
testredos:
17+
python test/test_redos.py
18+
1519
.PHONY: pygments
1620
pygments:
1721
[[ -d deps/pygments ]] || ( \

test/test_redos.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import logging
2+
import subprocess
3+
import sys
4+
import time
5+
from pathlib import Path
6+
7+
log = logging.getLogger("test")
8+
LIB_DIR = Path(__file__).parent.parent / "lib"
9+
10+
11+
def pull_387_example_1():
12+
# https://github.com/trentm/python-markdown2/pull/387
13+
return "[#a" + " " * 3456
14+
15+
16+
def pull_387_example_2():
17+
# https://github.com/trentm/python-markdown2/pull/387
18+
return "```" + "\n" * 3456
19+
20+
21+
def pull_387_example_3():
22+
# https://github.com/trentm/python-markdown2/pull/387
23+
return "-*-" + " " * 3456
24+
25+
26+
def pull_402():
27+
# https://github.com/trentm/python-markdown2/pull/402
28+
return " " * 100_000 + "$"
29+
30+
31+
def issue493():
32+
# https://github.com/trentm/python-markdown2/issues/493
33+
return "**_" + "*_" * 38730 * 10 + "\x00"
34+
35+
36+
def issue_633():
37+
# https://github.com/trentm/python-markdown2/issues/633
38+
return '<p m="1"' * 5000 + " " * 10_000 + "</div"
39+
40+
41+
# whack everything in a dict for easy lookup later on
42+
CASES = {
43+
fn.__name__: fn
44+
for fn in [
45+
pull_387_example_1,
46+
pull_387_example_2,
47+
pull_387_example_3,
48+
pull_402,
49+
issue493,
50+
issue_633,
51+
]
52+
}
53+
54+
55+
if __name__ == "__main__":
56+
logging.basicConfig()
57+
58+
if "--execute" in sys.argv:
59+
testcase = CASES[sys.argv[sys.argv.index("--execute") + 1]]
60+
sys.path.insert(0, str(LIB_DIR))
61+
from markdown2 import markdown
62+
63+
markdown(testcase())
64+
sys.exit(0)
65+
66+
print("-- ReDoS tests")
67+
68+
fails = []
69+
start_time = time.time()
70+
for testcase in CASES:
71+
print(f"markdown2/redos/{testcase} ... ", end="")
72+
73+
testcase_start_time = time.time()
74+
try:
75+
subprocess.run([sys.executable, __file__, "--execute", testcase], timeout=3)
76+
except subprocess.TimeoutExpired:
77+
fails.append(testcase)
78+
print(f"FAIL ({time.time() - testcase_start_time:.3f}s)")
79+
else:
80+
print(f"ok ({time.time() - testcase_start_time:.3f}s)")
81+
82+
print("----------------------------------------------------------------------")
83+
print(f"Ran {len(CASES)} tests in {time.time() - start_time:.3f}s")
84+
85+
if fails:
86+
print("FAIL:", fails)
87+
else:
88+
print("OK")
89+
90+
sys.exit(len(fails))

0 commit comments

Comments
 (0)