mirror of
https://git.yoctoproject.org/poky
synced 2026-02-22 09:29:40 +01:00
REXML is an XML toolkit for Ruby. The REXML gem before 3.3.9 has a ReDoS vulnerability when it parses an XML that has many digits between &# and x...; in a hex numeric character reference (&#x.... This does not happen with Ruby 3.2 or later. Ruby 3.1 is the only affected maintained Ruby. The REXML gem 3.3.9 or later include the patch to fix the vulnerability. CVE-2024-49761-0009.patch is the CVE fix and rest are dependent commits. Reference: https://nvd.nist.gov/vuln/detail/CVE-2024-49761 Upstream-patch:810d22852383ca5c4b0f51217dbcc67e4049f6a6fc6cad570b7712855547370666e314a579730f25ce59f2eb1a(From OE-Core rev: 5b453400e9dd878b81b1447d14b3f518809de17e) Signed-off-by: Divya Chellam <divya.chellam@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
108 lines
4.5 KiB
Diff
108 lines
4.5 KiB
Diff
From a579730f25ec7443796495541ec57c071b91805d Mon Sep 17 00:00:00 2001
|
|
From: NAITOH Jun <naitoh@gmail.com>
|
|
Date: Tue, 25 Jun 2024 09:07:11 +0900
|
|
Subject: [PATCH] Optimize BaseParser#unnormalize method (#158)
|
|
|
|
## Benchmark
|
|
```
|
|
RUBYLIB= BUNDLER_ORIG_RUBYLIB= /Users/naitoh/.rbenv/versions/3.3.3/bin/ruby -v -S benchmark-driver /Users/naitoh/ghq/github.com/naitoh/rexml/benchmark/parse.yaml
|
|
ruby 3.3.3 (2024-06-12 revision f1c7b6f435) [arm64-darwin22]
|
|
Calculating -------------------------------------
|
|
before after before(YJIT) after(YJIT)
|
|
dom 17.704 18.106 34.215 33.806 i/s - 100.000 times in 5.648398s 5.523110s 2.922698s 2.958036s
|
|
sax 25.664 25.302 48.429 48.602 i/s - 100.000 times in 3.896488s 3.952289s 2.064859s 2.057537s
|
|
pull 28.966 29.215 61.710 62.068 i/s - 100.000 times in 3.452275s 3.422901s 1.620480s 1.611129s
|
|
stream 28.291 28.426 53.860 55.548 i/s - 100.000 times in 3.534716s 3.517884s 1.856667s 1.800247s
|
|
|
|
Comparison:
|
|
dom
|
|
before(YJIT): 34.2 i/s
|
|
after(YJIT): 33.8 i/s - 1.01x slower
|
|
after: 18.1 i/s - 1.89x slower
|
|
before: 17.7 i/s - 1.93x slower
|
|
|
|
sax
|
|
after(YJIT): 48.6 i/s
|
|
before(YJIT): 48.4 i/s - 1.00x slower
|
|
before: 25.7 i/s - 1.89x slower
|
|
after: 25.3 i/s - 1.92x slower
|
|
|
|
pull
|
|
after(YJIT): 62.1 i/s
|
|
before(YJIT): 61.7 i/s - 1.01x slower
|
|
after: 29.2 i/s - 2.12x slower
|
|
before: 29.0 i/s - 2.14x slower
|
|
|
|
stream
|
|
after(YJIT): 55.5 i/s
|
|
before(YJIT): 53.9 i/s - 1.03x slower
|
|
after: 28.4 i/s - 1.95x slower
|
|
before: 28.3 i/s - 1.96x slower
|
|
|
|
```
|
|
|
|
- YJIT=ON : 1.00x - 1.03x faster
|
|
- YJIT=OFF : 0.98x - 1.02x faster
|
|
|
|
CVE: CVE-2024-49761
|
|
|
|
Upstream-Status: Backport [https://github.com/ruby/rexml/commit/a579730f25ec7443796495541ec57c071b91805d]
|
|
|
|
Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
|
|
---
|
|
.../rexml-3.2.5/lib/rexml/parsers/baseparser.rb | 15 +++++++++++----
|
|
1 file changed, 11 insertions(+), 4 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 bc59bcd..9983d51 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
|
|
@@ -121,6 +121,13 @@ module REXML
|
|
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
|
|
include Private
|
|
@@ -465,10 +472,10 @@ module REXML
|
|
|
|
# Unescapes all possible entities
|
|
def unnormalize( string, entities=nil, filter=nil )
|
|
- rv = string.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*')
|
|
@@ -479,7 +486,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]
|
|
@@ -487,7 +494,7 @@ module REXML
|
|
end
|
|
end
|
|
end
|
|
- rv.gsub!( /&/, '&' )
|
|
+ rv.gsub!( Private::DEFAULT_ENTITIES_PATTERNS['amp'], '&' )
|
|
end
|
|
rv
|
|
end
|
|
--
|
|
2.40.0
|
|
|