10000 Fix RuntimeError in `REXML::Parsers::BaseParser` for valid feeds (#199) · ruby/rexml@1c76dbb · GitHub
[go: up one dir, main page]

Skip to content

Commit 1c76dbb

Browse files
vikiv480kounaitoh
authored
Fix RuntimeError in REXML::Parsers::BaseParser for valid feeds (#199)
GitHub: fix GH-198 Change `#entity` to not match against default entities After this change, the following example will not raise a RuntimeError: ```ruby # rexml/refactor_entity_example.rb $LOAD_PATH.unshift(File.expand_path("lib")) require "rexml/parsers/baseparser" valid_feed = "&lt;p&gt;#{'A' * 10_240}&lt;/p&gt;" base_parser = REXML::Parsers::BaseParser.new("") base_parser.unnormalize(valid_feed) # => "<p>" + "A" * 10_240 + "</p>" ``` Default entities now gets substituted by this block instead https://github.com/ruby/rexml/blob/e14847cee53d26eb162ad786ba12e3cd7a86fce0/lib/rexml/parsers/baseparser.rb#L560-L563 --------- Co-authored-by: Sutou Kouhei <kou@clear-code.com> Co-authored-by: NAITOH Jun <naitoh@gmail.com>
1 parent 2f019f9 commit 1c76dbb

File tree

4 files changed

+98
-9
lines changed

4 files changed

+98
-9
lines changed

lib/rexml/parsers/baseparser.rb

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -521,15 +521,13 @@ def pull_event
521521
private :pull_event
522522

523523
def entity( reference, entities )
524-
value = nil
525-
value = entities[ reference ] if entities
526-
if value
527-
record_entity_expansion
528-
else
529-
value = DEFAULT_ENTITIES[ reference ]
530-
value = value[2] if value
531-
end
532-
unnormalize( value, entities ) if value
524+
return unless entities
525+
526+
value = entities[ reference ]
527+
return if value.nil?
528+
529+
record_entity_expansion
530+
unnormalize( value, entities )
533531
end
534532

535533
# Escapes all possible entities

test/test_pullparser.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,36 @@ def test_with_default_entity
254254
end
255255
end
256256

257+
def test_with_only_default_entities
258+
member_value = "&lt;p&gt;#{'A' * @default_entity_expansion_text_limit}&lt;/p&gt;"
259+
source = <<-XML
260+
<?xml version="1.0" encoding="UTF-8"?>
261+
<member>
262+
#{member_value}
263+
</member>
264+
XML
265+
266+
parser = REXML::Parsers::PullParser.new(source)
267+
events = {}
268+
element_name = ''
269+
while parser.has_next?
270+
event = parser.pull
271+
case event.event_type
272+
when :start_element
273+
element_name = event[0]
274+
when :text
275+
events[element_name] = event[1]
276+
end
277+
end
278+
279+
expected_value = "<p>#{'A' * @default_entity_expansion_text_limit}</p>" 8000
280+
assert_equal(expected_value, events['member'].strip)
281+
assert_equal(0, parser.entity_expansion_count)
282+
assert do
283+
events['member'].bytesize > @default_entity_expansion_text_limit
284+
end
285+
end
286+
257287
def test_entity_expansion_text_limit
258288
source = <<-XML
259289
<!DOCTYPE member [

test/test_sax.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,30 @@ def test_with_default_entity
187187
end
188188
end
189189

190+
def test_with_only_default_entities
191+
member_value = "&lt;p&gt;#{'A' * @default_entity_expansion_text_limit}&lt;/p&gt;"
192+
source = <<-XML
193+
<?xml version="1.0" encoding="UTF-8"?>
194+
<member>
195+
#{member_value}
196+
</member>
197+
XML
198+
199+
sax = REXML::Parsers::SAX2Parser.new(source)
200+
text_value = nil
201+
sax.listen(:characters, ["member"]) do |text|
202+
text_value = text
203+
end
204+
sax.parse
205+
206+
expected_value = "<p>#{'A' * @default_entity_expansion_text_limit}</p>"
207+
assert_equal(expected_value, text_value.strip)
208+
assert_equal(0, sax.entity_expansion_count)
209+
assert do
210+
text_value.bytesize > @default_entity_expansion_text_limit
211+
end
212+
end
213+
190214
def test_entity_expansion_text_limit
191215
source = <<-XML
192216
<!DOCTYPE member [

test/test_stream.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,43 @@ def entity(content)
8989
end
9090
end
9191

92+
class EntityExpansionLimitTest < Test::Unit::TestCase
93+
def setup
94+
@default_entity_expansion_limit = REXML::Security.entity_expansion_limit
95+
@default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
96+
end
97+
98+
def teardown
99+
REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
100+
REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
101+
end
102+
103+
def test_with_only_default_entities
104+
member_value = "&lt;p&gt;#{'A' * @default_entity_expansion_text_limit}&lt;/p&gt;"
105+
source = <<-XML
106+
<?xml version="1.0" encoding="UTF-8"?>
107+
<member>
108+
#{member_value}
109+
</member>
110+
XML
111+
112+
listener = MyListener.new
113+
class << listener
114+
attr_accessor :text_value
115+
def text(text)
116+
@text_value << text
117+
end
118+
end
119+
listener.text_value = ""
120+
REXML::Document.parse_stream(source, listener)
121+
122+
expected_value = "<p>#{'A' * @default_entity_expansion_text_limit}</p>"
123+
assert_equal(expected_value, listener.text_value.strip)
124+
assert do
125+
listener.text_value.bytesize > @default_entity_expansion_text_limit
126+
end
127+
end
128+
end
92129

93130
# For test_listener
94131
class RequestReader

0 commit comments

Comments
 (0)
0