diff --git a/lib/linguist/heuristics.rb b/lib/linguist/heuristics.rb index e497f2927c..de11e417fa 100644 --- a/lib/linguist/heuristics.rb +++ b/lib/linguist/heuristics.rb @@ -30,6 +30,8 @@ def self.call(blob, candidates) end [] # No heuristics matched + rescue Regexp::TimeoutError + [] # Return nothing if we have a bad regexp which leads to a timeout enforced by Regexp.timeout in Ruby 3.2 or later end # Public: Get all heuristic definitions diff --git a/lib/linguist/heuristics.yml b/lib/linguist/heuristics.yml index 46c66df7dd..356f8e27ac 100644 --- a/lib/linguist/heuristics.yml +++ b/lib/linguist/heuristics.yml @@ -686,7 +686,7 @@ disambiguations: - extensions: ['.stl'] rules: - language: STL - pattern: '\A\s*solid(?=$|\s)(?:.|[\r\n])*?^endsolid(?:$|\s)' + pattern: '\A\s*solid(?:$|\s)[\s\S]*^endsolid(?:$|\s)' - extensions: ['.sw'] rules: - language: Sway diff --git a/test/test_heuristics.rb b/test/test_heuristics.rb index 92c4206c95..f1cbe80772 100755 --- a/test/test_heuristics.rb +++ b/test/test_heuristics.rb @@ -34,6 +34,13 @@ def test_symlink_empty assert_equal [], Heuristics.call(file_blob("Markdown/symlink.md"), [Language["Markdown"]]) end + def test_no_match_if_regexp_timeout + skip("This test requires Ruby 3.2.0 or later") if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.2.0') + + Regexp.any_instance.stubs(:match).raises(Regexp::TimeoutError) + assert_equal [], Heuristics.call(file_blob("#{fixtures_path}/Generic/stl/STL/cube1.stl"), [Language["STL"]]) + end + # alt_name is a file name that will be used instead of the file name of the # original sample. This is used to force a sample to go through a specific # heuristic even if its extension doesn't match.