Skip to content

Commit 16d488b

Browse files
(PA-6507) Patch rexml for CVE-2024-35176
- Ruby 3.2.4 has rexml as its bundled gem, so the oatch was applied after the install step since bundled gems are available in the build after the install step in the .bundle folder. - Ruby 2.7.8 has rexml as its default gem, so we can go with the usual way to patch it. - Note that in the patch files for ruby_32, the file paths are prefixed with .bundle/gems/rexml-3.2.5 because that is where the bundled gem rexml is located with respect to the working directory of patching. - The upstream fix commit: ruby/rexml@4325835
1 parent 08c0261 commit 16d488b

File tree

4 files changed

+275
-0
lines changed

4 files changed

+275
-0
lines changed

configs/components/ruby-2.7.8.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242

4343
pkg.apply_patch "#{base}/uri-redos-cve-2023-36617.patch"
4444

45+
# This patch is not required for ruby >= 3.3.3
46+
pkg.apply_patch "#{base}/rexml_for_CVE-2024-35176.patch"
47+
4548
if platform.is_cross_compiled?
4649
unless platform.is_macos?
4750
pkg.apply_patch "#{base}/uri_generic_remove_safe_nav_operator_r2.5.patch"

configs/components/ruby-3.2.4.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,18 @@
300300
]
301301
end
302302
end
303+
304+
#########
305+
# BUILD
306+
#########
307+
308+
pkg.add_source("file://resources/patches/ruby_32/rexml_for_CVE-2024-35176.patch")
309+
310+
pkg.build do
311+
# This patch is applied after the install step because rexml gem is the bundled gem hence build
312+
# cannot find the path of the files to be patched prior to configuring and installing.
313+
# This patch is not required for ruby >= 3.3.3
314+
steps = ["#{platform.patch} --strip=1 --fuzz=0 --ignore-whitespace --no-backup-if-mismatch < ../rexml_for_CVE-2024-35176.patch"]
315+
end
316+
303317
end
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
commit e597f07718c27dc4414ad39f121376e53056475a
2+
Author: Shubham Shinde <[email protected]>
3+
Date: Tue Jul 9 19:40:43 2024 +0530
4+
5+
Read quoted attributes in chunks (#126)
6+
7+
8+
# Conflicts:
9+
# lib/rexml/parsers/baseparser.rb
10+
# lib/rexml/source.rb
11+
12+
diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb
13+
index f76aed0..f0b365d 100644
14+
--- a/lib/rexml/parsers/baseparser.rb
15+
+++ b/lib/rexml/parsers/baseparser.rb
16+
@@ -518,25 +518,43 @@ module REXML
17+
message = "Missing attribute equal: <#{name}>"
18+
raise REXML::ParseException.new(message, @source)
19+
end
20+
- quote = scanner.scan(/['"]/)
21+
- unless quote
22+
+ unless match = @source.match(/(['"])/, true)
23+
message = "Missing attribute value start quote: <#{name}>"
24+
raise REXML::ParseException.new(message, @source)
25+
end
26+
- unless scanner.scan(/.*#{Regexp.escape(quote)}/um)
27+
- match_data = @source.match(/^(.*?)(\/)?>/um, true)
28+
- if match_data
29+
- scanner << "/" if closed
30+
- scanner << ">"
31+
- scanner << match_data[1]
32+
- scanner.pos = pos
33+
- closed = !match_data[2].nil?
34+
- next
35+
- end
36+
- message =
37+
- "Missing attribute value end quote: <#{name}>: <#{quote}>"
38+
+ quote = match[1]
39+
+ value = @source.read_until(quote)
40+
+ unless value.chomp!(quote)
41+
+ message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
42+
raise REXML::ParseException.new(message, @source)
43+
end
44+
+ @source.match(/\s*/um, true)
45+
+ if prefix == "xmlns"
46+
+ if local_part == "xml"
47+
+ if value != "http://www.w3.org/XML/1998/namespace"
48+
+ msg = "The 'xml' prefix must not be bound to any other namespace "+
49+
+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
50+
+ raise REXML::ParseException.new( msg, @source, self )
51+
+ end
52+
+ elsif local_part == "xmlns"
53+
+ msg = "The 'xmlns' prefix must not be declared "+
54+
+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
55+
+ raise REXML::ParseException.new( msg, @source, self)
56+
+ end
57+
+ curr_ns << local_part
58+
+ elsif prefix
59+
+ prefixes << prefix unless prefix == "xml"
60+
+ end
61+
+
62+
+ if attributes[name]
63+
+ msg = "Duplicate attribute #{name.inspect}"
64+
+ raise REXML::ParseException.new(msg, @source, self)
65+
+ end
66+
+
67+
+ attributes[name] = value
68+
+ else
69+
+ message = "Invalid attribute name: <#{@source.buffer.split(%r{[/>\s]}).first}>"
70+
+ raise REXML::ParseException.new(message, @source)
71+
end
72+
name = scanner[1]
73+
prefix = scanner[2]
74+
diff --git a/lib/rexml/source.rb b/lib/rexml/source.rb
75+
index 770aefc..86bf6cf 100644
76+
--- a/lib/rexml/source.rb
77+
+++ b/lib/rexml/source.rb
78+
@@ -81,7 +81,11 @@ module REXML
79+
rv
80+
end
81+
82+
- def read
83+
+ def read(term = nil)
84+
+ end
85+
+
86+
+ def read_until(term)
87+
+ @scanner.scan_until(Regexp.union(term)) or @scanner.rest
88+
end
89+
90+
def consume( pattern )
91+
@@ -204,9 +208,9 @@ module REXML
92+
rv
93+
end
94+
95+
- def read
96+
+ def read(term = nil)
97+
begin
98+
- @buffer << readline
99+
+ @buffer << readline(term)
100+
rescue Exception, NameError
101+
@source = nil
102+
end
103+
@@ -216,6 +220,21 @@ module REXML
104+
match( pattern, true )
105+
end
106+
107+
+ def read_until(term)
108+
+ pattern = Regexp.union(term)
109+
+ data = []
110+
+ begin
111+
+ until str = @scanner.scan_until(pattern)
112+
+ @scanner << readline(term)
113+
+ end
114+
+ rescue EOFError
115+
+ @scanner.rest
116+
+ else
117+
+ read if @scanner.eos? and [email protected]?
118+
+ str
119+
+ end
120+
+ end
121+
+
122+
def match( pattern, cons=false )
123+
rv = pattern.match(@buffer)
124+
@buffer = $' if cons and rv
125+
@@ -263,8 +282,8 @@ module REXML
126+
end
127+
128+
private
129+
- def readline
130+
- str = @source.readline(@line_break)
131+
+ def readline(term = nil)
132+
+ str = @source.readline(term || @line_break)
133+
if @pending_buffer
134+
if str.nil?
135+
str = @pending_buffer
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
2+
diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb
3+
index 90b370b..373abcf 100644
4+
--- a/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb
5+
+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/source.rb
6+
@@ -81,7 +81,11 @@ module REXML
7+
rv
8+
end
9+
10+
- def read
11+
+ def read(term = nil)
12+
+ end
13+
+
14+
+ def read_until(term)
15+
+ @scanner.scan_until(Regexp.union(term)) or @scanner.rest
16+
end
17+
18+
def consume( pattern )
19+
@@ -204,14 +208,29 @@ module REXML
20+
rv
21+
end
22+
23+
- def read
24+
+ def read(term = nil)
25+
begin
26+
- @buffer << readline
27+
+ @buffer << readline(term)
28+
rescue Exception, NameError
29+
@source = nil
30+
end
31+
end
32+
33+
+ def read_until(term)
34+
+ pattern = Regexp.union(term)
35+
+ data = []
36+
+ begin
37+
+ until str = @scanner.scan_until(pattern)
38+
+ @scanner << readline(term)
39+
+ end
40+
+ rescue EOFError
41+
+ @scanner.rest
42+
+ else
43+
+ read if @scanner.eos? and [email protected]?
44+
+ str
45+
+ end
46+
+ end
47+
+
48+
def consume( pattern )
49+
match( pattern, true )
50+
end
51+
@@ -263,8 +282,8 @@ module REXML
52+
end
53+
54+
private
55+
- def readline
56+
- str = @source.readline(@line_break)
57+
+ def readline(term = nil)
58+
+ str = @source.readline(term || @line_break)
59+
if @pending_buffer
60+
if str.nil?
61+
str = @pending_buffer
62+
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
63+
index 305b120..7001bb2 100644
64+
--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb
65+
+++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb
66+
@@ -618,25 +618,43 @@ module REXML
67+
message = "Missing attribute equal: <#{name}>"
68+
raise REXML::ParseException.new(message, @source)
69+
end
70+
- quote = scanner.scan(/['"]/)
71+
- unless quote
72+
+ unless match = @source.match(/(['"])/, true)
73+
message = "Missing attribute value start quote: <#{name}>"
74+
raise REXML::ParseException.new(message, @source)
75+
end
76+
- unless scanner.scan(/.*#{Regexp.escape(quote)}/um)
77+
- match_data = @source.match(/^(.*?)(\/)?>/um, true)
78+
- if match_data
79+
- scanner << "/" if closed
80+
- scanner << ">"
81+
- scanner << match_data[1]
82+
- scanner.pos = pos
83+
- closed = !match_data[2].nil?
84+
- next
85+
- end
86+
- message =
87+
- "Missing attribute value end quote: <#{name}>: <#{quote}>"
88+
+ quote = match[1]
89+
+ value = @source.read_until(quote)
90+
+ unless value.chomp!(quote)
91+
+ message = "Missing attribute value end quote: <#{name}>: <#{quote}>"
92+
raise REXML::ParseException.new(message, @source)
93+
end
94+
+ @source.match(/\s*/um, true)
95+
+ if prefix == "xmlns"
96+
+ if local_part == "xml"
97+
+ if value != "http://www.w3.org/XML/1998/namespace"
98+
+ msg = "The 'xml' prefix must not be bound to any other namespace "+
99+
+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
100+
+ raise REXML::ParseException.new( msg, @source, self )
101+
+ end
102+
+ elsif local_part == "xmlns"
103+
+ msg = "The 'xmlns' prefix must not be declared "+
104+
+ "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
105+
+ raise REXML::ParseException.new( msg, @source, self)
106+
+ end
107+
+ curr_ns << local_part
108+
+ elsif prefix
109+
+ prefixes << prefix unless prefix == "xml"
110+
+ end
111+
+
112+
+ if attributes[name]
113+
+ msg = "Duplicate attribute #{name.inspect}"
114+
+ raise REXML::ParseException.new(msg, @source, self)
115+
+ end
116+
+
117+
+ attributes[name] = value
118+
+ else
119+
+ message = "Invalid attribute name: <#{@source.buffer.split(%r{[/>\s]}).first}>"
120+
+ raise REXML::ParseException.new(message, @source)
121+
end
122+
name = scanner[1]
123+
prefix = scanner[2]

0 commit comments

Comments
 (0)