From f49740ab9f256e4a734b5d77d7ce557cff60f188 Mon Sep 17 00:00:00 2001 From: NAITOH Jun Date: Thu, 22 Aug 2024 22:53:09 +0900 Subject: [PATCH] add Document#entity_expansion_text_limit= ## Why? See: https://github.com/ruby/rexml/issues/192 --- lib/rexml/attribute.rb | 8 ++++++-- lib/rexml/document.rb | 2 ++ lib/rexml/entity.rb | 9 +++++++-- lib/rexml/text.rb | 10 +++++++--- test/test_document.rb | 10 +--------- 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/rexml/attribute.rb b/lib/rexml/attribute.rb index 11893a95..60c6f029 100644 --- a/lib/rexml/attribute.rb +++ b/lib/rexml/attribute.rb @@ -148,8 +148,12 @@ def to_s # have been expanded to their values def value return @unnormalized if @unnormalized - @unnormalized = Text::unnormalize( @normalized, doctype ) - @unnormalized + + if @element and @element.document + @unnormalized = Text::unnormalize(@normalized, doctype, entity_expansion_text_limit: @element.document.entity_expansion_text_limit) + else + @unnormalized = Text::unnormalize(@normalized, doctype) + end end # The normalized value of this attribute. That is, the attribute with diff --git a/lib/rexml/document.rb b/lib/rexml/document.rb index 00057bb2..1bb26669 100644 --- a/lib/rexml/document.rb +++ b/lib/rexml/document.rb @@ -92,6 +92,7 @@ class Document < Element def initialize( source = nil, context = {} ) @entity_expansion_count = 0 @entity_expansion_limit = Security.entity_expansion_limit + @entity_expansion_text_limit = Security.entity_expansion_text_limit super() @context = context return if source.nil? @@ -432,6 +433,7 @@ def Document::entity_expansion_text_limit end attr_reader :entity_expansion_count + attr_accessor :entity_expansion_text_limit def record_entity_expansion @entity_expansion_count += 1 diff --git a/lib/rexml/entity.rb b/lib/rexml/entity.rb index 12bbad3f..a931219b 100644 --- a/lib/rexml/entity.rb +++ b/lib/rexml/entity.rb @@ -71,9 +71,14 @@ def Entity::matches? string # Evaluates to the unnormalized value of this entity; that is, replacing # &ent; entities. def unnormalized - document.record_entity_expansion unless document.nil? return nil if @value.nil? - @unnormalized = Text::unnormalize(@value, parent) + + if document.nil? + @unnormalized = Text::unnormalize(@value, parent) + else + document.record_entity_expansion + @unnormalized = Text::unnormalize(@value, parent, entity_expansion_text_limit: document.entity_expansion_text_limit) + end end #once :unnormalized diff --git a/lib/rexml/text.rb b/lib/rexml/text.rb index 7e0befe9..2642bdcf 100644 --- a/lib/rexml/text.rb +++ b/lib/rexml/text.rb @@ -268,7 +268,11 @@ def inspect # u = Text.new( "sean russell", false, nil, true ) # u.value #-> "sean russell" def value - @unnormalized ||= Text::unnormalize( @string, doctype ) + if document.nil? + @unnormalized ||= Text::unnormalize(@string, doctype) + else + @unnormalized ||= Text::unnormalize(@string, doctype, entity_expansion_text_limit: document.entity_expansion_text_limit) + end end # Sets the contents of this text node. This expects the text to be @@ -411,11 +415,11 @@ def Text::normalize( input, doctype=nil, entity_filter=nil ) end # Unescapes all possible entities - def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil ) + def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil, entity_expansion_text_limit: Security.entity_expansion_text_limit ) sum = 0 string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) { s = Text.expand($&, doctype, filter) - if sum + s.bytesize > Security.entity_expansion_text_limit + if sum + s.bytesize > entity_expansion_text_limit raise "entity expansion has grown too large" else sum += s.bytesize diff --git a/test/test_document.rb b/test/test_document.rb index bac5afb7..cda4354f 100644 --- a/test/test_document.rb +++ b/test/test_document.rb @@ -31,14 +31,6 @@ def test_new end class EntityExpansionLimitTest < Test::Unit::TestCase - def setup - @default_entity_expansion_text_limit = REXML::Security.entity_expansion_text_limit - end - - def teardown - REXML::Security.entity_expansion_text_limit = @default_entity_expansion_text_limit - end - class GeneralEntityTest < self def test_have_value xml = <&a; XML - REXML::Security.entity_expansion_text_limit = 90 doc = REXML::Document.new(xml) + doc.entity_expansion_text_limit = 90 assert_equal(90, doc.root.children.first.value.bytesize) end end