-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(PA-6507) Patch REXML for CVE-2024-35176 in ruby 2.7 and 3.2
- Loading branch information
1 parent
a39b23b
commit 022e103
Showing
4 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
resources/patches/ruby_27/rexml_for_CVE-2024-35176.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
diff --git a/Gemfile b/Gemfile | ||
index 042ef8ac..f78cc861 100644 | ||
--- a/Gemfile | ||
+++ b/Gemfile | ||
@@ -10,4 +10,5 @@ group :development do | ||
gem "bundler" | ||
gem "rake" | ||
gem "test-unit" | ||
+ gem "test-unit-ruby-core" | ||
end | ||
diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb | ||
index 8d62391c..d09237c5 100644 | ||
--- a/lib/rexml/parsers/baseparser.rb | ||
+++ b/lib/rexml/parsers/baseparser.rb | ||
@@ -628,17 +628,17 @@ def parse_attributes(prefixes, curr_ns) | ||
message = "Missing attribute equal: <#{name}>" | ||
raise REXML::ParseException.new(message, @source) | ||
end | ||
- unless match = @source.match(/(['"])(.*?)\1\s*/um, true) | ||
- if match = @source.match(/(['"])/, true) | ||
- message = | ||
- "Missing attribute value end quote: <#{name}>: <#{match[1]}>" | ||
- raise REXML::ParseException.new(message, @source) | ||
- else | ||
- message = "Missing attribute value start quote: <#{name}>" | ||
- raise REXML::ParseException.new(message, @source) | ||
- end | ||
+ unless match = @source.match(/(['"])/, true) | ||
+ message = "Missing attribute value start quote: <#{name}>" | ||
+ raise REXML::ParseException.new(message, @source) | ||
+ end | ||
+ quote = match[1] | ||
+ value = @source.read_until(quote) | ||
+ unless value.chomp!(quote) | ||
+ message = "Missing attribute value end quote: <#{name}>: <#{quote}>" | ||
+ raise REXML::ParseException.new(message, @source) | ||
end | ||
- value = match[2] | ||
+ @source.match(/\s*/um, true) | ||
if prefix == "xmlns" | ||
if local_part == "xml" | ||
if value != "http://www.w3.org/XML/1998/namespace" | ||
diff --git a/lib/rexml/source.rb b/lib/rexml/source.rb | ||
index 7f47c2be..999751b4 100644 | ||
--- a/lib/rexml/source.rb | ||
+++ b/lib/rexml/source.rb | ||
@@ -65,7 +65,11 @@ def encoding=(enc) | ||
encoding_updated | ||
end | ||
|
||
- def read | ||
+ def read(term = nil) | ||
+ end | ||
+ | ||
+ def read_until(term) | ||
+ @scanner.scan_until(Regexp.union(term)) or @scanner.rest | ||
end | ||
|
||
def ensure_buffer | ||
@@ -158,9 +162,9 @@ def initialize(arg, block_size=500, encoding=nil) | ||
end | ||
end | ||
|
||
- def read | ||
+ def read(term = nil) | ||
begin | ||
- @scanner << readline | ||
+ @scanner << readline(term) | ||
true | ||
rescue Exception, NameError | ||
@source = nil | ||
@@ -168,6 +172,21 @@ def read | ||
end | ||
end | ||
|
||
+ def read_until(term) | ||
+ pattern = Regexp.union(term) | ||
+ data = [] | ||
+ begin | ||
+ until str = @scanner.scan_until(pattern) | ||
+ @scanner << readline(term) | ||
+ end | ||
+ rescue EOFError | ||
+ @scanner.rest | ||
+ else | ||
+ read if @scanner.eos? and [email protected]? | ||
+ str | ||
+ end | ||
+ end | ||
+ | ||
def ensure_buffer | ||
read if @scanner.eos? && @source | ||
end | ||
@@ -218,8 +237,8 @@ def current_line | ||
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 | ||
diff --git a/test/test_document.rb b/test/test_document.rb | ||
index 953656f8..f96bfd5d 100644 | ||
--- a/test/test_document.rb | ||
+++ b/test/test_document.rb | ||
@@ -1,8 +1,12 @@ | ||
# -*- coding: utf-8 -*- | ||
# frozen_string_literal: false | ||
|
||
+require 'core_assertions' | ||
+ | ||
module REXMLTests | ||
class TestDocument < Test::Unit::TestCase | ||
+ include Test::Unit::CoreAssertions | ||
+ | ||
def test_version_attributes_to_s | ||
doc = REXML::Document.new(<<~eoxml) | ||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
@@ -198,6 +202,13 @@ def test_xml_declaration_standalone | ||
assert_equal('no', doc.stand_alone?, bug2539) | ||
end | ||
|
||
+ def test_gt_linear_performance | ||
+ seq = [10000, 50000, 100000, 150000, 200000] | ||
+ assert_linear_performance(seq) do |n| | ||
+ REXML::Document.new('<test testing="' + ">" * n + '"></test>') | ||
+ end | ||
+ end | ||
+ | ||
class WriteTest < Test::Unit::TestCase | ||
def setup | ||
@document = REXML::Document.new(<<-EOX) |
135 changes: 135 additions & 0 deletions
135
resources/patches/ruby_32/rexml_for_CVE-2024-35176.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
diff --git a/Gemfile b/Gemfile | ||
index 042ef8ac..f78cc861 100644 | ||
--- a/Gemfile | ||
+++ b/Gemfile | ||
@@ -10,4 +10,5 @@ group :development do | ||
gem "bundler" | ||
gem "rake" | ||
gem "test-unit" | ||
+ gem "test-unit-ruby-core" | ||
end | ||
diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb | ||
index 8d62391c..d09237c5 100644 | ||
--- a/lib/rexml/parsers/baseparser.rb | ||
+++ b/lib/rexml/parsers/baseparser.rb | ||
@@ -628,17 +628,17 @@ def parse_attributes(prefixes, curr_ns) | ||
message = "Missing attribute equal: <#{name}>" | ||
raise REXML::ParseException.new(message, @source) | ||
end | ||
- unless match = @source.match(/(['"])(.*?)\1\s*/um, true) | ||
- if match = @source.match(/(['"])/, true) | ||
- message = | ||
- "Missing attribute value end quote: <#{name}>: <#{match[1]}>" | ||
- raise REXML::ParseException.new(message, @source) | ||
- else | ||
- message = "Missing attribute value start quote: <#{name}>" | ||
- raise REXML::ParseException.new(message, @source) | ||
- end | ||
+ unless match = @source.match(/(['"])/, true) | ||
+ message = "Missing attribute value start quote: <#{name}>" | ||
+ raise REXML::ParseException.new(message, @source) | ||
+ end | ||
+ quote = match[1] | ||
+ value = @source.read_until(quote) | ||
+ unless value.chomp!(quote) | ||
+ message = "Missing attribute value end quote: <#{name}>: <#{quote}>" | ||
+ raise REXML::ParseException.new(message, @source) | ||
end | ||
- value = match[2] | ||
+ @source.match(/\s*/um, true) | ||
if prefix == "xmlns" | ||
if local_part == "xml" | ||
if value != "http://www.w3.org/XML/1998/namespace" | ||
diff --git a/lib/rexml/source.rb b/lib/rexml/source.rb | ||
index 7f47c2be..999751b4 100644 | ||
--- a/lib/rexml/source.rb | ||
+++ b/lib/rexml/source.rb | ||
@@ -65,7 +65,11 @@ def encoding=(enc) | ||
encoding_updated | ||
end | ||
|
||
- def read | ||
+ def read(term = nil) | ||
+ end | ||
+ | ||
+ def read_until(term) | ||
+ @scanner.scan_until(Regexp.union(term)) or @scanner.rest | ||
end | ||
|
||
def ensure_buffer | ||
@@ -158,9 +162,9 @@ def initialize(arg, block_size=500, encoding=nil) | ||
end | ||
end | ||
|
||
- def read | ||
+ def read(term = nil) | ||
begin | ||
- @scanner << readline | ||
+ @scanner << readline(term) | ||
true | ||
rescue Exception, NameError | ||
@source = nil | ||
@@ -168,6 +172,21 @@ def read | ||
end | ||
end | ||
|
||
+ def read_until(term) | ||
+ pattern = Regexp.union(term) | ||
+ data = [] | ||
+ begin | ||
+ until str = @scanner.scan_until(pattern) | ||
+ @scanner << readline(term) | ||
+ end | ||
+ rescue EOFError | ||
+ @scanner.rest | ||
+ else | ||
+ read if @scanner.eos? and [email protected]? | ||
+ str | ||
+ end | ||
+ end | ||
+ | ||
def ensure_buffer | ||
read if @scanner.eos? && @source | ||
end | ||
@@ -218,8 +237,8 @@ def current_line | ||
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 | ||
diff --git a/test/test_document.rb b/test/test_document.rb | ||
index 953656f8..f96bfd5d 100644 | ||
--- a/test/test_document.rb | ||
+++ b/test/test_document.rb | ||
@@ -1,8 +1,12 @@ | ||
# -*- coding: utf-8 -*- | ||
# frozen_string_literal: false | ||
|
||
+require 'core_assertions' | ||
+ | ||
module REXMLTests | ||
class TestDocument < Test::Unit::TestCase | ||
+ include Test::Unit::CoreAssertions | ||
+ | ||
def test_version_attributes_to_s | ||
doc = REXML::Document.new(<<~eoxml) | ||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
@@ -198,6 +202,13 @@ def test_xml_declaration_standalone | ||
assert_equal('no', doc.stand_alone?, bug2539) | ||
end | ||
|
||
+ def test_gt_linear_performance | ||
+ seq = [10000, 50000, 100000, 150000, 200000] | ||
+ assert_linear_performance(seq) do |n| | ||
+ REXML::Document.new('<test testing="' + ">" * n + '"></test>') | ||
+ end | ||
+ end | ||
+ | ||
class WriteTest < Test::Unit::TestCase | ||
def setup | ||
@document = REXML::Document.new(<<-EOX) |