Skip to content

Commit 5bc551c

Browse files
committed
Fix calculation of Security.entity_expansion_text_limit
[Why?] In SAX and PULL, the total value of rv.bytesize was checked, but the summing process was unnecessary. - Add Log ```patch diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb index 28810bf..5cfc089 100644 --- a/lib/rexml/parsers/baseparser.rb +++ b/lib/rexml/parsers/baseparser.rb @@ -556,6 +556,7 @@ module REXML re = Private::DEFAULT_ENTITIES_PATTERNS[entity_reference] || /&#{entity_reference};/ rv.gsub!( re, entity_value ) sum += rv.bytesize +puts " rv.bytesize: #{rv.bytesize} sum: #{sum} > Security.entity_expansion_text_limit: #{Security.entity_expansion_text_limit} : #{rv}" if sum > Security.entity_expansion_text_limit raise "entity expansion has grown too large" end diff --git a/lib/rexml/text.rb b/lib/rexml/text.rb index 7e0befe..cc68dbf 100644 --- a/lib/rexml/text.rb +++ b/lib/rexml/text.rb @@ -415,6 +415,7 @@ module REXML sum = 0 string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) { s = Text.expand($&, doctype, filter) +puts " s.bytesize: #{s.bytesize} sum + s.bytesize : #{sum + s.bytesize } > Security.entity_expansion_text_limit: #{Security.entity_expansion_text_limit} : #{s}" if sum + s.bytesize > Security.entity_expansion_text_limit raise "entity expansion has grown too large" else ``` - entity_expansion_text_limit.rb ``` $LOAD_PATH.unshift(File.expand_path("lib")) require 'rexml' require 'rexml/parsers/sax2parser' require 'rexml/parsers/pullparser' def dom_entity_expansion_count_check(xml) doc = REXML::Document.new(xml) doc.root.children.first.value puts "DOM: entity_expansion_count: #{doc.entity_expansion_count}" end def sax_entity_expansion_count_check(xml) sax = REXML::Parsers::SAX2Parser.new(xml) sax.parse puts "SAX: entity_expansion_count: #{sax.entity_expansion_count}" end def pull_entity_expansion_count_check(xml) parser = REXML::Parsers::PullParser.new(xml) while parser.has_next? parser.pull end puts "Pull: entity_expansion_count: #{parser.entity_expansion_count}" end xml = <<XML <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE member [ <!ENTITY a "&b;&b;&b;"> <!ENTITY b "&c;&d;&e;"> <!ENTITY c "xxxxxxxxxx"> <!ENTITY d "yyyyyyyyyy"> <!ENTITY e "zzzzzzzzzz"> ]> <member>&a;</member> XML dom_entity_expansion_count_check(xml) sax_entity_expansion_count_check(xml) pull_entity_expansion_count_check(xml) ``` ``` $ ruby entity_expansion_text_limit.rb s.bytesize: 10 sum + s.bytesize : 10 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx s.bytesize: 10 sum + s.bytesize : 20 > Security.entity_expansion_text_limit: 10240 : yyyyyyyyyy s.bytesize: 10 sum + s.bytesize : 30 > Security.entity_expansion_text_limit: 10240 : zzzzzzzzzz s.bytesize: 30 sum + s.bytesize : 30 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz s.bytesize: 10 sum + s.bytesize : 10 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx s.bytesize: 10 sum + s.bytesize : 20 > Security.entity_expansion_text_limit: 10240 : yyyyyyyyyy s.bytesize: 10 sum + s.bytesize : 30 > Security.entity_expansion_text_limit: 10240 : zzzzzzzzzz s.bytesize: 30 sum + s.bytesize : 60 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz s.bytesize: 10 sum + s.bytesize : 10 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx s.bytesize: 10 sum + s.bytesize : 20 > Security.entity_expansion_text_limit: 10240 : yyyyyyyyyy s.bytesize: 10 sum + s.bytesize : 30 > Security.entity_expansion_text_limit: 10240 : zzzzzzzzzz s.bytesize: 30 sum + s.bytesize : 90 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz s.bytesize: 90 sum + s.bytesize : 90 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz DOM: entity_expansion_count: 13 rv.bytesize: 16 sum: 16 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx&d;&e; rv.bytesize: 23 sum: 39 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyy&e; rv.bytesize: 30 sum: 69 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 90 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 16 sum: 16 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx&d;&e; rv.bytesize: 23 sum: 39 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyy&e; rv.bytesize: 30 sum: 69 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 180 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 16 sum: 16 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx&d;&e; rv.bytesize: 23 sum: 39 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyy&e; rv.bytesize: 30 sum: 69 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 270 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 90 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz SAX: entity_expansion_count: 13 rv.bytesize: 16 sum: 16 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx&d;&e; rv.bytesize: 23 sum: 39 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyy&e; rv.bytesize: 30 sum: 69 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 90 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 16 sum: 16 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx&d;&e; rv.bytesize: 23 sum: 39 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyy&e; rv.bytesize: 30 sum: 69 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 180 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 16 sum: 16 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxx&d;&e; rv.bytesize: 23 sum: 39 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyy&e; rv.bytesize: 30 sum: 69 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 270 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz rv.bytesize: 90 sum: 90 > Security.entity_expansion_text_limit: 10240 : xxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzzxxxxxxxxxxyyyyyyyyyyzzzzzzzzzz Pull: entity_expansion_count: 13 ``` 90 bytes is the expected value, but SAX and Pull exceed 90 bytes due to unnecessary total processing.
1 parent e3f747f commit 5bc551c

