diff --git a/backport-CVE-2023-36617.patch b/backport-CVE-2023-36617.patch deleted file mode 100644 index b1e50fb9670bcb700469e784071cb96f525370c0..0000000000000000000000000000000000000000 --- a/backport-CVE-2023-36617.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 5fbc1d45f17e4bff7cc61a78a7d788aa32ff390a Mon Sep 17 00:00:00 2001 -From: Hiroshi SHIBATA -Date: Thu, 29 Jun 2023 22:24:35 +0900 -Subject: [PATCH] CVE-2023-36617 for Ruby 3.1 (#7996) - -* Bump up v0.12.2 - -* Merge URI-0.10.3 for Bundler ---- - .../vendor/uri/lib/uri/rfc2396_parser.rb | 4 ++-- - .../vendor/uri/lib/uri/rfc3986_parser.rb | 2 +- - lib/uri/rfc2396_parser.rb | 4 ++-- - lib/uri/rfc3986_parser.rb | 2 +- - test/uri/test_parser.rb | 22 +++++++++++++++++++ - 5 files changed, 28 insertions(+), 6 deletions(-) - -diff --git a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb -index 2f8d553..09c22c9 100644 ---- a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb -+++ b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb -@@ -497,8 +497,8 @@ module Bundler::URI - ret = {} - - # for Bundler::URI::split -- ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) -- ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) -+ ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) -+ ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) - - # for Bundler::URI::extract - ret[:URI_REF] = Regexp.new(pattern[:URI_REF]) -diff --git a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb -index d527072..a85511c 100644 ---- a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb -+++ b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb -@@ -100,7 +100,7 @@ module Bundler::URI - QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/, - FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/, - OPAQUE: /\A(?:[^\/].*)?\z/, -- PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/, -+ PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/, - } - end - -diff --git a/lib/uri/rfc2396_parser.rb b/lib/uri/rfc2396_parser.rb -index 76a8f99..00c66cf 100644 ---- a/lib/uri/rfc2396_parser.rb -+++ b/lib/uri/rfc2396_parser.rb -@@ -497,8 +497,8 @@ module URI - ret = {} - - # for URI::split -- ret[:ABS_URI] = Regexp.new('\A\s*' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) -- ret[:REL_URI] = Regexp.new('\A\s*' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) -+ ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) -+ ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) - - # for URI::extract - ret[:URI_REF] = Regexp.new(pattern[:URI_REF]) -diff --git a/lib/uri/rfc3986_parser.rb b/lib/uri/rfc3986_parser.rb -index dd24a40..9b1663d 100644 ---- a/lib/uri/rfc3986_parser.rb -+++ b/lib/uri/rfc3986_parser.rb -@@ -100,7 +100,7 @@ module URI - QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/, - FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/, - OPAQUE: /\A(?:[^\/].*)?\z/, -- PORT: /\A[\x09\x0a\x0c\x0d ]*\d*[\x09\x0a\x0c\x0d ]*\z/, -+ PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/, - } - end - -diff --git a/test/uri/test_parser.rb b/test/uri/test_parser.rb -index 72fb590..cee0acb 100644 ---- a/test/uri/test_parser.rb -+++ b/test/uri/test_parser.rb -@@ -79,4 +79,26 @@ class URI::TestParser < Test::Unit::TestCase - assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com")) - assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]")) - end -+ -+ def test_rfc2822_parse_relative_uri -+ pre = ->(length) { -+ " " * length + "\0" -+ } -+ parser = URI::RFC2396_Parser.new -+ assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |uri| -+ assert_raise(URI::InvalidURIError) do -+ parser.split(uri) -+ end -+ end -+ end -+ -+ def test_rfc3986_port_check -+ pre = ->(length) {"\t" * length + "a"} -+ uri = URI.parse("http://my.example.com") -+ assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |port| -+ assert_raise(URI::InvalidComponentError) do -+ uri.port = port -+ end -+ end -+ end - end --- -2.33.0 - diff --git a/backport-CVE-2024-27281.patch b/backport-CVE-2024-27281.patch deleted file mode 100644 index f9115e85dd005fff772700dbf86a7b3cb4a935f8..0000000000000000000000000000000000000000 --- a/backport-CVE-2024-27281.patch +++ /dev/null @@ -1,91 +0,0 @@ -From d5dbada8a2127d9b6b670dd891eabbb63c48268f Mon Sep 17 00:00:00 2001 -From: Hiroshi SHIBATA -Date: Thu, 21 Mar 2024 15:39:09 +0900 -Subject: [PATCH] Merge RDoc-6.5.1.1 - ---- - lib/rdoc/store.rb | 45 ++++++++++++++++++++++++++------------------- - 1 files changed, 26 insertions(+), 19 deletions(-) - -diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb -index 9fc540d3172bd2..c793e49ed845ed 100644 ---- a/lib/rdoc/store.rb -+++ b/lib/rdoc/store.rb -@@ -556,9 +556,7 @@ def load_all - def load_cache - #orig_enc = @encoding - -- File.open cache_path, 'rb' do |io| -- @cache = Marshal.load io -- end -+ @cache = marshal_load(cache_path) - - load_enc = @cache[:encoding] - -@@ -615,9 +613,7 @@ def load_class klass_name - def load_class_data klass_name - file = class_file klass_name - -- File.open file, 'rb' do |io| -- Marshal.load io -- end -+ marshal_load(file) - rescue Errno::ENOENT => e - error = MissingFileError.new(self, file, klass_name) - error.set_backtrace e.backtrace -@@ -630,14 +626,10 @@ def load_class_data klass_name - def load_method klass_name, method_name - file = method_file klass_name, method_name - -- File.open file, 'rb' do |io| -- obj = Marshal.load io -- obj.store = self -- obj.parent = -- find_class_or_module(klass_name) || load_class(klass_name) unless -- obj.parent -- obj -- end -+ obj = marshal_load(file) -+ obj.store = self -+ obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name) -+ obj - rescue Errno::ENOENT => e - error = MissingFileError.new(self, file, klass_name + method_name) - error.set_backtrace e.backtrace -@@ -650,11 +642,9 @@ def load_method klass_name, method_name - def load_page page_name - file = page_file page_name - -- File.open file, 'rb' do |io| -- obj = Marshal.load io -- obj.store = self -- obj -- end -+ obj = marshal_load(file) -+ obj.store = self -+ obj - rescue Errno::ENOENT => e - error = MissingFileError.new(self, file, page_name) - error.set_backtrace e.backtrace -@@ -976,4 +966,21 @@ def unique_modules - @unique_modules - end - -+ private -+ def marshal_load(file) -+ File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)} -+ end -+ -+ MarshalFilter = proc do |obj| -+ case obj -+ when true, false, nil, Array, Class, Encoding, Hash, Integer, String, Symbol, RDoc::Text -+ else -+ unless obj.class.name.start_with?("RDoc::") -+ raise TypeError, "not permitted class: #{obj.class.name}" -+ end -+ end -+ obj -+ end -+ private_constant :MarshalFilter -+ - end diff --git a/backport-CVE-2024-27282.patch b/backport-CVE-2024-27282.patch deleted file mode 100644 index 1ecd087e37b76efc48bd0242c0186d939f8a139b..0000000000000000000000000000000000000000 --- a/backport-CVE-2024-27282.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 989a2355808a63fc45367785c82ffd46d18c900a Mon Sep 17 00:00:00 2001 -From: Hiroshi SHIBATA -Date: Fri, 12 Apr 2024 15:01:47 +1000 -Subject: [PATCH] Fix Use-After-Free issue for Regexp - -Co-authored-by: Isaac Peka <7493006+isaac-peka@users.noreply.github.com> - - -Reference:https://github.com/ruby/rdoc/commit/989a2355808a63fc45367785c82ffd46d18c900a -Conflict:NA ---- - regexec.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/regexec.c b/regexec.c -index 73694ab14a..140691ad42 100644 ---- a/regexec.c -+++ b/regexec.c -@@ -3449,8 +3449,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, - CASE(OP_MEMORY_END_PUSH_REC) MOP_IN(OP_MEMORY_END_PUSH_REC); - GET_MEMNUM_INC(mem, p); - STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */ -- STACK_PUSH_MEM_END(mem, s); - mem_start_stk[mem] = GET_STACK_INDEX(stkp); -+ STACK_PUSH_MEM_END(mem, s); - MOP_OUT; - JUMP; - --- -2.33.0 - diff --git a/backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.patch b/backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.patch deleted file mode 100644 index c6f1c17752ec26450bc19d35eb3aebbdac884e45..0000000000000000000000000000000000000000 --- a/backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.patch +++ /dev/null @@ -1,372 +0,0 @@ -From e4a067e11235a2ec7a00616d41350485e384ec05 Mon Sep 17 00:00:00 2001 -From: Sutou Kouhei -Date: Thu, 1 Aug 2024 11:51:33 +0900 -Subject: [PATCH] Add 3.3.3 entry - ---- - .../lib/rexml/formatters/pretty.rb | 2 +- - .../lib/rexml/parsers/baseparser.rb | 67 ++++++++++++++----- - .../lib/rexml/parsers/sax2parser.rb | 21 +----- - .../lib/rexml/parsers/streamparser.rb | 4 +- - .bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb | 2 +- - .bundle/gems/rexml-3.2.5/lib/rexml/source.rb | 22 ++++-- - .bundle/gems/rexml-3.2.5/lib/rexml/text.rb | 48 +++++++++---- - 7 files changed, 105 insertions(+), 61 deletions(-) - -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb -index a1198b7..a838d83 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb -@@ -111,7 +111,7 @@ module REXML - # itself, then we don't need a carriage return... which makes this - # logic more complex. - node.children.each { |child| -- next if child == node.children[-1] and child.instance_of?(Text) -+ next if child.instance_of?(Text) - unless child == node.children[0] or child.instance_of?(Text) or - (child == node.children[1] and !node.children[0].writethis) - output << "\n" -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -index 617a3d5..44dc658 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -@@ -124,11 +124,10 @@ module REXML - } - - module Private -- INSTRUCTION_END = /#{NAME}(\s+.*?)?\?>/um - TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um - CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um - ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um -- NAME_PATTERN = /\s*#{NAME}/um -+ NAME_PATTERN = /#{NAME}/um - GEDECL_PATTERN = "\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" - PEDECL_PATTERN = "\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" - ENTITYDECL_PATTERN = /(?:#{GEDECL_PATTERN})|(?:#{PEDECL_PATTERN})/um -@@ -159,6 +158,7 @@ module REXML - def stream=( source ) - @source = SourceFactory.create_from( source ) - @closed = nil -+ @have_root = false - @document_status = nil - @tags = [] - @stack = [] -@@ -241,7 +241,7 @@ module REXML - if @document_status == nil - start_position = @source.position - if @source.match("/um, true) -@@ -311,7 +311,11 @@ module REXML - raise REXML::ParseException.new( "Bad ELEMENT declaration!", @source ) if md.nil? - return [ :elementdecl, "/um, true) -+ unless match_data -+ raise ParseException.new("Malformed XML: Unclosed processing instruction", @source) -+ end -+ content = match_data[1] -+ else -+ content = nil -+ unless @source.match("?>", true) -+ raise ParseException.new("Malformed XML: Unclosed processing instruction", @source) -+ end - end -- if @document_status.nil? and match_data[1] == "xml" -- content = match_data[2] -+ if name == "xml" -+ if @document_status -+ raise ParseException.new("Malformed XML: XML declaration is not at the start", @source) -+ end - version = VERSION.match(content) - version = version[1] unless version.nil? - encoding = ENCODING.match(content) -@@ -664,7 +695,7 @@ module REXML - standalone = standalone[1] unless standalone.nil? - return [ :xmldecl, version, encoding, standalone ] - end -- [:processing_instruction, match_data[1], match_data[2]] -+ [:processing_instruction, name, content] - end - - def parse_attributes(prefixes, curr_ns) -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb -index 01cb469..cec9d2f 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb -@@ -161,25 +161,8 @@ module REXML - end - end - when :text -- #normalized = @parser.normalize( event[1] ) -- #handle( :characters, normalized ) -- copy = event[1].clone -- -- esub = proc { |match| -- if @entities.has_key?($1) -- @entities[$1].gsub(Text::REFERENCE, &esub) -- else -- match -- end -- } -- -- copy.gsub!( Text::REFERENCE, &esub ) -- copy.gsub!( Text::NUMERICENTITY ) {|m| -- m=$1 -- m = "0#{m}" if m[0] == ?x -- [Integer(m)].pack('U*') -- } -- handle( :characters, copy ) -+ unnormalized = @parser.unnormalize( event[1], @entities ) -+ handle( :characters, unnormalized ) - when :entitydecl - handle_entitydecl( event ) - when :processing_instruction, :comment, :attlistdecl, -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb -index 9e0eb0b..fa3ac49 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb -@@ -36,8 +36,8 @@ module REXML - @listener.tag_end( event[1] ) - @tag_stack.pop - when :text -- normalized = @parser.unnormalize( event[1] ) -- @listener.text( normalized ) -+ unnormalized = @parser.unnormalize( event[1] ) -+ @listener.text( unnormalized ) - when :processing_instruction - @listener.instruction( *event[1,2] ) - when :start_doctype -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -index 3af03ec..39e92a5 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -@@ -31,7 +31,7 @@ - module REXML - COPYRIGHT = "Copyright © 2001-2008 Sean Russell " - DATE = "2008/019" -- VERSION = "3.3.1" -+ VERSION = "3.3.3" - REVISION = "" - - Copyright = COPYRIGHT -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb -index 5715c35..ff887fc 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb -@@ -204,10 +204,20 @@ module REXML - end - end - -- def read(term = nil) -+ def read(term = nil, min_bytes = 1) - term = encode(term) if term - begin -- @scanner << readline(term) -+ str = readline(term) -+ @scanner << str -+ read_bytes = str.bytesize -+ begin -+ while read_bytes < min_bytes -+ str = readline(term) -+ @scanner << str -+ read_bytes += str.bytesize -+ end -+ rescue IOError -+ end - true - rescue Exception, NameError - @source = nil -@@ -237,10 +247,9 @@ module REXML - read if @scanner.eos? && @source - end - -- # Note: When specifying a string for 'pattern', it must not include '>' except in the following formats: -- # - ">" -- # - "XXX>" (X is any string excluding '>') - def match( pattern, cons=false ) -+ # To avoid performance issue, we need to increase bytes to read per scan -+ min_bytes = 1 - while true - if cons - md = @scanner.scan(pattern) -@@ -250,7 +259,8 @@ module REXML - break if md - return nil if pattern.is_a?(String) - return nil if @source.nil? -- return nil unless read -+ return nil unless read(nil, min_bytes) -+ min_bytes *= 2 - end - - md.nil? ? nil : @scanner -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb -index b47bad3..7e0befe 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb -@@ -151,25 +151,45 @@ module REXML - end - end - -- # context sensitive -- string.scan(pattern) do -- if $1[-1] != ?; -- raise "Illegal character #{$1.inspect} in raw string #{string.inspect}" -- elsif $1[0] == ?& -- if $5 and $5[0] == ?# -- case ($5[1] == ?x ? $5[2..-1].to_i(16) : $5[1..-1].to_i) -- when *VALID_CHAR -+ pos = 0 -+ while (index = string.index(/<|&/, pos)) -+ if string[index] == "<" -+ raise "Illegal character \"#{string[index]}\" in raw string #{string.inspect}" -+ end -+ -+ unless (end_index = string.index(/[^\s];/, index + 1)) -+ raise "Illegal character \"#{string[index]}\" in raw string #{string.inspect}" -+ end -+ -+ value = string[(index + 1)..end_index] -+ if /\s/.match?(value) -+ raise "Illegal character \"#{string[index]}\" in raw string #{string.inspect}" -+ end -+ -+ if value[0] == "#" -+ character_reference = value[1..-1] -+ -+ unless (/\A(\d+|x[0-9a-fA-F]+)\z/.match?(character_reference)) -+ if character_reference[0] == "x" || character_reference[-1] == "x" -+ raise "Illegal character \"#{string[index]}\" in raw string #{string.inspect}" - else -- raise "Illegal character #{$1.inspect} in raw string #{string.inspect}" -+ raise "Illegal character #{string.inspect} in raw string #{string.inspect}" - end -- # FIXME: below can't work but this needs API change. -- # elsif @parent and $3 and !SUBSTITUTES.include?($1) -- # if !doctype or !doctype.entities.has_key?($3) -- # raise "Undeclared entity '#{$1}' in raw string \"#{string}\"" -- # end - end -+ -+ case (character_reference[0] == "x" ? character_reference[1..-1].to_i(16) : character_reference[0..-1].to_i) -+ when *VALID_CHAR -+ else -+ raise "Illegal character #{string.inspect} in raw string #{string.inspect}" -+ end -+ elsif !(/\A#{Entity::NAME}\z/um.match?(value)) -+ raise "Illegal character \"#{string[index]}\" in raw string #{string.inspect}" - end -+ -+ pos = end_index + 1 - end -+ -+ string - end - - def node_type --- -2.27.0 - diff --git a/backport-CVE-2024-41946.patch b/backport-CVE-2024-41946.patch deleted file mode 100644 index 8970716a3e8ee82419dd30ea01622f0cc5c806e8..0000000000000000000000000000000000000000 --- a/backport-CVE-2024-41946.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 033d1909a8f259d5a7c53681bcaf14f13bcf0368 Mon Sep 17 00:00:00 2001 -From: NAITOH Jun -Date: Thu, 1 Aug 2024 09:20:31 +0900 -Subject: [PATCH] Add support for XML entity expansion limitation in SAX and - pull parsers (#187) -https://github.com/ruby/rexml/commit/033d1909a8f259d5a7c53681bcaf14f13bcf0368 - -- Supported `REXML::Security.entity_expansion_limit=` in SAX and pull parsers -- Supported `REXML::Security.entity_expansion_text_limit=` in SAX and pull parsers ---- - .bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb | 19 ++++++- - .bundle/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb | 4 ++ - .bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb | 4 ++ - 3 files changed, 26 insertions(+), 1 deletions(-) - -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -index 54014e5..c4ddee3 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -@@ -154,6 +154,7 @@ module REXML - self.stream = source - @listeners = [] - @prefixes = Set.new -+ @entity_expansion_count = 0 - end - - def add_listener( listener ) -@@ -161,6 +162,7 @@ module REXML - end - - attr_reader :source -+ attr_reader :entity_expansion_count - - def stream=( source ) - @source = SourceFactory.create_from( source ) -@@ -513,7 +515,9 @@ module REXML - def entity( reference, entities ) - value = nil - value = entities[ reference ] if entities -- if not value -+ if value -+ record_entity_expansion -+ else - value = DEFAULT_ENTITIES[ reference ] - value = value[2] if value - end -@@ -552,12 +556,17 @@ module REXML - } - matches.collect!{|x|x[0]}.compact! - if matches.size > 0 -+ sum = 0 - matches.each do |entity_reference| - unless filter and filter.include?(entity_reference) - entity_value = entity( entity_reference, entities ) - if entity_value - re = Private::DEFAULT_ENTITIES_PATTERNS[entity_reference] || /&#{entity_reference};/ - rv.gsub!( re, entity_value ) -+ sum += rv.bytesize -+ if sum > Security.entity_expansion_text_limit -+ raise "entity expansion has grown too large" -+ end - else - er = DEFAULT_ENTITIES[entity_reference] - rv.gsub!( er[0], er[2] ) if er -@@ -570,6 +579,14 @@ module REXML - end - - private -+ -+ def record_entity_expansion -+ @entity_expansion_count += 1 -+ if @entity_expansion_count > Security.entity_expansion_limit -+ raise "number of entity expansions exceeded, processing aborted." -+ end -+ end -+ - def need_source_encoding_update?(xml_declaration_encoding) - return false if xml_declaration_encoding.nil? - return false if /\AUTF-16\z/i =~ xml_declaration_encoding -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb -index f8b232a..36b4595 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/pullparser.rb -@@ -47,6 +47,10 @@ module REXML - @listeners << listener - end - -+ def entity_expansion_count -+ @parser.entity_expansion_count -+ end -+ - def each - while has_next? - yield self.pull -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb -index 36f98c2..cec9d2f 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb -@@ -22,6 +22,10 @@ module REXML - @parser.source - end - -+ def entity_expansion_count -+ @parser.entity_expansion_count -+ end -+ - def add_listener( listener ) - @parser.add_listener( listener ) - end --- -2.20.1 - diff --git a/backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch b/backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch deleted file mode 100644 index beba07aeeddf52685e2bef2e47b9ad7ccc594a38..0000000000000000000000000000000000000000 --- a/backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch +++ /dev/null @@ -1,524 +0,0 @@ -From 95871f399eda642a022b03550479b7994895c742 Mon Sep 17 00:00:00 2001 -From: Sutou Kouhei -Date: Thu, 22 Aug 2024 09:54:49 +0900 -Subject: [PATCH] Add 3.3.6 entry - ---- - .bundle/gems/rexml-3.2.5/lib/rexml/element.rb | 30 ++-- - .bundle/gems/rexml-3.2.5/lib/rexml/entity.rb | 52 +------ - .../lib/rexml/parsers/baseparser.rb | 139 +++++++++++++----- - .../lib/rexml/parsers/streamparser.rb | 16 +- - .../lib/rexml/parsers/treeparser.rb | 7 - - .bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb | 2 +- - 6 files changed, 131 insertions(+), 115 deletions(-) - -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb -index a5808d7..4e3a60b 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb -@@ -441,9 +441,14 @@ module REXML - # Related: #root_node, #document. - # - def root -- return elements[1] if self.kind_of? Document -- return self if parent.kind_of? Document or parent.nil? -- return parent.root -+ target = self -+ while target -+ return target.elements[1] if target.kind_of? Document -+ parent = target.parent -+ return target if parent.kind_of? Document or parent.nil? -+ target = parent -+ end -+ nil - end - - # :call-seq: -@@ -619,8 +624,12 @@ module REXML - else - prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns' - end -- ns = attributes[ prefix ] -- ns = parent.namespace(prefix) if ns.nil? and parent -+ ns = nil -+ target = self -+ while ns.nil? and target -+ ns = target.attributes[prefix] -+ target = target.parent -+ end - ns = '' if ns.nil? and prefix == 'xmlns' - return ns - end -@@ -2375,17 +2384,6 @@ module REXML - elsif old_attr.kind_of? Hash - old_attr[value.prefix] = value - elsif old_attr.prefix != value.prefix -- # Check for conflicting namespaces -- if value.prefix != "xmlns" and old_attr.prefix != "xmlns" -- old_namespace = old_attr.namespace -- new_namespace = value.namespace -- if old_namespace == new_namespace -- raise ParseException.new( -- "Namespace conflict in adding attribute \"#{value.name}\": "+ -- "Prefix \"#{old_attr.prefix}\" = \"#{old_namespace}\" and "+ -- "prefix \"#{value.prefix}\" = \"#{new_namespace}\"") -- end -- end - store value.name, {old_attr.prefix => old_attr, - value.prefix => value} - else -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb -index 573db69..12bbad3 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb -@@ -12,6 +12,7 @@ module REXML - EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" - NDATADECL = "\\s+NDATA\\s+#{NAME}" - PEREFERENCE = "%#{NAME};" -+ PEREFERENCE_RE = /#{PEREFERENCE}/um - ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))} - PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" - ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" -@@ -19,7 +20,7 @@ module REXML - GEDECL = "" - ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um - -- attr_reader :name, :external, :ref, :ndata, :pubid -+ attr_reader :name, :external, :ref, :ndata, :pubid, :value - - # Create a new entity. Simple entities can be constructed by passing a - # name, value to the constructor; this creates a generic, plain entity -@@ -68,14 +69,11 @@ module REXML - end - - # Evaluates to the unnormalized value of this entity; that is, replacing -- # all entities -- both %ent; and &ent; entities. This differs from -- # +value()+ in that +value+ only replaces %ent; entities. -+ # &ent; entities. - def unnormalized - document.record_entity_expansion unless document.nil? -- v = value() -- return nil if v.nil? -- @unnormalized = Text::unnormalize(v, parent) -- @unnormalized -+ return nil if @value.nil? -+ @unnormalized = Text::unnormalize(@value, parent) - end - - #once :unnormalized -@@ -121,46 +119,6 @@ module REXML - write rv - rv - end -- -- PEREFERENCE_RE = /#{PEREFERENCE}/um -- # Returns the value of this entity. At the moment, only internal entities -- # are processed. If the value contains internal references (IE, -- # %blah;), those are replaced with their values. IE, if the doctype -- # contains: -- # -- # -- # then: -- # doctype.entity('yada').value #-> "nanoo bar nanoo" -- def value -- @resolved_value ||= resolve_value -- end -- -- def parent=(other) -- @resolved_value = nil -- super -- end -- -- private -- def resolve_value -- return nil if @value.nil? -- return @value unless @value.match?(PEREFERENCE_RE) -- -- matches = @value.scan(PEREFERENCE_RE) -- rv = @value.clone -- if @parent -- sum = 0 -- matches.each do |entity_reference| -- entity_value = @parent.entity( entity_reference[0] ) -- if sum + entity_value.bytesize > Security.entity_expansion_text_limit -- raise "entity expansion has grown too large" -- else -- sum += entity_value.bytesize -- end -- rv.gsub!( /%#{entity_reference.join};/um, entity_value ) -- end -- end -- rv -- end - end - - # This is a set of entity constants -- the ones defined in the XML -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -index 44dc658..d11c276 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -@@ -1,12 +1,29 @@ - # frozen_string_literal: true - require_relative '../parseexception' - require_relative '../undefinednamespaceexception' -+require_relative '../security' - require_relative '../source' - require 'set' - require "strscan" - - module REXML - module Parsers -+ unless [].respond_to?(:tally) -+ module EnumerableTally -+ refine Enumerable do -+ def tally -+ counts = {} -+ each do |item| -+ counts[item] ||= 0 -+ counts[item] += 1 -+ end -+ counts -+ end -+ end -+ end -+ using EnumerableTally -+ end -+ - if StringScanner::Version < "3.0.8" - module StringScannerCaptures - refine StringScanner do -@@ -124,6 +141,7 @@ module REXML - } - - module Private -+ PEREFERENCE_PATTERN = /#{PEREFERENCE}/um - TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um - CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um - ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um -@@ -163,7 +181,8 @@ module REXML - @tags = [] - @stack = [] - @entities = [] -- @nsstack = [] -+ @namespaces = {} -+ @namespaces_restore_stack = [] - end - - def position -@@ -231,6 +250,10 @@ module REXML - if @document_status == :in_doctype - raise ParseException.new("Malformed DOCTYPE: unclosed", @source) - end -+ unless @tags.empty? -+ path = "/" + @tags.join("/") -+ raise ParseException.new("Missing end tag for '#{path}'", @source) -+ end - return [ :end_document ] - end - return @stack.shift if @stack.size > 0 -@@ -263,7 +286,6 @@ module REXML - @source.position = start_position - raise REXML::ParseException.new(message, @source) - end -- @nsstack.unshift(Set.new) - name = parse_name(base_error_message) - if @source.match(/\s*\[/um, true) - id = [nil, nil, nil] -@@ -333,6 +355,8 @@ module REXML - match[4] = match[4][1..-2] # HREF - match.delete_at(5) if match.size > 5 # Chop out NDATA decl - # match is [ :entity, name, PUBLIC, pubid, href(, ndata)? ] -+ elsif Private::PEREFERENCE_PATTERN.match?(match[2]) -+ raise REXML::ParseException.new("Parameter entity references forbidden in internal subset: #{match[2]}", @source) - else - match[2] = match[2][1..-2] - match.pop if match.size == 4 -@@ -355,7 +379,7 @@ module REXML - val = attdef[4] if val == "#FIXED " - pairs[attdef[0]] = val - if attdef[0] =~ /^xmlns:(.*)/ -- @nsstack[0] << $1 -+ @namespaces[$1] = val - end - end - end -@@ -408,7 +432,7 @@ module REXML - # here explicitly. - @source.ensure_buffer - if @source.match("/", true) -- @nsstack.shift -+ @namespaces_restore_stack.pop - last_tag = @tags.pop - md = @source.match(Private::CLOSE_PATTERN, true) - if md and !last_tag -@@ -453,18 +477,18 @@ module REXML - @document_status = :in_element - @prefixes.clear - @prefixes << md[2] if md[2] -- @nsstack.unshift(curr_ns=Set.new) -- attributes, closed = parse_attributes(@prefixes, curr_ns) -+ push_namespaces_restore -+ attributes, closed = parse_attributes(@prefixes) - # Verify that all of the prefixes have been defined - for prefix in @prefixes -- unless @nsstack.find{|k| k.member?(prefix)} -+ unless @namespaces.key?(prefix) - raise UndefinedNamespaceException.new(prefix,@source,self) - end - end - - if closed - @closed = tag -- @nsstack.shift -+ pop_namespaces_restore - else - if @tags.empty? and @have_root - raise ParseException.new("Malformed XML: Extra tag at the end of the document (got '<#{tag}')", @source) -@@ -504,15 +528,13 @@ module REXML - private :pull_event - - def entity( reference, entities ) -- value = nil -- value = entities[ reference ] if entities -- if value -- record_entity_expansion -- else -- value = DEFAULT_ENTITIES[ reference ] -- value = value[2] if value -- end -- unnormalize( value, entities ) if value -+ return unless entities -+ -+ value = entities[ reference ] -+ return if value.nil? -+ -+ record_entity_expansion -+ unnormalize( value, entities ) - end - - # Escapes all possible entities -@@ -546,22 +568,29 @@ module REXML - [Integer(m)].pack('U*') - } - matches.collect!{|x|x[0]}.compact! -+ if filter -+ matches.reject! do |entity_reference| -+ filter.include?(entity_reference) -+ end -+ end - if matches.size > 0 -- sum = 0 -- matches.each do |entity_reference| -- unless filter and filter.include?(entity_reference) -- entity_value = entity( entity_reference, entities ) -- if entity_value -- re = Private::DEFAULT_ENTITIES_PATTERNS[entity_reference] || /&#{entity_reference};/ -- rv.gsub!( re, entity_value ) -- sum += rv.bytesize -- if sum > Security.entity_expansion_text_limit -- raise "entity expansion has grown too large" -- end -- else -- er = DEFAULT_ENTITIES[entity_reference] -- rv.gsub!( er[0], er[2] ) if er -+ matches.tally.each do |entity_reference, n| -+ entity_expansion_count_before = @entity_expansion_count -+ entity_value = entity( entity_reference, entities ) -+ if entity_value -+ if n > 1 -+ entity_expansion_count_delta = -+ @entity_expansion_count - entity_expansion_count_before -+ record_entity_expansion(entity_expansion_count_delta * (n - 1)) - end -+ re = Private::DEFAULT_ENTITIES_PATTERNS[entity_reference] || /&#{entity_reference};/ -+ rv.gsub!( re, entity_value ) -+ if rv.bytesize > Security.entity_expansion_text_limit -+ raise "entity expansion has grown too large" -+ end -+ else -+ er = DEFAULT_ENTITIES[entity_reference] -+ rv.gsub!( er[0], er[2] ) if er - end - end - rv.gsub!( Private::DEFAULT_ENTITIES_PATTERNS['amp'], '&' ) -@@ -570,9 +599,34 @@ module REXML - end - - private -+ def add_namespace(prefix, uri) -+ @namespaces_restore_stack.last[prefix] = @namespaces[prefix] -+ if uri.nil? -+ @namespaces.delete(prefix) -+ else -+ @namespaces[prefix] = uri -+ end -+ end -+ -+ def push_namespaces_restore -+ namespaces_restore = {} -+ @namespaces_restore_stack.push(namespaces_restore) -+ namespaces_restore -+ end - -- def record_entity_expansion -- @entity_expansion_count += 1 -+ def pop_namespaces_restore -+ namespaces_restore = @namespaces_restore_stack.pop -+ namespaces_restore.each do |prefix, uri| -+ if uri.nil? -+ @namespaces.delete(prefix) -+ else -+ @namespaces[prefix] = uri -+ end -+ end -+ end -+ -+ def record_entity_expansion(delta=1) -+ @entity_expansion_count += delta - if @entity_expansion_count > Security.entity_expansion_limit - raise "number of entity expansions exceeded, processing aborted." - end -@@ -698,8 +752,9 @@ module REXML - [:processing_instruction, name, content] - end - -- def parse_attributes(prefixes, curr_ns) -+ def parse_attributes(prefixes) - attributes = {} -+ expanded_names = {} - closed = false - while true - if @source.match(">", true) -@@ -741,7 +796,7 @@ module REXML - "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" - raise REXML::ParseException.new( msg, @source, self) - end -- curr_ns << local_part -+ add_namespace(local_part, value) - elsif prefix - prefixes << prefix unless prefix == "xml" - end -@@ -751,6 +806,20 @@ module REXML - raise REXML::ParseException.new(msg, @source, self) - end - -+ unless prefix == "xmlns" -+ uri = @namespaces[prefix] -+ expanded_name = [uri, local_part] -+ existing_prefix = expanded_names[expanded_name] -+ if existing_prefix -+ message = "Namespace conflict in adding attribute " + -+ "\"#{local_part}\": " + -+ "Prefix \"#{existing_prefix}\" = \"#{uri}\" and " + -+ "prefix \"#{prefix}\" = \"#{uri}\"" -+ raise REXML::ParseException.new(message, @source, self) -+ end -+ expanded_names[expanded_name] = prefix -+ end -+ - attributes[name] = value - else - message = "Invalid attribute name: <#{@source.buffer.split(%r{[/>\s]}).first}>" -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb -index fa3ac49..7781fe4 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/streamparser.rb -@@ -7,36 +7,33 @@ module REXML - def initialize source, listener - @listener = listener - @parser = BaseParser.new( source ) -- @tag_stack = [] -+ @entities = {} - end - - def add_listener( listener ) - @parser.add_listener( listener ) - end - -+ def entity_expansion_count -+ @parser.entity_expansion_count -+ end -+ - def parse - # entity string - while true - event = @parser.pull - case event[0] - when :end_document -- unless @tag_stack.empty? -- tag_path = "/" + @tag_stack.join("/") -- raise ParseException.new("Missing end tag for '#{tag_path}'", -- @parser.source) -- end - return - when :start_element -- @tag_stack << event[1] - attrs = event[2].each do |n, v| - event[2][n] = @parser.unnormalize( v ) - end - @listener.tag_start( event[1], attrs ) - when :end_element - @listener.tag_end( event[1] ) -- @tag_stack.pop - when :text -- unnormalized = @parser.unnormalize( event[1] ) -+ unnormalized = @parser.unnormalize( event[1], @entities ) - @listener.text( unnormalized ) - when :processing_instruction - @listener.instruction( *event[1,2] ) -@@ -48,6 +45,7 @@ module REXML - when :comment, :attlistdecl, :cdata, :xmldecl, :elementdecl - @listener.send( event[0].to_s, *event[1..-1] ) - when :entitydecl, :notationdecl -+ @entities[ event[1] ] = event[2] if event.size == 3 - @listener.send( event[0].to_s, event[1..-1] ) - when :externalentity - entity_reference = event[1] -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb -index 0cb6f7c..4565a40 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb -@@ -15,7 +15,6 @@ module REXML - end - - def parse -- tag_stack = [] - entities = nil - begin - while true -@@ -23,19 +22,13 @@ module REXML - #STDERR.puts "TREEPARSER GOT #{event.inspect}" - case event[0] - when :end_document -- unless tag_stack.empty? -- raise ParseException.new("No close tag for #{@build_context.xpath}", -- @parser.source, @parser) -- end - return - when :start_element -- tag_stack.push(event[1]) - el = @build_context = @build_context.add_element( event[1] ) - event[2].each do |key, value| - el.attributes[key]=Attribute.new(key,value,self) - end - when :end_element -- tag_stack.pop - @build_context = @build_context.parent - when :text - if @build_context[-1].instance_of? Text -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -index 39e92a5..99d574b 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -@@ -31,7 +31,7 @@ - module REXML - COPYRIGHT = "Copyright © 2001-2008 Sean Russell " - DATE = "2008/019" -- VERSION = "3.3.3" -+ VERSION = "3.3.6" - REVISION = "" - - Copyright = COPYRIGHT --- -2.27.0 - diff --git a/ruby-3.2.2.tar.xz b/ruby-3.2.5.tar.xz similarity index 64% rename from ruby-3.2.2.tar.xz rename to ruby-3.2.5.tar.xz index 4adb7e55f1f98f4a3517ab8af59443c07e739325..bb28f2070fb5ae2a9f498d26fbf10b3667c2380d 100644 Binary files a/ruby-3.2.2.tar.xz and b/ruby-3.2.5.tar.xz differ diff --git a/ruby.spec b/ruby.spec index 1484200a8f44e8499f4eae7a22778e347d5532f5..8663f90701663764aaf9184875787c74c67b7330 100644 --- a/ruby.spec +++ b/ruby.spec @@ -1,10 +1,10 @@ -%global ruby_version 3.2.2 +%global ruby_version 3.2.5 # Bundled libraries versions -%global rubygems_version 3.4.10 +%global rubygems_version 3.4.19 %global rubygems_molinillo_version 0.8.0 -%global bundler_version 2.4.10 +%global bundler_version 2.4.19 %global bigdecimal_version 3.1.3 %global did_you_mean_version 1.6.3 %global erb_version 4.0.2 @@ -14,31 +14,32 @@ %global json_version 2.6.3 %global openssl_version 3.1.0 %global psych_version 5.0.1 -%global rdoc_version 6.5.0 +%global rdoc_version 6.5.1.1 %global minitest_version 5.16.3 %global power_assert_version 2.0.3 %global rake_version 13.0.6 %global rbs_version 2.8.2 %global test_unit_version 3.5.7 -%global rexml_version 3.2.5 +%global rexml_version 3.3.2 %global rss_version 0.2.9 +%global syntax_suggest_version 1.1.0 %global typeprof_version 0.21.3 -%global net_ftp_version 0.2.0 -%global net_imap_version 0.3.4 +%global net_ftp_version 0.2.1 +%global net_imap_version 0.3.4.1 %global net_pop_version 0.1.2 -%global net_smtp_version 0.3.3 +%global net_smtp_version 0.3.4 %global matrix_version 0.4.2 %global prime_version 0.1.2 %global debug_version 1.7.1 Name: ruby Version: %{ruby_version} -Release: 146 +Release: 147 Summary: Object-oriented scripting language interpreter -License: (Ruby or BSD) and Public Domain and MIT and CC0 and zlib and UCD +License: (Ruby OR BSD-2-Clause) AND (Ruby OR BSD-2-Clause OR GPL-1.0-or-later) AND BSD-3-Clause AND (GPL-3.0-or-later WITH Bison-exception-2.2) AND ISC AND Public Domain AND MIT AND CC0 AND zlib AND Unicode-DFS-2015 URL: https://www.ruby-lang.org/en/ -Source0: http://cache.ruby-lang.org/pub/ruby/3.1/%{name}-%{version}.tar.xz +Source0: https://cache.ruby-lang.org/pub/ruby/3.1/%{name}-%{version}.tar.xz Source1: operating_system.rb Source2: libruby.stp Source3: ruby-exercise.stp @@ -88,19 +89,12 @@ Patch6004: backport-CVE-2019-19246.patch Patch6005: backport-CVE-2019-16161.patch Patch6006: backport-CVE-2019-16162.patch Patch6007: backport-CVE-2019-16163.patch -Patch6015: backport-CVE-2023-36617.patch -Patch6016: backport-CVE-2024-27281.patch -Patch6017: backport-CVE-2024-27282.patch Patch6018: backport-rubygems-rubygems-Drop-to-support-Psych-3.0-bundled-.patch Patch6019: backport-0001-CVE-2024-35221.patch Patch6020: backport-0002-CVE-2024-35221.patch Patch6021: backport-0003-CVE-2024-35221.patch Patch6022: backport-0004-CVE-2024-35221.patch Patch6023: backport-0005-CVE-2024-35221.patch -Patch6024: upgrade-lib-rexml-to-3.3.1.patch -Patch6025: backport-CVE-2024-41946.patch -Patch6026: backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.patch -Patch6027: backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch Patch6028: backport-CVE-2024-47220.patch Provides: %{name}-libs = %{version}-%{release} @@ -136,7 +130,7 @@ Headers and libraries for building extension libraries for extensions Ruby or Ru %package -n rubygems Summary: Ruby standard for wrapping ruby libraries Version: %{rubygems_version} -License: Ruby or MIT +License: (Ruby OR MIT) AND BSD-2-Clause AND (BSD-2-Clause OR Ruby) AND (Ruby OR BSD-2-Clause OR GPL-1.0-or-later) AND MIT Requires: ruby(release) rubygem(openssl) >= 2.1.0 rubygem(psych) >= %{psych_version} Recommends: rubygem(rdoc) >= %{rdoc_version} rubygem(io-console) >= %{io_console_version} Provides: gem = %{version}-%{release} ruby(rubygems) = %{version}-%{release} bundled(rubygem-molinillo) = %{rubygems_molinillo_version} @@ -148,7 +142,7 @@ The Ruby standard for publishing and managing third party libraries provided by %package -n rubygems-devel Summary: For packaging RubyGems Version: %{rubygems_version} -License: Ruby or MIT +License: MIT Requires: ruby(rubygems) = %{version}-%{release} rubygem(json) >= %{json_version} rubygem(rdoc) >= %{rdoc_version} BuildArch: noarch @@ -169,7 +163,7 @@ Rake is a Make-like program implemented in Ruby,Tasks and dependencies are speci %package -n rubygem-rbs Summary: Type signature for Ruby Version: %{rbs_version} -License: Ruby or BSD +License: Ruby OR BSD-2-Clause Requires: ruby(release) Requires: ruby(rubygems) >= %{rubygems_version} Provides: rubygem(rbs) = %{version}-%{release} @@ -181,6 +175,7 @@ definitions. %package irb Summary: The Interactive Ruby Version: %{ruby_version} +License: Ruby OR BSD-2-Clause Requires: %{name}-libs = %{ruby_version} Provides: irb = %{version}-%{release} ruby(irb) = %{version}-%{release} BuildArch: noarch @@ -191,7 +186,7 @@ The irb is acronym for Interactive Ruby,It evaluates ruby expression from the te %package -n rubygem-rdoc Summary: Generate HTML and command-line documentation for Ruby projects Version: %{rdoc_version} -License: GPLv2 and Ruby and MIT and OFL-1.1-RFN +License: GPL-2.0-only AND Ruby AND BSD-3-Clause AND CC-BY-2.5 AND OFL-1.1-RFN Requires: ruby(release) ruby(rubygems) >= %{rubygems_version} ruby(irb) = %{ruby_version} rubygem(io-console) >= %{io_console_version} rubygem(json) >= %{json_version} Provides: rdoc = %{version}-%{release} ri = %{version}-%{release} rubygem(rdoc) = %{version}-%{release} BuildArch: noarch @@ -213,7 +208,7 @@ This package provides documentation for ruby. %package -n rubygem-bigdecimal Summary: Provide arbitrary-precision floating point decimal arithmetic Version: %{bigdecimal_version} -License: Ruby or BSD +License: Ruby OR BSD-2-Clause Requires: ruby(release) ruby(rubygems) >= %{rubygems_version} Provides: rubygem(bigdecimal) = %{version}-%{release} @@ -244,7 +239,7 @@ such as curses and readline. %package -n rubygem-json Summary: JSON implementation as a Ruby extension in C Version: %{json_version} -License: (Ruby or GPLv2) and UCD +License: (Ruby OR BSD-2-Clause) AND Unicode-DFS-2015 Requires: ruby(release) ruby(rubygems) >= %{rubygems_version} Provides: rubygem(json) = %{version}-%{release} @@ -269,7 +264,7 @@ minitest/pride - Show pride in the test and add color to the test output. %package -n rubygem-openssl Summary: Provide SSL、TLS and general purpose cryptography Version: %{openssl_version} -License: Ruby or BSD +License: Ruby or BSD-2-Clause Requires: ruby(release) ruby(rubygems) >= %{rubygems_version} Provides: rubygem(openssl) = %{version}-%{release} @@ -290,7 +285,7 @@ serialize and de-serialize most Ruby objects to and from the YAML format. %package -n rubygem-test-unit Summary: Unit testing framework for Ruby Version: %{test_unit_version} -License: (Ruby or BSD) and (Ruby or BSD or Python) and (Ruby or BSD or LGPLv2+) +License: (Ruby OR BSD-2-Clause) AND (Ruby OR BSD-2-Clause) Requires: ruby(release) ruby(rubygems) >= %{rubygems_version} rubygem(power_assert) Provides: rubygem(test-unit) = %{version}-%{release} BuildArch: noarch @@ -302,7 +297,7 @@ and automated testing are provided in Ruby. %package -n rubygem-rexml Summary: An XML toolkit for Ruby Version: %{rexml_version} -License: BSD +License: BSD-2-Clause URL: https://github.com/ruby/rexml Requires: ruby(release) Requires: ruby(rubygems) >= %{rubygems_version} @@ -323,7 +318,7 @@ features such as XPath. %package -n rubygem-rss Summary: Family of libraries that support various formats of XML "feeds" Version: %{rss_version} -License: BSD +License: BSD-2-Clause URL: https://github.com/ruby/rss Requires: ruby(release) Requires: ruby(rubygems) >= %{rubygems_version} @@ -486,6 +481,9 @@ ln -s %{_libdir}/gems/%{name}/psych-%{psych_version}/psych.so %{buildroot}%{ruby find %{buildroot}%{gem_dir}/extensions/*-%{_target_os}/%{version}/* -maxdepth 0 \ -exec mv '{}' %{buildroot}%{_libdir}/gems/%{name}/ \; || echo "No gem binary extensions to move." +# bundler is built as standalone pacakge +rm -fr %{buildroot}{%{_bindir}/bundle,%{_bindir}/bundler,%{gem_dir}/gems/bundler-%{bundler_version},%{ruby_libdir}/bundler} + sed -i '/^end$/ i\ s.extensions = ["json/ext/parser.so", "json/ext/generator.so"]' %{buildroot}%{gem_dir}/specifications/json-%{json_version}.gemspec @@ -527,7 +525,7 @@ make runruby TESTRUN_SCRIPT=%{SOURCE13} %doc README.md %lang(ja) %license COPYING.ja -%{_bindir}/{erb,ruby} +%{_bindir}/{erb,ruby,syntax_suggest} %dir %{ruby_vendorlibdir} %dir %{ruby_vendorarchdir} @@ -582,6 +580,7 @@ make runruby TESTRUN_SCRIPT=%{SOURCE13} %exclude %{_bindir}/racc %{gem_dir}/gems/erb-%{erb_version}/libexec/erb %{gem_dir}/gems/irb-%{irb_version}/exe/irb +%{gem_dir}/gems/syntax_suggest-%{syntax_suggest_version} %exclude %{gem_dir}/gems/racc-%{racc_version}/bin %{ruby_libdir}/benchmark/version.rb %{ruby_libdir}/csv/core_ext/array.rb @@ -789,11 +788,6 @@ make runruby TESTRUN_SCRIPT=%{SOURCE13} %{gem_dir}/gems/psych-%{psych_version} %{gem_dir}/specifications/psych-%{psych_version}.gemspec -%exclude %{_bindir}/bundle -%exclude %{_bindir}/bundler -%exclude %{gem_dir}/gems/bundler-%{bundler_version}/ -%exclude %{ruby_libdir}/bundler/ - %files -n rubygem-test-unit %{gem_dir}/gems/test-unit-%{test_unit_version} %{gem_dir}/specifications/test-unit-%{test_unit_version}.gemspec @@ -865,7 +859,11 @@ make runruby TESTRUN_SCRIPT=%{SOURCE13} %{gem_dir}/gems/net-imap-%{net_imap_version}/Gemfile %license %{gem_dir}/gems/net-imap-%{net_imap_version}/LICENSE.txt %doc %{gem_dir}/gems/net-imap-%{net_imap_version}/README.md -%{gem_dir}/gems/net-imap-%{net_imap_version} +%{gem_dir}/gems/net-imap-%{net_imap_version}/Rakefile +%doc %{gem_dir}/gems/net-imap-%{net_imap_version}/docs +%{gem_dir}/gems/net-imap-%{net_imap_version}/benchmarks +%{gem_dir}/gems/net-imap-%{net_imap_version}/lib +%{gem_dir}/gems/net-imap-%{net_imap_version}/rakelib %{gem_dir}/specifications/net-imap-%{net_imap_version}.gemspec %dir %{gem_dir}/gems/net-pop-%{net_pop_version} @@ -887,6 +885,9 @@ make runruby TESTRUN_SCRIPT=%{SOURCE13} %{gem_dir}/specifications/matrix-%{matrix_version}.gemspec %changelog +* Tue Oct 15 2024 Funda Wang - 3.2.5-147 +- update to 3.2.5 + * Tue Oct 08 2024 shixuantong - 3.2.2-146 - fix CVE-2024-47220 diff --git a/ruby.yaml b/ruby.yaml index 9a88a56fdd43cdd90c6e4550e70eb3021e853f1c..e0177b6c6d1fdae5057f7b8056feb6b53bc9ff9c 100644 --- a/ruby.yaml +++ b/ruby.yaml @@ -2,4 +2,4 @@ git_url: https://github.com/ruby/ruby version_control: github src_repo: ruby/ruby tag_prefix: "^v" -seperator: "_" +separator: "_" diff --git a/upgrade-lib-rexml-to-3.3.1.patch b/upgrade-lib-rexml-to-3.3.1.patch deleted file mode 100644 index 9ad4dc3a4abebc2b5e9df0bbe1117ff7ef33e31c..0000000000000000000000000000000000000000 --- a/upgrade-lib-rexml-to-3.3.1.patch +++ /dev/null @@ -1,1824 +0,0 @@ -From 20017eea807e8fa386aa5c79ae779004d8b366dd Mon Sep 17 00:00:00 2001 -From: Sutou Kouhei -Date: Tue, 25 Jun 2024 11:26:33 +0900 -Subject: [PATCH] Add 3.3.1 entry - -Backport from https://github.com/ruby/rexml/tree/v3.3.1/lib/rexml - ---- - .../gems/rexml-3.2.5/lib/rexml/attribute.rb | 23 +- - .../gems/rexml-3.2.5/lib/rexml/document.rb | 2 +- - .bundle/gems/rexml-3.2.5/lib/rexml/element.rb | 23 +- - .bundle/gems/rexml-3.2.5/lib/rexml/entity.rb | 40 +- - .../lib/rexml/formatters/pretty.rb | 4 +- - .../gems/rexml-3.2.5/lib/rexml/functions.rb | 3 +- - .../gems/rexml-3.2.5/lib/rexml/namespace.rb | 12 +- - .bundle/gems/rexml-3.2.5/lib/rexml/node.rb | 12 +- - .../rexml-3.2.5/lib/rexml/parseexception.rb | 1 + - .../lib/rexml/parsers/baseparser.rb | 521 ++++++++++-------- - .../lib/rexml/parsers/treeparser.rb | 23 +- - .../lib/rexml/parsers/xpathparser.rb | 222 +++++--- - .bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb | 4 +- - .bundle/gems/rexml-3.2.5/lib/rexml/source.rb | 220 ++++---- - .bundle/gems/rexml-3.2.5/lib/rexml/text.rb | 10 +- - .../rexml-3.2.5/lib/rexml/xpath_parser.rb | 10 +- - 16 files changed, 627 insertions(+), 503 deletions(-) - -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb -index 8933a01..11893a9 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/attribute.rb -@@ -1,4 +1,4 @@ --# frozen_string_literal: false -+# frozen_string_literal: true - require_relative "namespace" - require_relative 'text' - -@@ -13,9 +13,6 @@ module REXML - - # The element to which this attribute belongs - attr_reader :element -- # The normalized value of this attribute. That is, the attribute with -- # entities intact. -- attr_writer :normalized - PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um - - NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um -@@ -122,10 +119,13 @@ module REXML - # b = Attribute.new( "ns:x", "y" ) - # b.to_string # -> "ns:x='y'" - def to_string -+ value = to_s - if @element and @element.context and @element.context[:attribute_quote] == :quote -- %Q^#@expanded_name="#{to_s().gsub(/"/, '"')}"^ -+ value = value.gsub('"', '"') if value.include?('"') -+ %Q^#@expanded_name="#{value}"^ - else -- "#@expanded_name='#{to_s().gsub(/'/, ''')}'" -+ value = value.gsub("'", ''') if value.include?("'") -+ "#@expanded_name='#{value}'" - end - end - -@@ -141,7 +141,6 @@ module REXML - return @normalized if @normalized - - @normalized = Text::normalize( @unnormalized, doctype ) -- @unnormalized = nil - @normalized - end - -@@ -150,10 +149,16 @@ module REXML - def value - return @unnormalized if @unnormalized - @unnormalized = Text::unnormalize( @normalized, doctype ) -- @normalized = nil - @unnormalized - end - -+ # The normalized value of this attribute. That is, the attribute with -+ # entities intact. -+ def normalized=(new_normalized) -+ @normalized = new_normalized -+ @unnormalized = nil -+ end -+ - # Returns a copy of this attribute - def clone - Attribute.new self -@@ -190,7 +195,7 @@ module REXML - end - - def inspect -- rv = "" -+ rv = +"" - write( rv ) - rv - end -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb -index 2edeb98..b1caa02 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/document.rb -@@ -69,7 +69,7 @@ module REXML - # d.to_s # => "FooBar" - # - # When argument +document+ is given, it must be an existing -- # document object, whose context and attributes (but not chidren) -+ # document object, whose context and attributes (but not children) - # are cloned into the new document: - # - # d = REXML::Document.new(xml_string) -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb -index 4c21dbd..a5808d7 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb -@@ -7,14 +7,6 @@ require_relative "xpath" - require_relative "parseexception" - - module REXML -- # An implementation note about namespaces: -- # As we parse, when we find namespaces we put them in a hash and assign -- # them a unique ID. We then convert the namespace prefix for the node -- # to the unique ID. This makes namespace lookup much faster for the -- # cost of extra memory use. We save the namespace prefix for the -- # context node and convert it back when we write it. -- @@namespaces = {} -- - # An \REXML::Element object represents an XML element. - # - # An element: -@@ -989,7 +981,7 @@ module REXML - # :call-seq: - # has_text? -> true or false - # -- # Returns +true if the element has one or more text noded, -+ # Returns +true+ if the element has one or more text noded, - # +false+ otherwise: - # - # d = REXML::Document.new 'text' -@@ -1006,7 +998,7 @@ module REXML - # text(xpath = nil) -> text_string or nil - # - # Returns the text string from the first text node child -- # in a specified element, if it exists, # +nil+ otherwise. -+ # in a specified element, if it exists, +nil+ otherwise. - # - # With no argument, returns the text from the first text node in +self+: - # -@@ -1014,7 +1006,7 @@ module REXML - # d.root.text.class # => String - # d.root.text # => "some text " - # -- # With argument +xpath+, returns text from the the first text node -+ # With argument +xpath+, returns text from the first text node - # in the element that matches +xpath+: - # - # d.root.text(1) # => "this is bold!" -@@ -1284,16 +1276,11 @@ module REXML - # document.root.attribute("x", "a") # => a:x='a:x' - # - def attribute( name, namespace=nil ) -- prefix = nil -- if namespaces.respond_to? :key -- prefix = namespaces.key(namespace) if namespace -- else -- prefix = namespaces.index(namespace) if namespace -- end -+ prefix = namespaces.key(namespace) if namespace - prefix = nil if prefix == 'xmlns' - - ret_val = -- attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" ) -+ attributes.get_attribute( prefix ? "#{prefix}:#{name}" : name ) - - return ret_val unless ret_val.nil? - return nil if prefix.nil? -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb -index 89a9e84..573db69 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb -@@ -132,24 +132,34 @@ module REXML - # then: - # doctype.entity('yada').value #-> "nanoo bar nanoo" - def value -- if @value -- matches = @value.scan(PEREFERENCE_RE) -- rv = @value.clone -- if @parent -- sum = 0 -- matches.each do |entity_reference| -- entity_value = @parent.entity( entity_reference[0] ) -- if sum + entity_value.bytesize > Security.entity_expansion_text_limit -- raise "entity expansion has grown too large" -- else -- sum += entity_value.bytesize -- end -- rv.gsub!( /%#{entity_reference.join};/um, entity_value ) -+ @resolved_value ||= resolve_value -+ end -+ -+ def parent=(other) -+ @resolved_value = nil -+ super -+ end -+ -+ private -+ def resolve_value -+ return nil if @value.nil? -+ return @value unless @value.match?(PEREFERENCE_RE) -+ -+ matches = @value.scan(PEREFERENCE_RE) -+ rv = @value.clone -+ if @parent -+ sum = 0 -+ matches.each do |entity_reference| -+ entity_value = @parent.entity( entity_reference[0] ) -+ if sum + entity_value.bytesize > Security.entity_expansion_text_limit -+ raise "entity expansion has grown too large" -+ else -+ sum += entity_value.bytesize - end -+ rv.gsub!( /%#{entity_reference.join};/um, entity_value ) - end -- return rv - end -- nil -+ rv - end - end - -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb -index 562ef94..a1198b7 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb -@@ -1,4 +1,4 @@ --# frozen_string_literal: false -+# frozen_string_literal: true - require_relative 'default' - - module REXML -@@ -58,7 +58,7 @@ module REXML - skip = false - if compact - if node.children.inject(true) {|s,c| s & c.kind_of?(Text)} -- string = "" -+ string = +"" - old_level = @level - @level = 0 - node.children.each { |child| write( child, string ) } -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb -index 77926bf..4c11461 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/functions.rb -@@ -262,11 +262,10 @@ module REXML - string(string).length - end - -- # UNTESTED - def Functions::normalize_space( string=nil ) - string = string(@@context[:node]) if string.nil? - if string.kind_of? Array -- string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string} -+ string.collect{|x| x.to_s.strip.gsub(/\s+/um, ' ') if x} - else - string.to_s.strip.gsub(/\s+/um, ' ') - end -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb -index 924edf9..2e67252 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/namespace.rb -@@ -1,4 +1,4 @@ --# frozen_string_literal: false -+# frozen_string_literal: true - - require_relative 'xmltokens' - -@@ -10,13 +10,17 @@ module REXML - # The expanded name of the object, valid if name is set - attr_accessor :prefix - include XMLTokens -+ NAME_WITHOUT_NAMESPACE = /\A#{NCNAME_STR}\z/ - NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u - - # Sets the name and the expanded name - def name=( name ) - @expanded_name = name -- case name -- when NAMESPLIT -+ if name.match?(NAME_WITHOUT_NAMESPACE) -+ @prefix = "" -+ @namespace = "" -+ @name = name -+ elsif name =~ NAMESPLIT - if $1 - @prefix = $1 - else -@@ -24,7 +28,7 @@ module REXML - @namespace = "" - end - @name = $2 -- when "" -+ elsif name == "" - @prefix = nil - @namespace = nil - @name = nil -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb -index 081caba..c771db7 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/node.rb -@@ -52,10 +52,14 @@ module REXML - - # Visit all subnodes of +self+ recursively - def each_recursive(&block) # :yields: node -- self.elements.each {|node| -- block.call(node) -- node.each_recursive(&block) -- } -+ stack = [] -+ each { |child| stack.unshift child if child.node_type == :element } -+ until stack.empty? -+ child = stack.pop -+ yield child -+ n = stack.size -+ child.each { |grandchild| stack.insert n, grandchild if grandchild.node_type == :element } -+ end - end - - # Find (and return) first subnode (recursively) for which the block -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb -index 7b16cd1..e57d05f 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parseexception.rb -@@ -29,6 +29,7 @@ module REXML - err << "\nLine: #{line}\n" - err << "Position: #{position}\n" - err << "Last 80 unconsumed characters:\n" -+ err.force_encoding("ASCII-8BIT") - err << @source.buffer[0..80].force_encoding("ASCII-8BIT").gsub(/\n/, ' ') - end - -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -index 305b120..275372e 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb -@@ -1,4 +1,4 @@ --# frozen_string_literal: false -+# frozen_string_literal: true - require_relative '../parseexception' - require_relative '../undefinednamespaceexception' - require_relative '../source' -@@ -7,6 +7,17 @@ require "strscan" - - module REXML - module Parsers -+ if StringScanner::Version < "3.0.8" -+ module StringScannerCaptures -+ refine StringScanner do -+ def captures -+ values_at(*(1...size)) -+ end -+ end -+ end -+ using StringScannerCaptures -+ end -+ - # = Using the Pull Parser - # This API is experimental, and subject to change. - # parser = PullParser.new( "texttxet" ) -@@ -96,7 +107,7 @@ module REXML - ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" - PEDECL = "" - GEDECL = "" -- ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um -+ ENTITYDECL = /\s*(?:#{GEDECL})|\s*(?:#{PEDECL})/um - - NOTATIONDECL_START = /\A\s* [/'/, "'", "'", /'/] - } - -+ module Private -+ INSTRUCTION_END = /#{NAME}(\s+.*?)?\?>/um -+ TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um -+ CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um -+ ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um -+ NAME_PATTERN = /\s*#{NAME}/um -+ GEDECL_PATTERN = "\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" -+ PEDECL_PATTERN = "\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" -+ ENTITYDECL_PATTERN = /(?:#{GEDECL_PATTERN})|(?:#{PEDECL_PATTERN})/um -+ CARRIAGE_RETURN_NEWLINE_PATTERN = /\r\n?/ -+ CHARACTER_REFERENCES = /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ -+ DEFAULT_ENTITIES_PATTERNS = {} -+ default_entities = ['gt', 'lt', 'quot', 'apos', 'amp'] -+ default_entities.each do |term| -+ DEFAULT_ENTITIES_PATTERNS[term] = /&#{term};/ -+ end -+ end -+ private_constant :Private -+ - def initialize( source ) - self.stream = source - @listeners = [] -+ @prefixes = Set.new - end - - def add_listener( listener ) -@@ -180,6 +211,8 @@ module REXML - - # Returns the next event. This is a +PullEvent+ object. - def pull -+ @source.drop_parsed_content -+ - pull_event.tap do |event| - @listeners.each do |listener| - listener.receive event -@@ -192,236 +225,251 @@ module REXML - x, @closed = @closed, nil - return [ :end_element, x ] - end -- return [ :end_document ] if empty? -+ if empty? -+ if @document_status == :in_doctype -+ raise ParseException.new("Malformed DOCTYPE: unclosed", @source) -+ end -+ return [ :end_document ] -+ end - return @stack.shift if @stack.size > 0 - #STDERR.puts @source.encoding - #STDERR.puts "BUFFER = #{@source.buffer.inspect}" -+ -+ @source.ensure_buffer - if @document_status == nil -- word = @source.match( /\A((?:\s+)|(?:<[^>]*>))/um ) -- word = word[1] unless word.nil? -- #STDERR.puts "WORD = #{word.inspect}" -- case word -- when COMMENT_START -- return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ] -- when XMLDECL_START -- #STDERR.puts "XMLDECL" -- results = @source.match( XMLDECL_PATTERN, true )[1] -- version = VERSION.match( results ) -- version = version[1] unless version.nil? -- encoding = ENCODING.match(results) -- encoding = encoding[1] unless encoding.nil? -- if need_source_encoding_update?(encoding) -- @source.encoding = encoding -- end -- if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding -- encoding = "UTF-16" -- end -- standalone = STANDALONE.match(results) -- standalone = standalone[1] unless standalone.nil? -- return [ :xmldecl, version, encoding, standalone ] -- when INSTRUCTION_START -- return process_instruction -- when DOCTYPE_START -- base_error_message = "Malformed DOCTYPE" -- @source.match(DOCTYPE_START, true) -- @nsstack.unshift(curr_ns=Set.new) -- name = parse_name(base_error_message) -- if @source.match(/\A\s*\[/um, true) -- id = [nil, nil, nil] -- @document_status = :in_doctype -- elsif @source.match(/\A\s*>/um, true) -- id = [nil, nil, nil] -- @document_status = :after_doctype -- else -- id = parse_id(base_error_message, -- accept_external_id: true, -- accept_public_id: false) -- if id[0] == "SYSTEM" -- # For backward compatibility -- id[1], id[2] = id[2], nil -+ start_position = @source.position -+ if @source.match("/um, true) -+ if md.nil? -+ raise REXML::ParseException.new("Unclosed comment", @source) -+ end -+ if /--|-\z/.match?(md[1]) -+ raise REXML::ParseException.new("Malformed comment", @source) - end -- if @source.match(/\A\s*\[/um, true) -+ return [ :comment, md[1] ] -+ elsif @source.match("DOCTYPE", true) -+ base_error_message = "Malformed DOCTYPE" -+ unless @source.match(/\s+/um, true) -+ if @source.match(">") -+ message = "#{base_error_message}: name is missing" -+ else -+ message = "#{base_error_message}: invalid name" -+ end -+ @source.position = start_position -+ raise REXML::ParseException.new(message, @source) -+ end -+ @nsstack.unshift(Set.new) -+ name = parse_name(base_error_message) -+ if @source.match(/\s*\[/um, true) -+ id = [nil, nil, nil] - @document_status = :in_doctype -- elsif @source.match(/\A\s*>/um, true) -+ elsif @source.match(/\s*>/um, true) -+ id = [nil, nil, nil] - @document_status = :after_doctype -+ @source.ensure_buffer - else -- message = "#{base_error_message}: garbage after external ID" -- raise REXML::ParseException.new(message, @source) -+ id = parse_id(base_error_message, -+ accept_external_id: true, -+ accept_public_id: false) -+ if id[0] == "SYSTEM" -+ # For backward compatibility -+ id[1], id[2] = id[2], nil -+ end -+ if @source.match(/\s*\[/um, true) -+ @document_status = :in_doctype -+ elsif @source.match(/\s*>/um, true) -+ @document_status = :after_doctype -+ @source.ensure_buffer -+ else -+ message = "#{base_error_message}: garbage after external ID" -+ raise REXML::ParseException.new(message, @source) -+ end - end -- end -- args = [:start_doctype, name, *id] -- if @document_status == :after_doctype -- @source.match(/\A\s*/um, true) -- @stack << [ :end_doctype ] -- end -- return args -- when /\A\s+/ -- else -- @document_status = :after_doctype -- if @source.encoding == "UTF-8" -- @source.buffer.force_encoding(::Encoding::UTF_8) -+ args = [:start_doctype, name, *id] -+ if @document_status == :after_doctype -+ @source.match(/\s*/um, true) -+ @stack << [ :end_doctype ] -+ end -+ return args -+ else -+ message = "Invalid XML" -+ raise REXML::ParseException.new(message, @source) - end - end - end - if @document_status == :in_doctype -- md = @source.match(/\A\s*(.*?>)/um) -- case md[1] -- when SYSTEMENTITY -- match = @source.match( SYSTEMENTITY, true )[1] -- return [ :externalentity, match ] -- -- when ELEMENTDECL_START -- return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ] -- -- when ENTITY_START -- match = @source.match( ENTITYDECL, true ).to_a.compact -- match[0] = :entitydecl -- ref = false -- if match[1] == '%' -- ref = true -- match.delete_at 1 -- end -- # Now we have to sort out what kind of entity reference this is -- if match[2] == 'SYSTEM' -- # External reference -- match[3] = match[3][1..-2] # PUBID -- match.delete_at(4) if match.size > 4 # Chop out NDATA decl -- # match is [ :entity, name, SYSTEM, pubid(, ndata)? ] -- elsif match[2] == 'PUBLIC' -- # External reference -- match[3] = match[3][1..-2] # PUBID -- match[4] = match[4][1..-2] # HREF -- match.delete_at(5) if match.size > 5 # Chop out NDATA decl -- # match is [ :entity, name, PUBLIC, pubid, href(, ndata)? ] -- else -- match[2] = match[2][1..-2] -- match.pop if match.size == 4 -- # match is [ :entity, name, value ] -- end -- match << '%' if ref -- return match -- when ATTLISTDECL_START -- md = @source.match( ATTLISTDECL_PATTERN, true ) -- raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil? -- element = md[1] -- contents = md[0] -- -- pairs = {} -- values = md[0].scan( ATTDEF_RE ) -- values.each do |attdef| -- unless attdef[3] == "#IMPLIED" -- attdef.compact! -- val = attdef[3] -- val = attdef[4] if val == "#FIXED " -- pairs[attdef[0]] = val -- if attdef[0] =~ /^xmlns:(.*)/ -- @nsstack[0] << $1 -- end -+ @source.match(/\s*/um, true) # skip spaces -+ start_position = @source.position -+ if @source.match("/um, true) -+ raise REXML::ParseException.new( "Bad ELEMENT declaration!", @source ) if md.nil? -+ return [ :elementdecl, "/um) -- message = "#{base_error_message}: name is missing" -+ # Now we have to sort out what kind of entity reference this is -+ if match[2] == 'SYSTEM' -+ # External reference -+ match[3] = match[3][1..-2] # PUBID -+ match.delete_at(4) if match.size > 4 # Chop out NDATA decl -+ # match is [ :entity, name, SYSTEM, pubid(, ndata)? ] -+ elsif match[2] == 'PUBLIC' -+ # External reference -+ match[3] = match[3][1..-2] # PUBID -+ match[4] = match[4][1..-2] # HREF -+ match.delete_at(5) if match.size > 5 # Chop out NDATA decl -+ # match is [ :entity, name, PUBLIC, pubid, href(, ndata)? ] - else -- message = "#{base_error_message}: invalid declaration name" -+ match[2] = match[2][1..-2] -+ match.pop if match.size == 4 -+ # match is [ :entity, name, value ] - end -- raise REXML::ParseException.new(message, @source) -- end -- name = parse_name(base_error_message) -- id = parse_id(base_error_message, -- accept_external_id: true, -- accept_public_id: true) -- unless @source.match(/\A\s*>/um, true) -- message = "#{base_error_message}: garbage before end >" -- raise REXML::ParseException.new(message, @source) -+ match << '%' if ref -+ return match -+ elsif @source.match("ATTLIST", true) -+ md = @source.match(Private::ATTLISTDECL_END, true) -+ raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil? -+ element = md[1] -+ contents = md[0] -+ -+ pairs = {} -+ values = md[0].scan( ATTDEF_RE ) -+ values.each do |attdef| -+ unless attdef[3] == "#IMPLIED" -+ attdef.compact! -+ val = attdef[3] -+ val = attdef[4] if val == "#FIXED " -+ pairs[attdef[0]] = val -+ if attdef[0] =~ /^xmlns:(.*)/ -+ @nsstack[0] << $1 -+ end -+ end -+ end -+ return [ :attlistdecl, element, pairs, contents ] -+ elsif @source.match("NOTATION", true) -+ base_error_message = "Malformed notation declaration" -+ unless @source.match(/\s+/um, true) -+ if @source.match(">") -+ message = "#{base_error_message}: name is missing" -+ else -+ message = "#{base_error_message}: invalid name" -+ end -+ @source.position = start_position -+ raise REXML::ParseException.new(message, @source) -+ end -+ name = parse_name(base_error_message) -+ id = parse_id(base_error_message, -+ accept_external_id: true, -+ accept_public_id: true) -+ unless @source.match(/\s*>/um, true) -+ message = "#{base_error_message}: garbage before end >" -+ raise REXML::ParseException.new(message, @source) -+ end -+ return [:notationdecl, name, *id] -+ elsif md = @source.match(/--(.*?)-->/um, true) -+ case md[1] -+ when /--/, /-\z/ -+ raise REXML::ParseException.new("Malformed comment", @source) -+ end -+ return [ :comment, md[1] ] if md - end -- return [:notationdecl, name, *id] -- when DOCTYPE_END -+ elsif match = @source.match(/(%.*?;)\s*/um, true) -+ return [ :externalentity, match[1] ] -+ elsif @source.match(/\]\s*>/um, true) - @document_status = :after_doctype -- @source.match( DOCTYPE_END, true ) - return [ :end_doctype ] - end -+ if @document_status == :in_doctype -+ raise ParseException.new("Malformed DOCTYPE: invalid declaration", @source) -+ end - end - if @document_status == :after_doctype -- @source.match(/\A\s*/um, true) -+ @source.match(/\s*/um, true) - end - begin -- @source.read if @source.buffer.size<2 -- if @source.buffer[0] == ?< -- if @source.buffer[1] == ?/ -+ start_position = @source.position -+ if @source.match("<", true) -+ # :text's read_until may remain only "<" in buffer. In the -+ # case, buffer is empty here. So we need to fill buffer -+ # here explicitly. -+ @source.ensure_buffer -+ if @source.match("/", true) - @nsstack.shift - last_tag = @tags.pop -- md = @source.match( CLOSE_MATCH, true ) -+ md = @source.match(Private::CLOSE_PATTERN, true) - if md and !last_tag - message = "Unexpected top-level end tag (got '#{md[1]}')" - raise REXML::ParseException.new(message, @source) - end - if md.nil? or last_tag != md[1] - message = "Missing end tag for '#{last_tag}'" -- message << " (got '#{md[1]}')" if md -+ message += " (got '#{md[1]}')" if md -+ @source.position = start_position if md.nil? - raise REXML::ParseException.new(message, @source) - end - return [ :end_element, last_tag ] -- elsif @source.buffer[1] == ?! -- md = @source.match(/\A(\s*[^>]*>)/um) -+ elsif @source.match("!", true) -+ md = @source.match(/([^>]*>)/um) - #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}" - raise REXML::ParseException.new("Malformed node", @source) unless md -- if md[0][2] == ?- -- md = @source.match( COMMENT_PATTERN, true ) -+ if md[0][0] == ?- -+ md = @source.match(/--(.*?)-->/um, true) - -- case md[1] -- when /--/, /-\z/ -+ if md.nil? || /--|-\z/.match?(md[1]) - raise REXML::ParseException.new("Malformed comment", @source) - end - -- return [ :comment, md[1] ] if md -+ return [ :comment, md[1] ] - else -- md = @source.match( CDATA_PATTERN, true ) -+ md = @source.match(/\[CDATA\[(.*?)\]\]>/um, true) - return [ :cdata, md[1] ] if md - end - raise REXML::ParseException.new( "Declarations can only occur "+ - "in the doctype declaration.", @source) -- elsif @source.buffer[1] == ?? -- return process_instruction -+ elsif @source.match("?", true) -+ return process_instruction(start_position) - else - # Get the next tag -- md = @source.match(TAG_MATCH, true) -+ md = @source.match(Private::TAG_PATTERN, true) - unless md -+ @source.position = start_position - raise REXML::ParseException.new("malformed XML: missing tag start", @source) - end -+ tag = md[1] - @document_status = :in_element -- prefixes = Set.new -- prefixes << md[2] if md[2] -+ @prefixes.clear -+ @prefixes << md[2] if md[2] - @nsstack.unshift(curr_ns=Set.new) -- attributes, closed = parse_attributes(prefixes, curr_ns) -+ attributes, closed = parse_attributes(@prefixes, curr_ns) - # Verify that all of the prefixes have been defined -- for prefix in prefixes -+ for prefix in @prefixes - unless @nsstack.find{|k| k.member?(prefix)} - raise UndefinedNamespaceException.new(prefix,@source,self) - end - end - - if closed -- @closed = md[1] -+ @closed = tag - @nsstack.shift - else -- @tags.push( md[1] ) -+ @tags.push( tag ) - end -- return [ :start_element, md[1], attributes ] -+ return [ :start_element, tag, attributes ] - end - else -- md = @source.match( TEXT_PATTERN, true ) -- if md[0].length == 0 -- @source.match( /(\s+)/, true ) -+ text = @source.read_until("<") -+ if text.chomp!("<") -+ @source.position -= "<".bytesize - end -- #STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0 -- #return [ :text, "" ] if md[0].length == 0 -- # unnormalized = Text::unnormalize( md[1], self ) -- # return PullEvent.new( :text, md[1], unnormalized ) -- return [ :text, md[1] ] -+ return [ :text, text ] - end - rescue REXML::UndefinedNamespaceException - raise -@@ -463,11 +511,10 @@ module REXML - - # Unescapes all possible entities - def unnormalize( string, entities=nil, filter=nil ) -- rv = string.clone -- rv.gsub!( /\r\n?/, "\n" ) -+ rv = string.gsub( Private::CARRIAGE_RETURN_NEWLINE_PATTERN, "\n" ) - matches = rv.scan( REFERENCE_RE ) - return rv if matches.size == 0 -- rv.gsub!( /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ ) { -+ rv.gsub!( Private::CHARACTER_REFERENCES ) { - m=$1 - m = "0#{m}" if m[0] == ?x - [Integer(m)].pack('U*') -@@ -478,7 +525,7 @@ module REXML - unless filter and filter.include?(entity_reference) - entity_value = entity( entity_reference, entities ) - if entity_value -- re = /&#{entity_reference};/ -+ re = Private::DEFAULT_ENTITIES_PATTERNS[entity_reference] || /&#{entity_reference};/ - rv.gsub!( re, entity_value ) - else - er = DEFAULT_ENTITIES[entity_reference] -@@ -486,7 +533,7 @@ module REXML - end - end - end -- rv.gsub!( /&/, '&' ) -+ rv.gsub!( Private::DEFAULT_ENTITIES_PATTERNS['amp'], '&' ) - end - rv - end -@@ -499,9 +546,9 @@ module REXML - end - - def parse_name(base_error_message) -- md = @source.match(/\A\s*#{NAME}/um, true) -+ md = @source.match(Private::NAME_PATTERN, true) - unless md -- if @source.match(/\A\s*\S/um) -+ if @source.match(/\s*\S/um) - message = "#{base_error_message}: invalid name" - else - message = "#{base_error_message}: name is missing" -@@ -577,97 +624,91 @@ module REXML - end - end - -- def process_instruction -- match_data = @source.match(INSTRUCTION_PATTERN, true) -+ def process_instruction(start_position) -+ match_data = @source.match(Private::INSTRUCTION_END, true) - unless match_data - message = "Invalid processing instruction node" -+ @source.position = start_position - raise REXML::ParseException.new(message, @source) - end -+ if @document_status.nil? and match_data[1] == "xml" -+ content = match_data[2] -+ version = VERSION.match(content) -+ version = version[1] unless version.nil? -+ encoding = ENCODING.match(content) -+ encoding = encoding[1] unless encoding.nil? -+ if need_source_encoding_update?(encoding) -+ @source.encoding = encoding -+ end -+ if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding -+ encoding = "UTF-16" -+ end -+ standalone = STANDALONE.match(content) -+ standalone = standalone[1] unless standalone.nil? -+ return [ :xmldecl, version, encoding, standalone ] -+ end - [:processing_instruction, match_data[1], match_data[2]] - end - - def parse_attributes(prefixes, curr_ns) - attributes = {} - closed = false -- match_data = @source.match(/^(.*?)(\/)?>/um, true) -- if match_data.nil? -- message = "Start tag isn't ended" -- raise REXML::ParseException.new(message, @source) -- end -- -- raw_attributes = match_data[1] -- closed = !match_data[2].nil? -- return attributes, closed if raw_attributes.nil? -- return attributes, closed if raw_attributes.empty? -- -- scanner = StringScanner.new(raw_attributes) -- until scanner.eos? -- if scanner.scan(/\s+/) -- break if scanner.eos? -- end -- -- pos = scanner.pos -- loop do -- break if scanner.scan(ATTRIBUTE_PATTERN) -- unless scanner.scan(QNAME) -- message = "Invalid attribute name: <#{scanner.rest}>" -- raise REXML::ParseException.new(message, @source) -- end -- name = scanner[0] -- unless scanner.scan(/\s*=\s*/um) -+ while true -+ if @source.match(">", true) -+ return attributes, closed -+ elsif @source.match("/>", true) -+ closed = true -+ return attributes, closed -+ elsif match = @source.match(QNAME, true) -+ name = match[1] -+ prefix = match[2] -+ local_part = match[3] -+ -+ unless @source.match(/\s*=\s*/um, true) - message = "Missing attribute equal: <#{name}>" - raise REXML::ParseException.new(message, @source) - end -- quote = scanner.scan(/['"]/) -- unless quote -+ unless match = @source.match(/(['"])/, true) - message = "Missing attribute value start quote: <#{name}>" - raise REXML::ParseException.new(message, @source) - end -- unless scanner.scan(/.*#{Regexp.escape(quote)}/um) -- match_data = @source.match(/^(.*?)(\/)?>/um, true) -- if match_data -- scanner << "/" if closed -- scanner << ">" -- scanner << match_data[1] -- scanner.pos = pos -- closed = !match_data[2].nil? -- next -- end -- message = -- "Missing attribute value end quote: <#{name}>: <#{quote}>" -+ quote = match[1] -+ start_position = @source.position -+ value = @source.read_until(quote) -+ unless value.chomp!(quote) -+ @source.position = start_position -+ message = "Missing attribute value end quote: <#{name}>: <#{quote}>" - raise REXML::ParseException.new(message, @source) - end -- end -- name = scanner[1] -- prefix = scanner[2] -- local_part = scanner[3] -- # quote = scanner[4] -- value = scanner[5] -- if prefix == "xmlns" -- if local_part == "xml" -- if value != "http://www.w3.org/XML/1998/namespace" -- msg = "The 'xml' prefix must not be bound to any other namespace "+ -+ @source.match(/\s*/um, true) -+ if prefix == "xmlns" -+ if local_part == "xml" -+ if value != "http://www.w3.org/XML/1998/namespace" -+ msg = "The 'xml' prefix must not be bound to any other namespace "+ -+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" -+ raise REXML::ParseException.new( msg, @source, self ) -+ end -+ elsif local_part == "xmlns" -+ msg = "The 'xmlns' prefix must not be declared "+ - "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" -- raise REXML::ParseException.new( msg, @source, self ) -+ raise REXML::ParseException.new( msg, @source, self) - end -- elsif local_part == "xmlns" -- msg = "The 'xmlns' prefix must not be declared "+ -- "(http://www.w3.org/TR/REC-xml-names/#ns-decl)" -- raise REXML::ParseException.new( msg, @source, self) -+ curr_ns << local_part -+ elsif prefix -+ prefixes << prefix unless prefix == "xml" - end -- curr_ns << local_part -- elsif prefix -- prefixes << prefix unless prefix == "xml" -- end - -- if attributes.has_key?(name) -- msg = "Duplicate attribute #{name.inspect}" -- raise REXML::ParseException.new(msg, @source, self) -- end -+ if attributes[name] -+ msg = "Duplicate attribute #{name.inspect}" -+ raise REXML::ParseException.new(msg, @source, self) -+ end - -- attributes[name] = value -+ attributes[name] = value -+ else -+ message = "Invalid attribute name: <#{@source.buffer.split(%r{[/>\s]}).first}>" -+ raise REXML::ParseException.new(message, @source) -+ end - end -- return attributes, closed - end - end - end -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb -index bf9a425..0cb6f7c 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/treeparser.rb -@@ -16,7 +16,6 @@ module REXML - - def parse - tag_stack = [] -- in_doctype = false - entities = nil - begin - while true -@@ -39,17 +38,15 @@ module REXML - tag_stack.pop - @build_context = @build_context.parent - when :text -- if not in_doctype -- if @build_context[-1].instance_of? Text -- @build_context[-1] << event[1] -- else -- @build_context.add( -- Text.new(event[1], @build_context.whitespace, nil, true) -- ) unless ( -- @build_context.ignore_whitespace_nodes and -- event[1].strip.size==0 -- ) -- end -+ if @build_context[-1].instance_of? Text -+ @build_context[-1] << event[1] -+ else -+ @build_context.add( -+ Text.new(event[1], @build_context.whitespace, nil, true) -+ ) unless ( -+ @build_context.ignore_whitespace_nodes and -+ event[1].strip.size==0 -+ ) - end - when :comment - c = Comment.new( event[1] ) -@@ -60,14 +57,12 @@ module REXML - when :processing_instruction - @build_context.add( Instruction.new( event[1], event[2] ) ) - when :end_doctype -- in_doctype = false - entities.each { |k,v| entities[k] = @build_context.entities[k].value } - @build_context = @build_context.parent - when :start_doctype - doctype = DocType.new( event[1..-1], @build_context ) - @build_context = doctype - entities = {} -- in_doctype = true - when :attlistdecl - n = AttlistDecl.new( event[1..-1] ) - @build_context.add( n ) -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb -index d92678f..bd3b685 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/xpathparser.rb -@@ -1,4 +1,5 @@ - # frozen_string_literal: false -+ - require_relative '../namespace' - require_relative '../xmltokens' - -@@ -38,108 +39,143 @@ module REXML - parsed - end - -- def abbreviate( path ) -- path = path.kind_of?(String) ? parse( path ) : path -- string = "" -- document = false -- while path.size > 0 -- op = path.shift -+ def abbreviate(path_or_parsed) -+ if path_or_parsed.kind_of?(String) -+ parsed = parse(path_or_parsed) -+ else -+ parsed = path_or_parsed -+ end -+ components = [] -+ component = nil -+ while parsed.size > 0 -+ op = parsed.shift - case op - when :node -+ component << "node()" - when :attribute -- string << "/" if string.size > 0 -- string << "@" -+ component = "@" -+ components << component - when :child -- string << "/" if string.size > 0 -+ component = "" -+ components << component - when :descendant_or_self -- string << "/" -+ next_op = parsed[0] -+ if next_op == :node -+ parsed.shift -+ component = "" -+ components << component -+ else -+ component = "descendant-or-self::" -+ components << component -+ end - when :self -- string << "." -+ next_op = parsed[0] -+ if next_op == :node -+ parsed.shift -+ components << "." -+ else -+ component = "self::" -+ components << component -+ end - when :parent -- string << ".." -+ next_op = parsed[0] -+ if next_op == :node -+ parsed.shift -+ components << ".." -+ else -+ component = "parent::" -+ components << component -+ end - when :any -- string << "*" -+ component << "*" - when :text -- string << "text()" -+ component << "text()" - when :following, :following_sibling, - :ancestor, :ancestor_or_self, :descendant, - :namespace, :preceding, :preceding_sibling -- string << "/" unless string.size == 0 -- string << op.to_s.tr("_", "-") -- string << "::" -+ component = op.to_s.tr("_", "-") << "::" -+ components << component - when :qname -- prefix = path.shift -- name = path.shift -- string << prefix+":" if prefix.size > 0 -- string << name -+ prefix = parsed.shift -+ name = parsed.shift -+ component << prefix+":" if prefix.size > 0 -+ component << name - when :predicate -- string << '[' -- string << predicate_to_string( path.shift ) {|x| abbreviate( x ) } -- string << ']' -+ component << '[' -+ component << predicate_to_path(parsed.shift) {|x| abbreviate(x)} -+ component << ']' - when :document -- document = true -+ components << "" - when :function -- string << path.shift -- string << "( " -- string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )} -- string << " )" -+ component << parsed.shift -+ component << "( " -+ component << predicate_to_path(parsed.shift[0]) {|x| abbreviate(x)} -+ component << " )" - when :literal -- string << %Q{ "#{path.shift}" } -+ component << quote_literal(parsed.shift) - else -- string << "/" unless string.size == 0 -- string << "UNKNOWN(" -- string << op.inspect -- string << ")" -+ component << "UNKNOWN(" -+ component << op.inspect -+ component << ")" - end - end -- string = "/"+string if document -- return string -+ case components -+ when [""] -+ "/" -+ when ["", ""] -+ "//" -+ else -+ components.join("/") -+ end - end - -- def expand( path ) -- path = path.kind_of?(String) ? parse( path ) : path -- string = "" -+ def expand(path_or_parsed) -+ if path_or_parsed.kind_of?(String) -+ parsed = parse(path_or_parsed) -+ else -+ parsed = path_or_parsed -+ end -+ path = "" - document = false -- while path.size > 0 -- op = path.shift -+ while parsed.size > 0 -+ op = parsed.shift - case op - when :node -- string << "node()" -+ path << "node()" - when :attribute, :child, :following, :following_sibling, - :ancestor, :ancestor_or_self, :descendant, :descendant_or_self, - :namespace, :preceding, :preceding_sibling, :self, :parent -- string << "/" unless string.size == 0 -- string << op.to_s.tr("_", "-") -- string << "::" -+ path << "/" unless path.size == 0 -+ path << op.to_s.tr("_", "-") -+ path << "::" - when :any -- string << "*" -+ path << "*" - when :qname -- prefix = path.shift -- name = path.shift -- string << prefix+":" if prefix.size > 0 -- string << name -+ prefix = parsed.shift -+ name = parsed.shift -+ path << prefix+":" if prefix.size > 0 -+ path << name - when :predicate -- string << '[' -- string << predicate_to_string( path.shift ) { |x| expand(x) } -- string << ']' -+ path << '[' -+ path << predicate_to_path( parsed.shift ) { |x| expand(x) } -+ path << ']' - when :document - document = true - else -- string << "/" unless string.size == 0 -- string << "UNKNOWN(" -- string << op.inspect -- string << ")" -+ path << "UNKNOWN(" -+ path << op.inspect -+ path << ")" - end - end -- string = "/"+string if document -- return string -+ path = "/"+path if document -+ path - end - -- def predicate_to_string( path, &block ) -- string = "" -- case path[0] -+ def predicate_to_path(parsed, &block) -+ path = "" -+ case parsed[0] - when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union -- op = path.shift -+ op = parsed.shift - case op - when :eq - op = "=" -@@ -156,36 +192,50 @@ module REXML - when :union - op = "|" - end -- left = predicate_to_string( path.shift, &block ) -- right = predicate_to_string( path.shift, &block ) -- string << " " -- string << left -- string << " " -- string << op.to_s -- string << " " -- string << right -- string << " " -+ left = predicate_to_path( parsed.shift, &block ) -+ right = predicate_to_path( parsed.shift, &block ) -+ path << left -+ path << " " -+ path << op.to_s -+ path << " " -+ path << right - when :function -- path.shift -- name = path.shift -- string << name -- string << "( " -- string << predicate_to_string( path.shift, &block ) -- string << " )" -+ parsed.shift -+ name = parsed.shift -+ path << name -+ path << "(" -+ parsed.shift.each_with_index do |argument, i| -+ path << ", " if i > 0 -+ path << predicate_to_path(argument, &block) -+ end -+ path << ")" - when :literal -- path.shift -- string << " " -- string << path.shift.inspect -- string << " " -+ parsed.shift -+ path << quote_literal(parsed.shift) - else -- string << " " -- string << yield( path ) -- string << " " -+ path << yield( parsed ) - end -- return string.squeeze(" ") -+ return path.squeeze(" ") - end -+ # For backward compatibility -+ alias_method :preciate_to_string, :predicate_to_path - - private -+ def quote_literal( literal ) -+ case literal -+ when String -+ # XPath 1.0 does not support escape characters. -+ # Assumes literal does not contain both single and double quotes. -+ if literal.include?("'") -+ "\"#{literal}\"" -+ else -+ "'#{literal}'" -+ end -+ else -+ literal.inspect -+ end -+ end -+ - #LocationPath - # | RelativeLocationPath - # | '/' RelativeLocationPath? -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -index 8a01f0e..573d0a1 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb -@@ -26,10 +26,12 @@ - # - REXML::Document. - # - REXML::Element. - # -+# There's also an {REXML tutorial}[doc/rexml/tutorial_rdoc.html]. -+# - module REXML - COPYRIGHT = "Copyright © 2001-2008 Sean Russell " - DATE = "2008/019" -- VERSION = "3.2.5" -+ VERSION = "3.3.1" - REVISION = "" - - Copyright = COPYRIGHT -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb -index 90b370b..5715c35 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb -@@ -1,8 +1,28 @@ - # coding: US-ASCII - # frozen_string_literal: false -+ -+require "strscan" -+ - require_relative 'encoding' - - module REXML -+ if StringScanner::Version < "1.0.0" -+ module StringScannerCheckScanString -+ refine StringScanner do -+ def check(pattern) -+ pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String) -+ super(pattern) -+ end -+ -+ def scan(pattern) -+ pattern = /#{Regexp.escape(pattern)}/ if pattern.is_a?(String) -+ super(pattern) -+ end -+ end -+ end -+ using StringScannerCheckScanString -+ end -+ - # Generates Source-s. USE THIS CLASS. - class SourceFactory - # Generates a Source object -@@ -30,18 +50,27 @@ module REXML - # objects and provides consumption of text - class Source - include Encoding -- # The current buffer (what we're going to read next) -- attr_reader :buffer - # The line number of the last consumed text - attr_reader :line - attr_reader :encoding - -+ module Private -+ SCANNER_RESET_SIZE = 100000 -+ PRE_DEFINED_TERM_PATTERNS = {} -+ pre_defined_terms = ["'", '"', "<"] -+ pre_defined_terms.each do |term| -+ PRE_DEFINED_TERM_PATTERNS[term] = /#{Regexp.escape(term)}/ -+ end -+ end -+ private_constant :Private -+ - # Constructor - # @param arg must be a String, and should be a valid XML document - # @param encoding if non-null, sets the encoding of the source to this - # value, overriding all encoding detection - def initialize(arg, encoding=nil) -- @orig = @buffer = arg -+ @orig = arg -+ @scanner = StringScanner.new(@orig) - if encoding - self.encoding = encoding - else -@@ -50,6 +79,20 @@ module REXML - @line = 0 - end - -+ # The current buffer (what we're going to read next) -+ def buffer -+ @scanner.rest -+ end -+ -+ def drop_parsed_content -+ if @scanner.pos > Private::SCANNER_RESET_SIZE -+ @scanner.string = @scanner.rest -+ end -+ end -+ -+ def buffer_encoding=(encoding) -+ @scanner.string.force_encoding(encoding) -+ end - - # Inherited from Encoding - # Overridden to support optimized en/decoding -@@ -58,98 +101,78 @@ module REXML - encoding_updated - end - -- # Scans the source for a given pattern. Note, that this is not your -- # usual scan() method. For one thing, the pattern argument has some -- # requirements; for another, the source can be consumed. You can easily -- # confuse this method. Originally, the patterns were easier -- # to construct and this method more robust, because this method -- # generated search regexps on the fly; however, this was -- # computationally expensive and slowed down the entire REXML package -- # considerably, since this is by far the most commonly called method. -- # @param pattern must be a Regexp, and must be in the form of -- # /^\s*(#{your pattern, with no groups})(.*)/. The first group -- # will be returned; the second group is used if the consume flag is -- # set. -- # @param consume if true, the pattern returned will be consumed, leaving -- # everything after it in the Source. -- # @return the pattern, if found, or nil if the Source is empty or the -- # pattern is not found. -- def scan(pattern, cons=false) -- return nil if @buffer.nil? -- rv = @buffer.scan(pattern) -- @buffer = $' if cons and rv.size>0 -- rv -+ def read(term = nil) - end - -- def read -+ def read_until(term) -+ pattern = Private::PRE_DEFINED_TERM_PATTERNS[term] || /#{Regexp.escape(term)}/ -+ data = @scanner.scan_until(pattern) -+ unless data -+ data = @scanner.rest -+ @scanner.pos = @scanner.string.bytesize -+ end -+ data - end - -- def consume( pattern ) -- @buffer = $' if pattern.match( @buffer ) -+ def ensure_buffer - end - -- def match_to( char, pattern ) -- return pattern.match(@buffer) -+ def match(pattern, cons=false) -+ if cons -+ @scanner.scan(pattern).nil? ? nil : @scanner -+ else -+ @scanner.check(pattern).nil? ? nil : @scanner -+ end - end - -- def match_to_consume( char, pattern ) -- md = pattern.match(@buffer) -- @buffer = $' -- return md -+ def position -+ @scanner.pos - end - -- def match(pattern, cons=false) -- md = pattern.match(@buffer) -- @buffer = $' if cons and md -- return md -+ def position=(pos) -+ @scanner.pos = pos - end - - # @return true if the Source is exhausted - def empty? -- @buffer == "" -- end -- -- def position -- @orig.index( @buffer ) -+ @scanner.eos? - end - - # @return the current line in the source - def current_line - lines = @orig.split -- res = lines.grep @buffer[0..30] -+ res = lines.grep @scanner.rest[0..30] - res = res[-1] if res.kind_of? Array - lines.index( res ) if res - end - - private -+ - def detect_encoding -- buffer_encoding = @buffer.encoding -+ scanner_encoding = @scanner.rest.encoding - detected_encoding = "UTF-8" - begin -- @buffer.force_encoding("ASCII-8BIT") -- if @buffer[0, 2] == "\xfe\xff" -- @buffer[0, 2] = "" -+ @scanner.string.force_encoding("ASCII-8BIT") -+ if @scanner.scan(/\xfe\xff/n) - detected_encoding = "UTF-16BE" -- elsif @buffer[0, 2] == "\xff\xfe" -- @buffer[0, 2] = "" -+ elsif @scanner.scan(/\xff\xfe/n) - detected_encoding = "UTF-16LE" -- elsif @buffer[0, 3] == "\xef\xbb\xbf" -- @buffer[0, 3] = "" -+ elsif @scanner.scan(/\xef\xbb\xbf/n) - detected_encoding = "UTF-8" - end - ensure -- @buffer.force_encoding(buffer_encoding) -+ @scanner.string.force_encoding(scanner_encoding) - end - self.encoding = detected_encoding - end - - def encoding_updated - if @encoding != 'UTF-8' -- @buffer = decode(@buffer) -+ @scanner.string = decode(@scanner.rest) - @to_utf = true - else - @to_utf = false -- @buffer.force_encoding ::Encoding::UTF_8 -+ @scanner.string.force_encoding(::Encoding::UTF_8) - end - end - end -@@ -172,7 +195,7 @@ module REXML - end - - if !@to_utf and -- @buffer.respond_to?(:force_encoding) and -+ @orig.respond_to?(:force_encoding) and - @source.respond_to?(:external_encoding) and - @source.external_encoding != ::Encoding::UTF_8 - @force_utf8 = true -@@ -181,65 +204,62 @@ module REXML - end - end - -- def scan(pattern, cons=false) -- rv = super -- # You'll notice that this next section is very similar to the same -- # section in match(), but just a liiittle different. This is -- # because it is a touch faster to do it this way with scan() -- # than the way match() does it; enough faster to warrant duplicating -- # some code -- if rv.size == 0 -- until @buffer =~ pattern or @source.nil? -- begin -- @buffer << readline -- rescue Iconv::IllegalSequence -- raise -- rescue -- @source = nil -- end -- end -- rv = super -- end -- rv.taint if RUBY_VERSION < '2.7' -- rv -- end -- -- def read -+ def read(term = nil) -+ term = encode(term) if term - begin -- @buffer << readline -+ @scanner << readline(term) -+ true - rescue Exception, NameError - @source = nil -+ false -+ end -+ end -+ -+ def read_until(term) -+ pattern = Private::PRE_DEFINED_TERM_PATTERNS[term] || /#{Regexp.escape(term)}/ -+ term = encode(term) -+ until str = @scanner.scan_until(pattern) -+ break if @source.nil? -+ break if @source.eof? -+ @scanner << readline(term) -+ end -+ if str -+ read if @scanner.eos? and !@source.eof? -+ str -+ else -+ rest = @scanner.rest -+ @scanner.pos = @scanner.string.bytesize -+ rest - end - end - -- def consume( pattern ) -- match( pattern, true ) -+ def ensure_buffer -+ read if @scanner.eos? && @source - end - -+ # Note: When specifying a string for 'pattern', it must not include '>' except in the following formats: -+ # - ">" -+ # - "XXX>" (X is any string excluding '>') - def match( pattern, cons=false ) -- rv = pattern.match(@buffer) -- @buffer = $' if cons and rv -- while !rv and @source -- begin -- @buffer << readline -- rv = pattern.match(@buffer) -- @buffer = $' if cons and rv -- rescue -- @source = nil -+ while true -+ if cons -+ md = @scanner.scan(pattern) -+ else -+ md = @scanner.check(pattern) - end -+ break if md -+ return nil if pattern.is_a?(String) -+ return nil if @source.nil? -+ return nil unless read - end -- rv.taint if RUBY_VERSION < '2.7' -- rv -+ -+ md.nil? ? nil : @scanner - end - - def empty? - super and ( @source.nil? || @source.eof? ) - end - -- def position -- @er_source.pos rescue 0 -- end -- - # @return the current line in the source - def current_line - begin -@@ -263,8 +283,8 @@ module REXML - end - - private -- def readline -- str = @source.readline(@line_break) -+ def readline(term = nil) -+ str = @source.readline(term || @line_break) - if @pending_buffer - if str.nil? - str = @pending_buffer -@@ -290,7 +310,7 @@ module REXML - @source.set_encoding(@encoding, @encoding) - end - @line_break = encode(">") -- @pending_buffer, @buffer = @buffer, "" -+ @pending_buffer, @scanner.string = @scanner.rest, "" - @pending_buffer.force_encoding(@encoding) - super - end -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb -index 050b09c..b47bad3 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/text.rb -@@ -1,4 +1,4 @@ --# frozen_string_literal: false -+# frozen_string_literal: true - require_relative 'security' - require_relative 'entity' - require_relative 'doctype' -@@ -131,7 +131,7 @@ module REXML - def Text.check string, pattern, doctype - - # illegal anywhere -- if string !~ VALID_XML_CHARS -+ if !string.match?(VALID_XML_CHARS) - if String.method_defined? :encode - string.chars.each do |c| - case c.ord -@@ -371,7 +371,7 @@ module REXML - copy = input.to_s - # Doing it like this rather than in a loop improves the speed - #copy = copy.gsub( EREFERENCE, '&' ) -- copy = copy.gsub( "&", "&" ) -+ copy = copy.gsub( "&", "&" ) if copy.include?("&") - if doctype - # Replace all ampersands that aren't part of an entity - doctype.entities.each_value do |entity| -@@ -382,7 +382,9 @@ module REXML - else - # Replace all ampersands that aren't part of an entity - DocType::DEFAULT_ENTITIES.each_value do |entity| -- copy = copy.gsub(entity.value, "&#{entity.name};" ) -+ if copy.include?(entity.value) -+ copy = copy.gsub(entity.value, "&#{entity.name};" ) -+ end - end - end - copy -diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb -index d8b88e7..5eb1e5a 100644 ---- a/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb -+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/xpath_parser.rb -@@ -590,6 +590,7 @@ module REXML - - def evaluate_predicate(expression, nodesets) - enter(:predicate, expression, nodesets) if @debug -+ new_nodeset_count = 0 - new_nodesets = nodesets.collect do |nodeset| - new_nodeset = [] - subcontext = { :size => nodeset.size } -@@ -606,17 +607,20 @@ module REXML - result = result[0] if result.kind_of? Array and result.length == 1 - if result.kind_of? Numeric - if result == node.position -- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) -+ new_nodeset_count += 1 -+ new_nodeset << XPathNode.new(node, position: new_nodeset_count) - end - elsif result.instance_of? Array - if result.size > 0 and result.inject(false) {|k,s| s or k} - if result.size > 0 -- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) -+ new_nodeset_count += 1 -+ new_nodeset << XPathNode.new(node, position: new_nodeset_count) - end - end - else - if result -- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1) -+ new_nodeset_count += 1 -+ new_nodeset << XPathNode.new(node, position: new_nodeset_count) - end - end - end --- -2.27.0 -