8000 Add support for XML entity expansion limitation in Stream parser · naitoh/rexml@dc48407 · GitHub
[go: up one dir, main page]

Skip to content

Commit dc48407

Browse files
committed
Add support for XML entity expansion limitation in Stream parser
## Why? See: - ruby#187 - ruby#195 ## Change - Supported `REXML::Security.entity_expansion_limit=` in Stream parser - Supported `REXML::Security.entity_expansion_text_limit=` in Stream parser
1 parent 8b97bae commit dc48407

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

lib/rexml/parsers/streamparser.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ def add_listener( listener )
1414
@parser.add_listener( listener )
1515
end
1616

17+
def entity_expansion_count
18+
@parser.entity_expansion_count
19+
end
20+
1721
def parse
1822
# entity string
1923
while true

test/test_stream.rb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,81 @@ def teardown
134134
REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
135135
end
136136

137+
def test_have_value
138+
source = <<-XML
139+
<?xml version="1.0" encoding="UTF-8"?>
140+
<!DOCTYPE member [
141+
<!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
142+
<!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
143+
<!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
144+
<!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
145+
<!ENTITY e "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
146+
]>
147+
<member>
148+
&a;
149+
</member>
150+
XML
151+
152+
assert_raise(RuntimeError.new("entity expansion has grown too large")) do
153+
REXML::Document.parse_stream(source, MyListener.new)
154+
end
155+
end
156+
157+
def test_empty_value
158+
source = <<-XML
159+
<?xml version="1.0" encoding="UTF-8"?>
160+
<!DOCTYPE member [
161+
<!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
162+
<!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
163+
<!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
164+
<!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
165+
<!ENTITY e "">
166+
]>
167+
<member>
168+
&a;
169+
</member>
170+
XML
171+
172+
listener = MyListener.new
173+
REXML::Security.entity_expansion_limit = 100000
174+
parser = REXML::Parsers::StreamParser.new( source, listener )
175+
parser.parse
176+
assert_equal(11111, parser.entity_expansion_count)
177+
178+
REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
179+
parser = REXML::Parsers::StreamParser.new( source, listener )
180+
assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
181+
parser.parse
182+
end
183+
assert do
184+
parser.entity_expansion_count > @default_entity_expansion_limit
185+
end
186+
end
187+
188+
def test_with_default_entity
189+
source = <<-XML
190+
<?xml version="1.0" encoding="UTF-8"?>
191+
<!DOCTYPE member [
192+
<!ENTITY a "a">
193+
<!ENTITY a2 "&a; &a;">
194+
]>
195+
<member>
196+
&a;
197+
&a2;
198+
&lt;
199+
</member>
200+
XML
201+
202+
listener = MyListener.new
203+
REXML::Security.entity_expansion_limit = 4
204+
REXML::Document.parse_stream(source, listener)
205+
206+
REXML::Security.entity_expansion_limit = 3
207+
assert_raise(RuntimeError.new("number of entity expansions exceeded, processing aborted.")) do
208+
REXML::Document.parse_stream(source, listener)
209+
end
210+
end
211+
137212
def test_with_only_default_entities
138213
member_value = "&lt;p&gt;#{'A' * @default_entity_expansion_text_limit}&lt;/p&gt;"
139214
source = <<-XML
@@ -159,6 +234,32 @@ def text(text)
159234
listener.text_value.bytesize > @default_entity_expansion_text_limit
160235
end
161236
end
237+
238+
def test_entity_expansion_text_limit
239+
source = <<-XML
240+
<!DOCTYPE member [
241+
<!ENTITY a "&b;&b;&b;">
242+
<!ENTITY b "&c;&d;&e;">
243+
<!ENTITY c "xxxxxxxxxx">
244+
<!ENTITY d "yyyyyyyyyy">
245+
<!ENTITY e "zzzzzzzzzz">
246+
]>
247+
<member>&a;</member>
248+
XML
249+
250+
listener = MyListener.new
251+
class << listener
252+
attr_accessor :text_value
253+
def text(text)
254+
@text_value << text
255+
end
256+
end
257+
listener.text_value = ""
258+
REXML::Security.entity_expansion_text_limit = 90
259+
REXML::Document.parse_stream(source, listener)
260+
261+
assert_equal(90, listener.text_value.size)
262+
end
162263
end
163264

164265
# For test_listener

0 commit comments

Comments
 (0)
0