Skip to content

Commit 86790e6

Browse files
committed
Add protections against infinite loop in bezier calculations
Closes matplotlib#27753
1 parent 8f296db commit 86790e6

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

lib/matplotlib/bezier.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,17 @@ def find_bezier_t_intersecting_with_closedpath(
171171

172172
if start_inside ^ middle_inside:
173173
t1 = middle_t
174+
if end == middle:
175+
# Edge case where infinite loop is possible
176+
# Caused by large numbers relative to tolerance
177+
return t0, t1
174178
end = middle
175179
else:
176180
t0 = middle_t
181+
if start == middle:
182+
# Edge case where infinite loop is possible
183+
# Caused by large numbers relative to tolerance
184+
return t0, t1
177185
start = middle
178186
start_inside = middle_inside
179187

lib/matplotlib/tests/test_bezier.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Tests specific to the bezier module.
3+
"""
4+
5+
from matplotlib.bezier import inside_circle, split_bezier_intersecting_with_closedpath
6+
7+
8+
def test_split_bezier_with_large_values():
9+
# These numbers come from gh-27753
10+
arrow_path = [(96950809781500.0, 804.7503795623779),
11+
(96950809781500.0, 859.6242585800646),
12+
(96950809781500.0, 914.4981375977513)]
13+
in_f = inside_circle(96950809781500.0, 804.7503795623779, 0.06)
14+
split_bezier_intersecting_with_closedpath(arrow_path, in_f)
15+
# All we are testing is that this completes
16+
# The failure case is an infinite loop resulting from floating point precision
17+
# pytest will timeout if that occurs

0 commit comments

Comments
 (0)