ruby/SOURCES/ruby-3.0.7-Fix-CVE-2024-27281-RCE-vulnerability-with-rdoc_options.patch

204 lines
6.6 KiB
Diff

From 7957a25edf844c966de45848fa7e9e2513955660 Mon Sep 17 00:00:00 2001
From: Hiroshi SHIBATA <hsbt@ruby-lang.org>
Date: Thu, 21 Mar 2024 15:47:40 +0900
Subject: [PATCH 1/2] Merge RDoc-6.3.4.1
---
lib/rdoc/rdoc.rb | 3 ++-
lib/rdoc/store.rb | 45 ++++++++++++++++++++--------------
test/rdoc/test_rdoc_options.rb | 6 ++---
3 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index a2711fbbd1..c5690fc3b4 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -162,8 +162,9 @@ def load_options
RDoc.load_yaml
begin
- options = YAML.load_file '.rdoc_options'
+ options = YAML.safe_load_file '.rdoc_options', permitted_classes: [RDoc::Options, Symbol]
rescue Psych::SyntaxError
+ raise RDoc::Error, "#{options_file} is not a valid rdoc options file"
end
raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
index 999aa76f92..07d03e90f7 100644
--- a/lib/rdoc/store.rb
+++ b/lib/rdoc/store.rb
@@ -539,9 +539,7 @@ def load_all
def load_cache
#orig_enc = @encoding
- open cache_path, 'rb' do |io|
- @cache = Marshal.load io.read
- end
+ @cache = marshal_load(cache_path)
load_enc = @cache[:encoding]
@@ -596,9 +594,7 @@ def load_class klass_name
def load_class_data klass_name
file = class_file klass_name
- open file, 'rb' do |io|
- Marshal.load io.read
- end
+ marshal_load(file)
rescue Errno::ENOENT => e
error = MissingFileError.new(self, file, klass_name)
error.set_backtrace e.backtrace
@@ -611,14 +607,10 @@ def load_class_data klass_name
def load_method klass_name, method_name
file = method_file klass_name, method_name
- open file, 'rb' do |io|
- obj = Marshal.load io.read
- 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
@@ -631,11 +623,9 @@ def load_method klass_name, method_name
def load_page page_name
file = page_file page_name
- open file, 'rb' do |io|
- obj = Marshal.load io.read
- 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
@@ -965,4 +955,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/test/rdoc/test_rdoc_options.rb b/test/rdoc/test_rdoc_options.rb
index 400ed9a549..247c7c87ce 100644
--- a/test/rdoc/test_rdoc_options.rb
+++ b/test/rdoc/test_rdoc_options.rb
@@ -145,7 +145,7 @@ def test_init_with_encoding
@options.encoding = Encoding::IBM437
- options = YAML.load YAML.dump @options
+ options = YAML.safe_load(YAML.dump(@options), permitted_classes: [RDoc::Options, Symbol])
assert_equal Encoding::IBM437, options.encoding
end
@@ -161,7 +161,7 @@ def test_init_with_trim_paths
- /etc
YAML
- options = YAML.load yaml
+ options = YAML.safe_load(yaml, permitted_classes: [RDoc::Options, Symbol])
assert_empty options.rdoc_include
assert_empty options.static_path
@@ -729,7 +729,7 @@ def test_write_options
assert File.exist? '.rdoc_options'
- assert_equal @options, YAML.load(File.read('.rdoc_options'))
+ assert_equal @options, YAML.safe_load(File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol])
end
end
From 153a4d16058783c923d0df5b1cbe2610ef96e3a8 Mon Sep 17 00:00:00 2001
From: Jarek Prokop <jprokop@redhat.com>
Date: Tue, 28 May 2024 16:56:26 +0200
Subject: [PATCH 2/2] Port the rebase to work with Ruby 2.5.9.
Ruby 2.5's Psych does not have safe_load_file method.
However, from Ruby 3.3's sources, the method is just File.read
simple wrapper with a safe_load call. Therefore it was copied over to
the lib/rdoc/rdoc.rb file.
---
lib/rdoc/rdoc.rb | 9 ++++++-
test/rdoc/test_rdoc_options.rb | 6 +++---
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index c5690fc3b4..435cd2eaf0 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -162,7 +162,12 @@ def load_options
RDoc.load_yaml
begin
- options = YAML.safe_load_file '.rdoc_options', permitted_classes: [RDoc::Options, Symbol]
+ # Opening file inspired from Ruby 3.3.0 sources,
+ # file 'ext/psych/lib/psych.rb', line 658.
+ # https://github.com/ruby/ruby/blob/v3_3_0/ext/psych/lib/psych.rb#L658
+ options = File.open('.rdoc_options', 'r:bom|utf-8') do |file|
+ YAML.safe_load file, [RDoc::Options, Symbol], [], false, '.rdoc_options'
+ end
rescue Psych::SyntaxError
raise RDoc::Error, "#{options_file} is not a valid rdoc options file"
end
diff --git a/test/rdoc/test_rdoc_options.rb b/test/rdoc/test_rdoc_options.rb
index 247c7c87ce..60fe035dce 100644
--- a/test/rdoc/test_rdoc_options.rb
+++ b/test/rdoc/test_rdoc_options.rb
@@ -145,7 +145,7 @@ def test_init_with_encoding
@options.encoding = Encoding::IBM437
- options = YAML.safe_load(YAML.dump(@options), permitted_classes: [RDoc::Options, Symbol])
+ options = YAML.safe_load(YAML.dump(@options), [RDoc::Options, Symbol])
assert_equal Encoding::IBM437, options.encoding
end
@@ -161,7 +161,7 @@ def test_init_with_trim_paths
- /etc
YAML
- options = YAML.safe_load(yaml, permitted_classes: [RDoc::Options, Symbol])
+ options = YAML.safe_load(yaml, [RDoc::Options, Symbol])
assert_empty options.rdoc_include
assert_empty options.static_path
@@ -729,7 +729,7 @@ def test_write_options
assert File.exist? '.rdoc_options'
- assert_equal @options, YAML.safe_load(File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol])
+ assert_equal @options, YAML.safe_load(File.read('.rdoc_options'), [RDoc::Options, Symbol])
end
end