Skip to content

Commit 1311ca8

Browse files
committed
Fix polynominal backtracking
Fix #995
1 parent adfa7db commit 1311ca8

File tree

2 files changed

+26
-33
lines changed

2 files changed

+26
-33
lines changed

lib/rdoc/comment.rb

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -97,42 +97,26 @@ def extract_call_seq method
9797
# comment. The difficulty is to make sure not to match lines starting
9898
# with ARGF at the same indent, but that are after the first description
9999
# paragraph.
100-
if @text =~ /^\s*:?call-seq:(.*?(?:\S).*?)^\s*$/m then
100+
if /^(?<S> ((?!\n)\s)*+ (?# whitespaces except newline))
101+
:?call-seq:
102+
(?<B> \g<S>(?<N>\n|\z) (?# trailing spaces))?
103+
(?<seq>
104+
(\g<S>(?!\w)\S.*\g<N>)*
105+
(?>
106+
(?<H> \g<S>\w+ (?# ' # ARGF' in the example above))
107+
.*\g<N>)?
108+
(\g<S>\S.*\g<N> (?# other non-blank line))*+
109+
(\g<B>+(\k<H>.*\g<N> (?# ARGF.to_a lines))++)*+
110+
)
111+
(?m:^\s*$|\z)
112+
/x =~ @text
113+
seq = $~[:seq]
114+
101115
all_start, all_stop = $~.offset(0)
102-
seq_start, seq_stop = $~.offset(1)
103-
104-
# we get the following lines that start with the leading word at the
105-
# same indent, even if they have blank lines before
106-
if $1 =~ /(^\s*\n)+^(\s*\w+)/m then
107-
leading = $2 # ' * ARGF' in the example above
108-
re = %r%
109-
\A(
110-
(^\s*\n)+
111-
(^#{Regexp.escape leading}.*?\n)+
112-
)+
113-
^\s*$
114-
%xm
115-
116-
if @text[seq_stop..-1] =~ re then
117-
all_stop = seq_stop + $~.offset(0).last
118-
seq_stop = seq_stop + $~.offset(1).last
119-
end
120-
end
121-
122-
seq = @text[seq_start..seq_stop]
123-
seq.gsub!(/^\s*(\S|\n)/m, '\1')
124116
@text.slice! all_start...all_stop
125117

126-
method.call_seq = seq.chomp
127-
128-
else
129-
regexp = /^\s*:?call-seq:(.*?)(^\s*$|\z)/m
130-
if regexp =~ @text then
131-
@text = @text.sub(regexp, '')
132-
seq = $1
133-
seq.gsub!(/^\s*/, '')
134-
method.call_seq = seq
135-
end
118+
seq.gsub!(/^\s*/, '')
119+
method.call_seq = seq
136120
end
137121

138122
method

test/rdoc/test_rdoc_comment.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ def test_extract_call_seq_c_separator
206206
assert_equal expected, comment.text
207207
end
208208

209+
def test_extract_call_linear_performance
210+
pre = ->(n) {[n, RDoc::Comment.new("\n"*n + 'call-seq:' + 'a'*n)]}
211+
method_obj = RDoc::AnyMethod.new nil, 'blah'
212+
assert_linear_performance((2..5).map {|i| 10**i}, pre: pre) do |n, comment|
213+
comment.extract_call_seq method_obj
214+
assert_equal n, method_obj.call_seq.size
215+
end
216+
end
217+
209218
def test_force_encoding
210219
@comment = RDoc::Encoding.change_encoding @comment, Encoding::UTF_8
211220

0 commit comments

Comments
 (0)