diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 12a2950..9e47401 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -795,7 +795,7 @@ def escape_empty(val): | # terminal hyperlinks {_osc}8; # OSC opening - (\w+=\w+:?)* # key=value params list (submatch 2) + (\w+=\w+(?::\w+=\w+)*:?)? # key=value params list (submatch 2) ; # delimiter ([^{_esc}]+) # URI - anything but ESC (submatch 3) {_st} # ST diff --git a/test/test_regression.py b/test/test_regression.py index 9555676..c730173 100644 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -1,5 +1,7 @@ """Regression tests.""" +import time + from tabulate import DataRow, Line, TableFormat, tabulate from common import assert_equal, skip @@ -598,3 +600,13 @@ def test_github_escape_pipe_character(): result = tabulate([["foo|bar"]], headers=("spam|eggs",), tablefmt="github") expected = "| spam\\|eggs |\n|:------------|\n| foo\\|bar |" assert_equal(expected, result) + + +def test_osc8_link_params_no_catastrophic_backtracking(): + "Regression: unterminated OSC 8 link params must not backtrack exponentially" + cell = "\x1b]8;a=" + "aaaa=" * 16 + start = time.perf_counter() + result = tabulate([[cell]], tablefmt="plain") + elapsed = time.perf_counter() - start + assert_equal(cell, result) + assert elapsed < 1.0