File tree

4 files changed

+60
-3
lines changed

4 files changed

+60
-3
lines changed

lib/rexml/parsers/baseparser.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,15 +548,13 @@ def unnormalize( string, entities=nil, filter=nil )
548548
}
549549
matches.collect!{|x|x[0]}.compact!
550550
if matches.size > 0
551-
sum = 0
552551
matches.each do |entity_reference|
553552
unless filter and filter.include?(entity_reference)
554553
entity_value = entity( entity_reference, entities )
555554
if entity_value
556555
re = Private::DEFAULT_ENTITIES_PATTERNS[entity_reference] || /&#{entity_reference};/
557556
rv.gsub!( re, entity_value )
558-
sum += rv.bytesize
559-
if sum > Security.entity_expansion_text_limit
557+
if rv.bytesize > Security.entity_expansion_text_limit
560558
raise "entity expansion has grown too large"
561559
end
562560
else

test/test_document.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ def test_new
3333
class EntityExpansionLimitTest < Test::Unit::TestCase
3434
def setup
3535
@default_entity_expansion_limit = REXML::Security.entity_expansion_limit
36+
@default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
3637
end
3738

3839
def teardown
3940
REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
41+
REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
4042
end
4143

4244
class GeneralEntityTest < self
@@ -126,6 +128,24 @@ def test_with_default_entity
126128
doc.root.children.first.value
127129
end
128130
end
131+
132+
def test_entity_expansion_text_limit
133+
xml = <<-XML
134+
<?xml version="1.0" encoding="UTF-8"?>
135+
<!DOCTYPE member [
136+
<!ENTITY a "&b;&b;&b;">
137+
<!ENTITY b "&c;&d;&e;">
138+
<!ENTITY c "xxxxxxxxxx">
139+
<!ENTITY d "yyyyyyyyyy">
140+
<!ENTITY e "zzzzzzzzzz">
141+
]>
142+
<member>&a;</member>
143+
XML
144+
145+
REXML::Security.entity_expansion_text_limit = 90
146+
doc = REXML::Document.new(xml)
147+
doc.root.children.first.value
148+
end
129149
end
130150

131151
class ParameterEntityTest < self

test/test_pullparser.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,12 @@ def test_peek
159159
class EntityExpansionLimitTest < Test::Unit::TestCase
160160
def setup
161161
@default_entity_expansion_limit = REXML::Security.entity_expansion_limit
162+
@default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
162163
end
163164

164165
def teardown
165166
REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
167+
REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
166168
end
167169

168170
class GeneralEntityTest < self
@@ -249,6 +251,25 @@ def test_with_default_entity
249251
end
250252
end
251253
end
254+
255+
def test_entity_expansion_text_limit
256+
source = <<-XML
257+
<!DOCTYPE member [
258+
<!ENTITY a "&b;&b;&b;">
259+
<!ENTITY b "&c;&d;&e;">
260+
<!ENTITY c "xxxxxxxxxx">
261+
<!ENTITY d "yyyyyyyyyy">
262+
<!ENTITY e "zzzzzzzzzz">
263+
]>
264+
<member>&a;</member>
265+
XML
266+
267+
REXML::Security.entity_expansion_text_limit = 90
268+
parser = REXML::Parsers::PullParser.new(source)
269+
while parser.has_next?
270+
parser.pull
271+
end
272+
end
252273
end
253274
end
254275
end

test/test_sax.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,12 @@ def test_sax2
102102
class EntityExpansionLimitTest < Test::Unit::TestCase
103103
def setup
104104
@default_entity_expansion_limit = REXML::Security.entity_expansion_limit
105+
@default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit
105106
end
106107

107108
def teardown
108109
REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
110+
REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit
109111
end
110112

111113
class GeneralEntityTest < self
@@ -182,6 +184,22 @@ def test_with_default_entity
182184
sax.parse
183185
end
184186
end
187+
188+
def test_entity_expansion_text_limit
189+
source = <<-XML
190+
<!DOCTYPE member [
191+
<!ENTITY a "&b;&b;&b;">
192+
<!ENTITY b "&c;&d;&e;">
193+
<!ENTITY c "xxxxxxxxxx">
194+
<!ENTITY d "yyyyyyyyyy">
195+
<!ENTITY e "zzzzzzzzzz">
196+
]>
197+
<member>&a;</member>
198+
XML
199+
200+
REXML::Security.entity_expansion_text_limit = 90
201+
REXML::Parsers::SAX2Parser.new(source).parse
202+
end
185203
end
186204
end
187205

0 commit comments

Comments
 (0)