Files
poky/meta/recipes-devtools/ruby/ruby/CVE-2024-41123-0004.patch
Divya Chellam 6639c7b295 ruby: fix CVE-2024-41123
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.2 has some DoS
vulnerabilities when it parses an XML that has many specific characters
such as whitespace character, `>]` and `]>`. The REXML gem 3.3.3 or later
include the patches to fix these vulnerabilities.

Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-41123

Upstream-patches:
2c39c91a65
4444a04ece
ebc3e85bfa
6cac15d458
e2546e6eca

(From OE-Core rev: 6b2a2e689a69deef6098f6c266542234e46fb24b)

Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
2025-12-01 06:50:49 -08:00

164 lines
6.4 KiB
Diff

From 6cac15d45864c8d70904baa5cbfcc97181000960 Mon Sep 17 00:00:00 2001
From: tomoya ishida <tomoyapenguin@gmail.com>
Date: Thu, 1 Aug 2024 09:21:19 +0900
Subject: [PATCH] Fix source.match performance without specifying term string
(#186)
Performance problem of `source.match(regexp)` was recently fixed by
specifying terminator string. However, I think maintaining appropriate
terminator string for a regexp is hard.
I propose solving this performance issue by increasing bytes to read in
each iteration.
CVE: CVE-2024-41123
Upstream-Status: Backport [https://github.com/ruby/rexml/commit/6cac15d45864c8d70904baa5cbfcc97181000960]
Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
---
.../lib/rexml/parsers/baseparser.rb | 22 ++++++------------
.bundle/gems/rexml-3.2.5/lib/rexml/source.rb | 23 +++++++++++++++----
2 files changed, 25 insertions(+), 20 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 71fce99..c1a22b8 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,14 +124,6 @@ module REXML
}
module Private
- # Terminal requires two or more letters.
- INSTRUCTION_TERM = "?>"
- COMMENT_TERM = "-->"
- CDATA_TERM = "]]>"
- DOCTYPE_TERM = "]>"
- # Read to the end of DOCTYPE because there is no proper ENTITY termination
- ENTITY_TERM = DOCTYPE_TERM
-
INSTRUCTION_END = /#{NAME}(\s+.*?)?\?>/um
TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um
CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um
@@ -244,7 +236,7 @@ module REXML
return process_instruction(start_position)
elsif @source.match("<!", true)
if @source.match("--", true)
- md = @source.match(/(.*?)-->/um, true, term: Private::COMMENT_TERM)
+ md = @source.match(/(.*?)-->/um, true)
if md.nil?
raise REXML::ParseException.new("Unclosed comment", @source)
end
@@ -308,7 +300,7 @@ module REXML
raise REXML::ParseException.new( "Bad ELEMENT declaration!", @source ) if md.nil?
return [ :elementdecl, "<!ELEMENT" + md[1] ]
elsif @source.match("ENTITY", true)
- match_data = @source.match(Private::ENTITYDECL_PATTERN, true, term: Private::ENTITY_TERM)
+ match_data = @source.match(Private::ENTITYDECL_PATTERN, true)
unless match_data
raise REXML::ParseException.new("Malformed entity declaration", @source)
end
@@ -377,14 +369,14 @@ module REXML
raise REXML::ParseException.new(message, @source)
end
return [:notationdecl, name, *id]
- elsif md = @source.match(/--(.*?)-->/um, true, term: Private::COMMENT_TERM)
+ 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
- elsif match = @source.match(/(%.*?;)\s*/um, true, term: Private::DOCTYPE_TERM)
+ elsif match = @source.match(/(%.*?;)\s*/um, true)
return [ :externalentity, match[1] ]
elsif @source.match(/\]\s*>/um, true)
@document_status = :after_doctype
@@ -417,7 +409,7 @@ module REXML
#STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
raise REXML::ParseException.new("Malformed node", @source) unless md
if md[0][0] == ?-
- md = @source.match(/--(.*?)-->/um, true, term: Private::COMMENT_TERM)
+ md = @source.match(/--(.*?)-->/um, true)
case md[1]
when /--/, /-\z/
@@ -426,7 +418,7 @@ module REXML
return [ :comment, md[1] ] if md
else
- md = @source.match(/\[CDATA\[(.*?)\]\]>/um, true, term: Private::CDATA_TERM)
+ md = @source.match(/\[CDATA\[(.*?)\]\]>/um, true)
return [ :cdata, md[1] ] if md
end
raise REXML::ParseException.new( "Declarations can only occur "+
@@ -664,7 +656,7 @@ module REXML
end
def process_instruction(start_position)
- match_data = @source.match(Private::INSTRUCTION_END, true, term: Private::INSTRUCTION_TERM)
+ match_data = @source.match(Private::INSTRUCTION_END, true)
unless match_data
message = "Invalid processing instruction node"
@source.position = start_position
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 7be430a..7c05cb5 100644
--- a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb
+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb
@@ -72,7 +72,7 @@ module REXML
@scanner.scan_until(Regexp.union(term)) or @scanner.rest
end
- def match(pattern, cons=false, term: nil)
+ def match(pattern, cons=false)
if cons
@scanner.scan(pattern).nil? ? nil : @scanner
else
@@ -159,10 +159,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
@@ -186,7 +196,9 @@ module REXML
end
end
- def match( pattern, cons=false, term: nil )
+ def match( pattern, cons=false )
+ # To avoid performance issue, we need to increase bytes to read per scan
+ min_bytes = 1
read if @scanner.eos? && @source
while true
if cons
@@ -197,7 +209,8 @@ module REXML
break if md
return nil if pattern.is_a?(String) && pattern.bytesize <= @scanner.rest_size
return nil if @source.nil?
- return nil unless read(term)
+ return nil unless read(nil, min_bytes)
+ min_bytes *= 2
end
md.nil? ? nil : @scanner
--
2.40.0