Projects

Ticket #749: reproductible_regexp_crash.rb

File reproductible_regexp_crash.rb, 1.8 KB (added by martinlagardette@…, 22 months ago)
Line 
1
2str = <<EOT
3class PrintProxy
4  # instance_methods.each {
5  #   |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/
6  # }
7 
8  def initialize(obj, &block)
9    @obj = obj
10  end
11
12  protected
13
14  def method_missing(symbol, *args, &block)
15    print "foo"
16    if @block then print "foo\n" else print "\n" end
17   
18    @obj.send(symbol, *args, &block)
19  end
20end
21EOT
22
23class StringScanner
24  attr_reader :string, :pos
25
26  def initialize(string, dup = false)
27    @string = string
28    @pos = 0
29  end
30
31  def eos?
32    self.pos >= self.string.size
33  end
34
35  def rest
36    string[pos..-1]
37  end
38
39  def skip_until(pattern)
40    _scan(pattern, true, false, false)
41  end
42
43  def pos=(n)
44    n = (n + string.size) if (n < 0)
45    raise RangeError, "index out of range" if (n < 0 || (string && n > string.size))
46    @pos = n
47  end
48
49  def matched?
50    !@match.nil?
51  end 
52
53  def matched
54    @match.to_s if matched?
55  end
56
57  def matched_size
58    @match.to_s.size if matched?
59  end
60
61  def _scan(pattern, succptr, getstr, headonly)
62    raise TypeError, "bad pattern argument: #{pattern.inspect}" unless
63      String === pattern or Regexp === pattern or pattern.respond_to? :to_str
64 
65    @match = nil
66    rest = self.rest
67   
68    return nil if rest.size < 0
69 
70    if headonly
71      headonly_pattern = Regexp.new('^' + pattern.source, pattern.options)
72      @match = headonly_pattern.match rest
73    else
74      @match = pattern.match rest
75    end
76 
77    return nil unless @match
78 
79    m = rest[0, @match.end(0)]
80 
81    if succptr
82      @prev_pos = pos
83      self.pos += m.size
84    end
85   
86    getstr ? m : m.size
87  end
88end
89
90match = []
91ss = StringScanner.new(str)
92
93while ss.skip_until(/(class(?![^ \n])|def(?![^ \n]))/)
94  a = ss.pos - ss.matched_size
95  b = ss.matched_size
96
97  warn "[#{a}, #{b}] = \"#{ss.matched}\""
98  x = [a, b, ss.matched]
99  match << x
100end
101