import UBI ruby-3.3.12-8.module+el8.10.0+24567+c4e5368e
This commit is contained in:
parent
c3477a424b
commit
2b83b0b5ee
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
SOURCES/ruby-3.3.10.tar.xz
|
||||
SOURCES/ruby-3.3.12.tar.xz
|
||||
|
||||
@ -1 +1 @@
|
||||
5db7cd707e7e79cd99f5d1009c754466c9d8d9e3 SOURCES/ruby-3.3.10.tar.xz
|
||||
7df70ae8a9feb880e2ad5054dfebd712ba03d0eb SOURCES/ruby-3.3.12.tar.xz
|
||||
|
||||
@ -11,7 +11,7 @@ diff --git a/configure.ac b/configure.ac
|
||||
index d261ea57b5..3c13076b82 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -3480,6 +3480,11 @@ AS_IF([test ${multiarch+set}], [
|
||||
@@ -3477,6 +3477,11 @@ AS_IF([test ${multiarch+set}], [
|
||||
])
|
||||
|
||||
archlibdir='${libdir}/${arch}'
|
||||
|
||||
@ -14,7 +14,7 @@ diff --git a/configure.ac b/configure.ac
|
||||
index c42436c23d..d261ea57b5 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -4319,7 +4319,8 @@ AS_CASE(["$ruby_version_dir_name"],
|
||||
@@ -4317,7 +4317,8 @@ AS_CASE(["$ruby_version_dir_name"],
|
||||
ruby_version_dir=/'${ruby_version_dir_name}'
|
||||
|
||||
if test -z "${ruby_version_dir_name}"; then
|
||||
|
||||
@ -11,7 +11,7 @@ diff --git a/configure.ac b/configure.ac
|
||||
index 3c13076b82..93af30321d 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -4383,6 +4383,8 @@ AC_SUBST(vendorarchdir)dnl
|
||||
@@ -4381,6 +4381,8 @@ AC_SUBST(vendorarchdir)dnl
|
||||
AC_SUBST(CONFIGURE, "`echo $0 | sed 's|.*/||'`")dnl
|
||||
AC_SUBST(configure_args, "`echo "${ac_configure_args}" | sed 's/\\$/$$/g'`")dnl
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ diff --git a/configure.ac b/configure.ac
|
||||
index 93af30321d..bc13397e0e 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -4355,6 +4355,10 @@ AC_ARG_WITH(vendorarchdir,
|
||||
@@ -4353,6 +4353,10 @@ AC_ARG_WITH(vendorarchdir,
|
||||
[vendorarchdir=$withval],
|
||||
[vendorarchdir=${multiarch+'${rubysitearchprefix}/vendor_ruby'${ruby_version_dir}}${multiarch-'${vendorlibdir}/${sitearch}'}])
|
||||
|
||||
@ -26,7 +26,7 @@ index 93af30321d..bc13397e0e 100644
|
||||
AS_IF([test "${LOAD_RELATIVE+set}"], [
|
||||
AC_DEFINE_UNQUOTED(LOAD_RELATIVE, $LOAD_RELATIVE)
|
||||
RUBY_EXEC_PREFIX=''
|
||||
@@ -4379,6 +4383,7 @@ AC_SUBST(sitearchdir)dnl
|
||||
@@ -4377,6 +4381,7 @@ AC_SUBST(sitearchdir)dnl
|
||||
AC_SUBST(vendordir)dnl
|
||||
AC_SUBST(vendorlibdir)dnl
|
||||
AC_SUBST(vendorarchdir)dnl
|
||||
|
||||
@ -20,7 +20,7 @@ diff --git a/configure.ac b/configure.ac
|
||||
index 80b137e380..63cd3b4f8b 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -4269,9 +4269,6 @@ AS_CASE(["$target_os"],
|
||||
@@ -4267,9 +4267,6 @@ AS_CASE(["$target_os"],
|
||||
rubyw_install_name='$(RUBYW_INSTALL_NAME)'
|
||||
])
|
||||
|
||||
@ -30,7 +30,7 @@ index 80b137e380..63cd3b4f8b 100644
|
||||
rubyarchprefix=${multiarch+'${archlibdir}/${RUBY_BASE_NAME}'}${multiarch-'${rubylibprefix}/${arch}'}
|
||||
AC_ARG_WITH(rubyarchprefix,
|
||||
AS_HELP_STRING([--with-rubyarchprefix=DIR],
|
||||
@@ -4294,57 +4291,63 @@ AC_ARG_WITH(ridir,
|
||||
@@ -4292,57 +4289,63 @@ AC_ARG_WITH(ridir,
|
||||
AC_SUBST(ridir)
|
||||
AC_SUBST(RI_BASE_NAME)
|
||||
|
||||
@ -122,7 +122,7 @@ index 80b137e380..63cd3b4f8b 100644
|
||||
|
||||
AS_IF([test "${LOAD_RELATIVE+set}"], [
|
||||
AC_DEFINE_UNQUOTED(LOAD_RELATIVE, $LOAD_RELATIVE)
|
||||
@@ -4361,6 +4364,7 @@ AC_SUBST(sitearchincludedir)dnl
|
||||
@@ -4359,6 +4362,7 @@ AC_SUBST(sitearchincludedir)dnl
|
||||
AC_SUBST(arch)dnl
|
||||
AC_SUBST(sitearch)dnl
|
||||
AC_SUBST(ruby_version)dnl
|
||||
|
||||
@ -12,9 +12,9 @@ diff --git a/common.mk b/common.mk
|
||||
index d55d1788aa..73755f6ccd 100644
|
||||
--- a/common.mk
|
||||
+++ b/common.mk
|
||||
@@ -1607,8 +1607,6 @@ yes-test-syntax-suggest: $(PREPARE_SYNTAX_SUGGEST)
|
||||
$(ACTIONS_ENDGROUP)
|
||||
no-test-syntax-suggest:
|
||||
@@ -1585,8 +1585,6 @@ test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS)
|
||||
|
||||
test-syntax-suggest:
|
||||
|
||||
-check: $(DOT_WAIT) $(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest
|
||||
-
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From feee246753aa097e836a79ea8437f4b8c73df7e8 Mon Sep 17 00:00:00 2001
|
||||
From: Jarek Prokop <jprokop@redhat.com>
|
||||
Date: Tue, 21 Jul 2026 10:32:29 +0200
|
||||
Subject: [PATCH] Allow up to 1 send from exits YJIT stat for proc test.
|
||||
|
||||
Add an allowed range of 0..1 for exits send stat.
|
||||
|
||||
In some case, the stats contain extra stat under 'exits' for 'send'.
|
||||
|
||||
In any other case, the stat is 0, and test passes.
|
||||
From RPM build of Ruby for Fedora distro family, the exits' stats emit 1 extra send.
|
||||
|
||||
The commit that introduced fix and the offending test
|
||||
0cba8cf414dfd8ab30edc3081645405c165a81d5 for [Bug #21266]
|
||||
prevents a crash, which seems prevented here as well.
|
||||
---
|
||||
test/ruby/test_yjit.rb | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
|
||||
index 0d40d38872..df1b41aa16 100644
|
||||
--- a/test/ruby/test_yjit.rb
|
||||
+++ b/test/ruby/test_yjit.rb
|
||||
@@ -1528,7 +1528,7 @@ def test_disable_stats
|
||||
|
||||
def test_proc_block_with_kwrest
|
||||
# When the bug was present this required --yjit-stats to trigger.
|
||||
- assert_compiles(<<~RUBY, result: {extra: 5})
|
||||
+ assert_compiles(<<~RUBY, result: {extra: 5}, exits: {send: 0..1})
|
||||
def foo = bar(w: 1, x: 2, y: 3, z: 4, extra: 5, &proc { _1 })
|
||||
def bar(w:, x:, y:, z:, **kwrest) = yield kwrest
|
||||
|
||||
@ -171,7 +171,7 @@ index f35fad6a362611..0da15772d36671 100644
|
||||
AC_CACHE_CHECK([whether compiler has statement and declarations in expressions],
|
||||
rb_cv_have_stmt_and_decl_in_expr,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[ __extension__ ({ int a = 0; a; }); ]])],
|
||||
@@ -4213,12 +4270,13 @@ AS_IF([test "${ARCH_FLAG}"], [
|
||||
@@ -4211,12 +4268,13 @@ AS_IF([test "${ARCH_FLAG}"], [
|
||||
rb_cv_warnflags=`echo "$rb_cv_warnflags" | sed 's/^ *//;s/ *$//'`
|
||||
warnflags="$rb_cv_warnflags"
|
||||
AC_SUBST(cppflags)dnl
|
||||
@ -186,7 +186,7 @@ index f35fad6a362611..0da15772d36671 100644
|
||||
AC_SUBST(XCFLAGS)dnl
|
||||
AC_SUBST(XLDFLAGS)dnl
|
||||
AC_SUBST(EXTLDFLAGS)dnl
|
||||
@@ -4686,6 +4744,7 @@ config_summary "DLDFLAGS" "$DLDFLAGS"
|
||||
@@ -4684,6 +4742,7 @@ config_summary "DLDFLAGS" "$DLDFLAGS"
|
||||
config_summary "optflags" "$optflags"
|
||||
config_summary "debugflags" "$debugflags"
|
||||
config_summary "warnflags" "$warnflags"
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
From a53f3d57d1c70f35534c457de2c471d84a55956a Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Kokubun <takashikkbn@gmail.com>
|
||||
Date: Tue, 21 Apr 2026 16:27:44 +0900
|
||||
Subject: [PATCH 1/2] [ruby/erb] Prohibit def_method on marshal-loaded ERB
|
||||
instances
|
||||
|
||||
Extends the @_init guard to def_method so that an ERB object created
|
||||
via Marshal.load (which bypasses initialize) raises ArgumentError
|
||||
instead of evaluating arbitrary source. def_module and def_class both
|
||||
delegate to def_method and are covered by the same check.
|
||||
|
||||
Co-authored-by: Tristan Madani <TristanInSec@gmail.com>
|
||||
---
|
||||
lib/erb.rb | 3 +++
|
||||
test/erb/test_erb.rb | 27 +++++++++++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/lib/erb.rb b/lib/erb.rb
|
||||
index bc1615d7da..a7317c0856 100644
|
||||
--- a/lib/erb.rb
|
||||
+++ b/lib/erb.rb
|
||||
@@ -463,6 +463,9 @@ def new_toplevel(vars = nil)
|
||||
# erb.def_method(MyClass, 'render(arg1, arg2)', filename)
|
||||
# print MyClass.new.render('foo', 123)
|
||||
def def_method(mod, methodname, fname='(ERB)')
|
||||
+ unless @_init.equal?(self.class.singleton_class)
|
||||
+ raise ArgumentError, "not initialized"
|
||||
+ end
|
||||
src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n"
|
||||
mod.module_eval do
|
||||
eval(src, binding, fname, -1)
|
||||
diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb
|
||||
index 555345a140..1266b64e41 100644
|
||||
--- a/test/erb/test_erb.rb
|
||||
+++ b/test/erb/test_erb.rb
|
||||
@@ -714,6 +714,33 @@ def test_prohibited_marshal_load
|
||||
assert_raise(ArgumentError) {erb.result}
|
||||
end
|
||||
|
||||
+ def test_prohibited_marshal_load_def_method
|
||||
+ erb = ERB.allocate
|
||||
+ erb.instance_variable_set(:@src, "")
|
||||
+ erb.instance_variable_set(:@lineno, 1)
|
||||
+ erb.instance_variable_set(:@_init, true)
|
||||
+ erb = Marshal.load(Marshal.dump(erb))
|
||||
+ assert_raise(ArgumentError) {erb.def_method(Class.new, 'render')}
|
||||
+ end
|
||||
+
|
||||
+ def test_prohibited_marshal_load_def_module
|
||||
+ erb = ERB.allocate
|
||||
+ erb.instance_variable_set(:@src, "")
|
||||
+ erb.instance_variable_set(:@lineno, 1)
|
||||
+ erb.instance_variable_set(:@_init, true)
|
||||
+ erb = Marshal.load(Marshal.dump(erb))
|
||||
+ assert_raise(ArgumentError) {erb.def_module}
|
||||
+ end
|
||||
+
|
||||
+ def test_prohibited_marshal_load_def_class
|
||||
+ erb = ERB.allocate
|
||||
+ erb.instance_variable_set(:@src, "")
|
||||
+ erb.instance_variable_set(:@lineno, 1)
|
||||
+ erb.instance_variable_set(:@_init, true)
|
||||
+ erb = Marshal.load(Marshal.dump(erb))
|
||||
+ assert_raise(ArgumentError) {erb.def_class}
|
||||
+ end
|
||||
+
|
||||
def test_multi_line_comment_lineno
|
||||
erb = ERB.new(<<~EOS)
|
||||
<%= __LINE__ %>
|
||||
|
||||
From 2f223e90edf40f5d537760cb26c77b608bddff36 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Kokubun <takashikkbn@gmail.com>
|
||||
Date: Tue, 21 Apr 2026 17:14:06 +0900
|
||||
Subject: [PATCH 2/2] [ruby/erb] Version 4.0.3.1
|
||||
|
||||
---
|
||||
lib/erb/version.rb | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/erb/version.rb b/lib/erb/version.rb
|
||||
index 295fc5fa6f..85e2a79def 100644
|
||||
--- a/lib/erb/version.rb
|
||||
+++ b/lib/erb/version.rb
|
||||
@@ -1,5 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
class ERB
|
||||
- VERSION = '4.0.3'
|
||||
+ VERSION = '4.0.3.1'
|
||||
private_constant :VERSION
|
||||
end
|
||||
@ -1,209 +0,0 @@
|
||||
From e55d73b170eb4a5523a411cdc9bd5cf13121694e Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Wed, 22 Apr 2026 11:25:06 -0400
|
||||
Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8D=92=20edit=20ca72ac45:=20=E2=99=BB?=
|
||||
=?UTF-8?q?=EF=B8=8F=20Extract=20superclass=20for=20(internal)=20command?=
|
||||
=?UTF-8?q?=20data?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Unlike the cherry-picked commit (ca72ac45), this _only_ makes
|
||||
`CommandData` the superclass for `Literal` and `Atom`. Because those
|
||||
are the classes that will be modified by later cherry-picked commits.
|
||||
This allows those other commits to merge more cleanly, and work with
|
||||
fewer modifications.
|
||||
---
|
||||
lib/net/imap/command_data.rb | 50 +++++++++++++++++++-----------------
|
||||
1 file changed, 26 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/net/imap/command_data.rb b/lib/net/imap/command_data.rb
|
||||
index 180a254..91c7336 100644
|
||||
--- a/lib/net/imap/command_data.rb
|
||||
+++ b/lib/net/imap/command_data.rb
|
||||
@@ -119,33 +119,44 @@ module Net
|
||||
put_string("\\" + symbol.to_s)
|
||||
end
|
||||
|
||||
- class RawData # :nodoc:
|
||||
- def send_data(imap, tag)
|
||||
- imap.__send__(:put_string, @data)
|
||||
+ # simplistic emulation of CommandData = Data.define(:data)
|
||||
+ class CommandData # :nodoc:
|
||||
+ class << self
|
||||
+ def new(arg = nil, data: arg) super(data: data) end
|
||||
+ alias :[] :new
|
||||
end
|
||||
|
||||
- def validate
|
||||
+ def initialize(data:)
|
||||
+ @data = data
|
||||
+ freeze
|
||||
end
|
||||
|
||||
- private
|
||||
+ attr_reader :data
|
||||
|
||||
- def initialize(data)
|
||||
- @data = data
|
||||
- end
|
||||
- end
|
||||
+ def to_h(&block) block ? to_h.to_h(&block) : { data: data } end
|
||||
+ def ==(other) self.class === other && to_h == other.to_h end
|
||||
+ def eql?(other) self.class === other && to_h.eql?(other.to_h) end
|
||||
+
|
||||
+ # following class definition goes beyond the basic Data.define(:data)
|
||||
+ ##
|
||||
|
||||
- class Atom # :nodoc:
|
||||
def send_data(imap, tag)
|
||||
- imap.__send__(:put_string, @data)
|
||||
+ raise NoMethodError, "#{self.class} must implement #{__method__}"
|
||||
end
|
||||
|
||||
def validate
|
||||
end
|
||||
+ end
|
||||
|
||||
- private
|
||||
+ class RawData < CommandData # :nodoc:
|
||||
+ def send_data(imap, tag)
|
||||
+ imap.__send__(:put_string, @data)
|
||||
+ end
|
||||
+ end
|
||||
|
||||
- def initialize(data)
|
||||
- @data = data
|
||||
+ class Atom < CommandData # :nodoc:
|
||||
+ def send_data(imap, tag)
|
||||
+ imap.__send__(:put_string, @data)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -164,19 +175,10 @@ module Net
|
||||
end
|
||||
end
|
||||
|
||||
- class Literal # :nodoc:
|
||||
+ class Literal < CommandData # :nodoc:
|
||||
def send_data(imap, tag)
|
||||
imap.__send__(:send_literal, @data, tag)
|
||||
end
|
||||
-
|
||||
- def validate
|
||||
- end
|
||||
-
|
||||
- private
|
||||
-
|
||||
- def initialize(data)
|
||||
- @data = data
|
||||
- end
|
||||
end
|
||||
|
||||
class MessageSet # :nodoc:
|
||||
|
||||
From d1c362631589b20e59f5e64fe1ee9222b3ea07f9 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Thu, 19 Feb 2026 15:06:08 -0500
|
||||
Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8D=92=20pick=209db3e9d60:=20?=
|
||||
=?UTF-8?q?=F0=9F=A5=85=20Strictly=20validate=20symbol=20(\flag)=20argumen?=
|
||||
=?UTF-8?q?ts=20[backports=20#657]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Flags should not allow `atom-specials`.
|
||||
|
||||
Previously, no validation was done on symbol data. Sending atom or flag
|
||||
args which contain atom specials could lead to various errors.
|
||||
|
||||
Although this could theoretically include injection attacks, this is not
|
||||
considered to be a critical vulnerability in `net-imap`, for the
|
||||
following reason: Valid "system flag" inputs are restricted to an
|
||||
enumerated set of RFC-defined flag types. User-defined "keyword" flags
|
||||
are sent as atoms, not flags, which use string inputs (strings which
|
||||
can't be sent as an atom will be quoted or sent as a literal). `\Seen`
|
||||
as a flag (symbol argument) is semantically different from `Seen` as a
|
||||
keyword (string argument). So there is no scenario where it is
|
||||
appropriate to call `#to_sym` on unvetted user input. Any code which
|
||||
calls `#to_sym` indiscriminately on user-input is already buggy.
|
||||
|
||||
Nevertheless, users should reasonably be able to rely on `net-imap` to
|
||||
do very basic input validation on its basic input types.
|
||||
---
|
||||
lib/net/imap/command_data.rb | 33 +++++++++++++++++++++++++++------
|
||||
1 file changed, 27 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/lib/net/imap/command_data.rb b/lib/net/imap/command_data.rb
|
||||
index 91c7336..499002f 100644
|
||||
--- a/lib/net/imap/command_data.rb
|
||||
+++ b/lib/net/imap/command_data.rb
|
||||
@@ -25,6 +25,7 @@ module Net
|
||||
end
|
||||
when Time, Date, DateTime
|
||||
when Symbol
|
||||
+ Flag.validate(data)
|
||||
else
|
||||
data.validate
|
||||
end
|
||||
@@ -45,7 +46,7 @@ module Net
|
||||
when Date
|
||||
send_date_data(data)
|
||||
when Symbol
|
||||
- send_symbol_data(data)
|
||||
+ Flag[data].send_data(self, tag)
|
||||
else
|
||||
data.send_data(self, tag)
|
||||
end
|
||||
@@ -115,10 +116,6 @@ module Net
|
||||
def send_date_data(date) put_string Net::IMAP.encode_date(date) end
|
||||
def send_time_data(time) put_string Net::IMAP.encode_time(time) end
|
||||
|
||||
- def send_symbol_data(symbol)
|
||||
- put_string("\\" + symbol.to_s)
|
||||
- end
|
||||
-
|
||||
# simplistic emulation of CommandData = Data.define(:data)
|
||||
class CommandData # :nodoc:
|
||||
class << self
|
||||
@@ -140,6 +137,12 @@ module Net
|
||||
# following class definition goes beyond the basic Data.define(:data)
|
||||
##
|
||||
|
||||
+ def self.validate(...)
|
||||
+ data = new(...)
|
||||
+ data.validate
|
||||
+ data
|
||||
+ end
|
||||
+
|
||||
def send_data(imap, tag)
|
||||
raise NoMethodError, "#{self.class} must implement #{__method__}"
|
||||
end
|
||||
@@ -155,8 +158,26 @@ module Net
|
||||
end
|
||||
|
||||
class Atom < CommandData # :nodoc:
|
||||
+ def initialize(**)
|
||||
+ super
|
||||
+ validate
|
||||
+ end
|
||||
+
|
||||
+ def validate
|
||||
+ data.to_s.ascii_only? \
|
||||
+ or raise DataFormatError, "#{self.class} must be ASCII only"
|
||||
+ data.match?(ResponseParser::Patterns::ATOM_SPECIALS) \
|
||||
+ and raise DataFormatError, "#{self.class} must not contain atom-specials"
|
||||
+ end
|
||||
+
|
||||
def send_data(imap, tag)
|
||||
- imap.__send__(:put_string, @data)
|
||||
+ imap.__send__(:put_string, data.to_s)
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
+ class Flag < Atom # :nodoc:
|
||||
+ def send_data(imap, tag)
|
||||
+ imap.__send__(:put_string, "\\#{data}")
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,340 +0,0 @@
|
||||
From cd5ccc6948eac1a0b5d5da625ab19f56df6cfaa5 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Tue, 31 Mar 2026 19:28:20 -0400
|
||||
Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8D=92=20pick=20341ab6281:=20?=
|
||||
=?UTF-8?q?=E2=9A=A1=EF=B8=8F=F0=9F=94=92=EF=B8=8F=20Fix=20non-linear=20pe?=
|
||||
=?UTF-8?q?rformance=20in=20ResponseReader?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
A very large response with many small repeated literals can trigger
|
||||
super-linear time. This happens because the regular expression that
|
||||
checks for literal continuation matches from the beginning of the buffer
|
||||
every time.
|
||||
|
||||
This could be mitigated by searching from an offset, based on what has
|
||||
already been processed, or only searching the most recent line (before
|
||||
merging it with the buffer), but that is still `O(n)` on line length.
|
||||
|
||||
The regexp is anchored to the end of the string, so searching in reverse
|
||||
from the end of the string should be `O(1)`. This is accomplished by
|
||||
converting `=~` to `rindex`.
|
||||
|
||||
Note that this _does_ slow down the "no literals" scenario.
|
||||
|
||||
```
|
||||
$ benchmark-driver benchmarks/response_reader.yml --filter KiB
|
||||
Warming up --------------------------------------
|
||||
1KiB with no literals 143.564k i/s - 153.197k times in 1.067099s (6.97μs/i)
|
||||
10KiB with no literals 27.394k i/s - 28.864k times in 1.053670s (36.50μs/i)
|
||||
100KiB with no literals 2.926k i/s - 3.157k times in 1.079109s (341.81μs/i)
|
||||
1KiB of 25B literals 2.786k i/s - 2.970k times in 1.066159s (358.98μs/i)
|
||||
10KiB of 25B literals 263.498 i/s - 286.000 times in 1.085396s (3.80ms/i)
|
||||
100KiB of 25B literals 19.470 i/s - 20.000 times in 1.027203s (51.36ms/i)
|
||||
1KiB of 0B literals 530.014 i/s - 530.000 times in 0.999974s (1.89ms/i)
|
||||
10KiB of 0B literals 45.239 i/s - 50.000 times in 1.105233s (22.10ms/i)
|
||||
100KiB of 0B literals 3.075 i/s - 4.000 times in 1.300721s (325.18ms/i)
|
||||
Calculating -------------------------------------
|
||||
local YJIT
|
||||
1KiB with no literals 137.049k 159.971k i/s - 430.691k times in 3.142607s 2.692304s
|
||||
10KiB with no literals 27.272k 28.101k i/s - 82.181k times in 3.013413s 2.924470s
|
||||
100KiB with no literals 2.941k 2.937k i/s - 8.776k times in 2.984095s 2.988129s
|
||||
1KiB of 25B literals 2.803k 4.136k i/s - 8.357k times in 2.981249s 2.020772s
|
||||
10KiB of 25B literals 262.978 385.394 i/s - 790.000 times in 3.004055s 2.049850s
|
||||
100KiB of 25B literals 18.355 22.549 i/s - 58.000 times in 3.159962s 2.572152s
|
||||
1KiB of 0B literals 505.733 759.572 i/s - 1.590k times in 3.143953s 2.093285s
|
||||
10KiB of 0B literals 45.414 67.569 i/s - 135.000 times in 2.972648s 1.997962s
|
||||
100KiB of 0B literals 2.722 3.510 i/s - 9.000 times in 3.306786s 2.564007s
|
||||
|
||||
Comparison:
|
||||
1KiB with no literals
|
||||
YJIT: 159971.1 i/s
|
||||
local: 137049.0 i/s - 1.17x slower
|
||||
|
||||
10KiB with no literals
|
||||
YJIT: 28101.2 i/s
|
||||
local: 27271.7 i/s - 1.03x slower
|
||||
|
||||
100KiB with no literals
|
||||
local: 2940.9 i/s
|
||||
YJIT: 2937.0 i/s - 1.00x slower
|
||||
|
||||
1KiB of 25B literals
|
||||
YJIT: 4135.5 i/s
|
||||
local: 2803.2 i/s - 1.48x slower
|
||||
|
||||
10KiB of 25B literals
|
||||
YJIT: 385.4 i/s
|
||||
local: 263.0 i/s - 1.47x slower
|
||||
|
||||
100KiB of 25B literals
|
||||
YJIT: 22.5 i/s
|
||||
local: 18.4 i/s - 1.23x slower
|
||||
|
||||
1KiB of 0B literals
|
||||
YJIT: 759.6 i/s
|
||||
local: 505.7 i/s - 1.50x slower
|
||||
|
||||
10KiB of 0B literals
|
||||
YJIT: 67.6 i/s
|
||||
local: 45.4 i/s - 1.49x slower
|
||||
|
||||
100KiB of 0B literals
|
||||
YJIT: 3.5 i/s
|
||||
local: 2.7 i/s - 1.29x slower
|
||||
```
|
||||
|
||||
For responses that are larger than 10KiB, the benchmarks do take another
|
||||
dip. Despite that, I believe the algorithm _is_ still linear, and that
|
||||
the performance hit on large responses is probably due to the large
|
||||
strings inducing memory locality (paging/caching) bottlenecks.
|
||||
---
|
||||
lib/net/imap/response_reader.rb | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/net/imap/response_reader.rb b/lib/net/imap/response_reader.rb
|
||||
index fd7561f..d59d672 100644
|
||||
--- a/lib/net/imap/response_reader.rb
|
||||
+++ b/lib/net/imap/response_reader.rb
|
||||
@@ -32,7 +32,7 @@ module Net
|
||||
def empty?; buff.empty? end
|
||||
def done?; line_done? && !get_literal_size end
|
||||
def line_done?; buff.end_with?(CRLF) end
|
||||
- def get_literal_size; /\{(\d+)\}\r\n\z/n =~ buff && $1.to_i end
|
||||
+ def get_literal_size; buff.rindex(/\{(\d+)\}\r\n\z/n) && $1.to_i end
|
||||
|
||||
def read_line
|
||||
buff << (@sock.gets(CRLF, read_limit) or throw :eof)
|
||||
|
||||
From c6493156d14dbac9e46a0b14e7d01ee5b83c70a9 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Wed, 15 Apr 2026 10:00:24 -0400
|
||||
Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8D=92=20pick=2049c516d62:=20?=
|
||||
=?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Faster=20ResponseParser:=20short-circuit?=
|
||||
=?UTF-8?q?=20no=20literal?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
I was suprised at how much slower `buff.rindex` is (vs `=~`) when it
|
||||
doesn't match. This speeds up that case significantly (it's now faster
|
||||
than it was prior to the `rindex` change), with only a small impact in
|
||||
the case when it does match.
|
||||
|
||||
```
|
||||
$ benchmark-driver benchmarks/response_reader.yml --filter KiB
|
||||
Warming up --------------------------------------
|
||||
1KiB with no literals 202.754k i/s - 210.144k times in 1.036449s (4.93μs/i)
|
||||
10KiB with no literals 55.683k i/s - 57.541k times in 1.033362s (17.96μs/i)
|
||||
100KiB with no literals 6.654k i/s - 7.176k times in 1.078491s (150.29μs/i)
|
||||
1KiB of 25B literals 2.780k i/s - 2.959k times in 1.064363s (359.70μs/i)
|
||||
10KiB of 25B literals 260.357 i/s - 286.000 times in 1.098491s (3.84ms/i)
|
||||
100KiB of 25B literals 19.485 i/s - 20.000 times in 1.026445s (51.32ms/i)
|
||||
1KiB of 0B literals 506.675 i/s - 550.000 times in 1.085508s (1.97ms/i)
|
||||
10KiB of 0B literals 44.384 i/s - 45.000 times in 1.013872s (22.53ms/i)
|
||||
100KiB of 0B literals 3.063 i/s - 4.000 times in 1.305939s (326.48ms/i)
|
||||
Calculating -------------------------------------
|
||||
local YJIT
|
||||
1KiB with no literals 194.355k 247.756k i/s - 608.261k times in 3.129645s 2.455086s
|
||||
10KiB with no literals 55.733k 58.585k i/s - 167.049k times in 2.997311s 2.851414s
|
||||
100KiB with no literals 6.553k 6.453k i/s - 19.961k times in 3.045870s 3.093461s
|
||||
1KiB of 25B literals 2.732k 4.061k i/s - 8.340k times in 3.052737s 2.053682s
|
||||
10KiB of 25B literals 256.552 379.524 i/s - 781.000 times in 3.044220s 2.057840s
|
||||
100KiB of 25B literals 17.804 23.286 i/s - 58.000 times in 3.257733s 2.490779s
|
||||
1KiB of 0B literals 467.714 703.446 i/s - 1.520k times in 3.249846s 2.160791s
|
||||
10KiB of 0B literals 45.376 65.876 i/s - 133.000 times in 2.931045s 2.018955s
|
||||
100KiB of 0B literals 3.072 3.840 i/s - 9.000 times in 2.929458s 2.343586s
|
||||
|
||||
Comparison:
|
||||
1KiB with no literals
|
||||
YJIT: 247755.5 i/s
|
||||
local: 194354.7 i/s - 1.27x slower
|
||||
|
||||
10KiB with no literals
|
||||
YJIT: 58584.6 i/s
|
||||
local: 55733.0 i/s - 1.05x slower
|
||||
|
||||
100KiB with no literals
|
||||
local: 6553.5 i/s
|
||||
YJIT: 6452.6 i/s - 1.02x slower
|
||||
|
||||
1KiB of 25B literals
|
||||
YJIT: 4061.0 i/s
|
||||
local: 2732.0 i/s - 1.49x slower
|
||||
|
||||
10KiB of 25B literals
|
||||
YJIT: 379.5 i/s
|
||||
local: 256.6 i/s - 1.48x slower
|
||||
|
||||
100KiB of 25B literals
|
||||
YJIT: 23.3 i/s
|
||||
local: 17.8 i/s - 1.31x slower
|
||||
|
||||
1KiB of 0B literals
|
||||
YJIT: 703.4 i/s
|
||||
local: 467.7 i/s - 1.50x slower
|
||||
|
||||
10KiB of 0B literals
|
||||
YJIT: 65.9 i/s
|
||||
local: 45.4 i/s - 1.45x slower
|
||||
|
||||
100KiB of 0B literals
|
||||
YJIT: 3.8 i/s
|
||||
local: 3.1 i/s - 1.25x slower
|
||||
```
|
||||
---
|
||||
lib/net/imap/response_reader.rb | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/net/imap/response_reader.rb b/lib/net/imap/response_reader.rb
|
||||
index d59d672..024d67a 100644
|
||||
--- a/lib/net/imap/response_reader.rb
|
||||
+++ b/lib/net/imap/response_reader.rb
|
||||
@@ -32,7 +32,10 @@ module Net
|
||||
def empty?; buff.empty? end
|
||||
def done?; line_done? && !get_literal_size end
|
||||
def line_done?; buff.end_with?(CRLF) end
|
||||
- def get_literal_size; buff.rindex(/\{(\d+)\}\r\n\z/n) && $1.to_i end
|
||||
+
|
||||
+ def get_literal_size
|
||||
+ buff.end_with?("}\r\n") && buff.rindex(/\{(\d+)\}\r\n\z/n) && $1.to_i
|
||||
+ end
|
||||
|
||||
def read_line
|
||||
buff << (@sock.gets(CRLF, read_limit) or throw :eof)
|
||||
|
||||
From 2e9d425aae61801deb18384fbd295cee6a9850a3 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Tue, 14 Apr 2026 14:40:48 -0400
|
||||
Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=8D=92=20pick=206f82e28f7:=20?=
|
||||
=?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Faster=20ResponseReader:=20parse=20literal?=
|
||||
=?UTF-8?q?=20from=20line?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Unfortunately, neither `#rindex` nor even `#end_with?` appear to be
|
||||
truly `O(1)` for very large strings (100K+). I'm guessing that this is
|
||||
due to memory locality and caching issues. But, by parsing the literal
|
||||
from the latest `line` (rather than the full buffer), we mostly avoid
|
||||
that problem.
|
||||
|
||||
Also, by explicitly parsing literal_size immediately after reading the
|
||||
line, we don't need to parse it again in `#done?`.
|
||||
|
||||
```
|
||||
$ benchmark-driver benchmarks/response_reader.yml --filter KiB
|
||||
Warming up --------------------------------------
|
||||
1KiB with no literals 202.846k i/s - 214.181k times in 1.055878s (4.93μs/i)
|
||||
10KiB with no literals 55.699k i/s - 57.354k times in 1.029717s (17.95μs/i)
|
||||
100KiB with no literals 6.622k i/s - 6.688k times in 1.009943s (151.01μs/i)
|
||||
1KiB of 25B literals 3.428k i/s - 3.751k times in 1.094065s (291.67μs/i)
|
||||
10KiB of 25B literals 342.733 i/s - 350.000 times in 1.021202s (2.92ms/i)
|
||||
100KiB of 25B literals 34.343 i/s - 36.000 times in 1.048234s (29.12ms/i)
|
||||
1KiB of 0B literals 683.800 i/s - 690.000 times in 1.009066s (1.46ms/i)
|
||||
10KiB of 0B literals 69.186 i/s - 70.000 times in 1.011759s (14.45ms/i)
|
||||
100KiB of 0B literals 6.914 i/s - 7.000 times in 1.012449s (144.64ms/i)
|
||||
Calculating -------------------------------------
|
||||
local YJIT
|
||||
1KiB with no literals 193.622k 250.330k i/s - 608.539k times in 3.142929s 2.430944s
|
||||
10KiB with no literals 55.944k 58.881k i/s - 167.096k times in 2.986849s 2.837843s
|
||||
100KiB with no literals 6.550k 6.480k i/s - 19.866k times in 3.033041s 3.065821s
|
||||
1KiB of 25B literals 3.445k 5.520k i/s - 10.285k times in 2.985693s 1.863057s
|
||||
10KiB of 25B literals 338.578 548.670 i/s - 1.028k times in 3.036224s 1.873620s
|
||||
100KiB of 25B literals 33.829 55.860 i/s - 103.000 times in 3.044728s 1.843900s
|
||||
1KiB of 0B literals 626.970 1.103k i/s - 2.051k times in 3.271287s 1.860275s
|
||||
10KiB of 0B literals 66.065 108.347 i/s - 207.000 times in 3.133301s 1.910523s
|
||||
100KiB of 0B literals 6.720 8.159 i/s - 20.000 times in 2.976273s 2.451265s
|
||||
|
||||
Comparison:
|
||||
1KiB with no literals
|
||||
YJIT: 250330.3 i/s
|
||||
local: 193621.6 i/s - 1.29x slower
|
||||
|
||||
10KiB with no literals
|
||||
YJIT: 58881.3 i/s
|
||||
local: 55943.9 i/s - 1.05x slower
|
||||
|
||||
100KiB with no literals
|
||||
local: 6549.9 i/s
|
||||
YJIT: 6479.8 i/s - 1.01x slower
|
||||
|
||||
1KiB of 25B literals
|
||||
YJIT: 5520.5 i/s
|
||||
local: 3444.8 i/s - 1.60x slower
|
||||
|
||||
10KiB of 25B literals
|
||||
YJIT: 548.7 i/s
|
||||
local: 338.6 i/s - 1.62x slower
|
||||
|
||||
100KiB of 25B literals
|
||||
YJIT: 55.9 i/s
|
||||
local: 33.8 i/s - 1.65x slower
|
||||
|
||||
1KiB of 0B literals
|
||||
YJIT: 1102.5 i/s
|
||||
local: 627.0 i/s - 1.76x slower
|
||||
|
||||
10KiB of 0B literals
|
||||
YJIT: 108.3 i/s
|
||||
local: 66.1 i/s - 1.64x slower
|
||||
|
||||
100KiB of 0B literals
|
||||
YJIT: 8.2 i/s
|
||||
local: 6.7 i/s - 1.21x slower
|
||||
```
|
||||
---
|
||||
lib/net/imap/response_reader.rb | 13 ++++++++-----
|
||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/net/imap/response_reader.rb b/lib/net/imap/response_reader.rb
|
||||
index 024d67a..56958eb 100644
|
||||
--- a/lib/net/imap/response_reader.rb
|
||||
+++ b/lib/net/imap/response_reader.rb
|
||||
@@ -8,6 +8,7 @@ module Net
|
||||
|
||||
def initialize(client, sock)
|
||||
@client, @sock = client, sock
|
||||
+ @buff = @literal_size = nil
|
||||
end
|
||||
|
||||
def read_response_buffer
|
||||
@@ -15,13 +16,13 @@ module Net
|
||||
catch :eof do
|
||||
while true
|
||||
read_line
|
||||
- break unless (@literal_size = get_literal_size)
|
||||
+ break unless literal_size
|
||||
read_literal
|
||||
end
|
||||
end
|
||||
buff
|
||||
ensure
|
||||
- @buff = nil
|
||||
+ @buff = @literal_size = nil
|
||||
end
|
||||
|
||||
private
|
||||
@@ -30,16 +31,18 @@ module Net
|
||||
|
||||
def bytes_read; buff.bytesize end
|
||||
def empty?; buff.empty? end
|
||||
- def done?; line_done? && !get_literal_size end
|
||||
+ def done?; line_done? && !literal_size end
|
||||
def line_done?; buff.end_with?(CRLF) end
|
||||
|
||||
- def get_literal_size
|
||||
+ def get_literal_size(buff)
|
||||
buff.end_with?("}\r\n") && buff.rindex(/\{(\d+)\}\r\n\z/n) && $1.to_i
|
||||
end
|
||||
|
||||
def read_line
|
||||
- buff << (@sock.gets(CRLF, read_limit) or throw :eof)
|
||||
+ line = (@sock.gets(CRLF, read_limit) or throw :eof)
|
||||
+ buff << line
|
||||
max_response_remaining! unless line_done?
|
||||
+ @literal_size = get_literal_size(line)
|
||||
end
|
||||
|
||||
def read_literal
|
||||
@ -1,116 +0,0 @@
|
||||
From 4244a308dc09682079ef461b68b08ad4ad9e5a57 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Fri, 27 Mar 2026 17:31:11 -0400
|
||||
Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8D=92=20pick=2062eea6ffe:=20?=
|
||||
=?UTF-8?q?=F0=9F=94=92=F0=9F=A5=85=20Ensure=20STARTTLS=20tagged=20respons?=
|
||||
=?UTF-8?q?e=20was=20handled=20[backport=20#664]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Taking a "belt-and-suspenders" approach to a STARTTLS stripping attack:
|
||||
|
||||
This handles `STARTTLS` as a special-case: if the `STARTTLS` handler
|
||||
did not run, for _whatever_ reason, an exception _must_ be raised and
|
||||
the connection dropped.
|
||||
|
||||
_No_ command should ever receive a tagged `OK` prior to completely
|
||||
sending the command. But `STARTTLS` is security-sensitive enough to
|
||||
warrant this special-case handler.
|
||||
---
|
||||
lib/net/imap.rb | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index 84bc094..a8ac7d8 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -1294,9 +1294,11 @@ module Net
|
||||
#
|
||||
def starttls(**options)
|
||||
@ssl_ctx_params, @ssl_ctx = build_ssl_ctx(options)
|
||||
+ handled = false
|
||||
error = nil
|
||||
ok = send_command("STARTTLS") do |resp|
|
||||
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
||||
+ handled = true
|
||||
clear_cached_capabilities
|
||||
clear_responses
|
||||
start_tls_session
|
||||
@@ -1308,6 +1310,13 @@ module Net
|
||||
disconnect
|
||||
raise error
|
||||
end
|
||||
+ unless handled
|
||||
+ disconnect
|
||||
+ raise InvalidResponseError,
|
||||
+ "STARTTLS handler was bypassed, although server responded %p" % [
|
||||
+ ok.raw_data.chomp
|
||||
+ ]
|
||||
+ end
|
||||
ok
|
||||
end
|
||||
|
||||
|
||||
From 00192b9a410251c5ed76c96be564d739cba67008 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Fri, 27 Mar 2026 18:00:09 -0400
|
||||
Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8D=92=20pick=2024d5c773d:=20?=
|
||||
=?UTF-8?q?=F0=9F=94=92=F0=9F=A5=85=20Handle=20tagged=20"OK"=20to=20incomp?=
|
||||
=?UTF-8?q?lete=20command=20[backport=20#664]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Taking a "belt-and-suspenders" approach:
|
||||
|
||||
This is a potential problem for any command which registers a response
|
||||
handler: a malicious server can easily guess what the next tag will be,
|
||||
and send an `OK` response _before_ the client the response handler is
|
||||
attached.
|
||||
|
||||
`STARTTLS` is an extreme example of this issue: if the `STARTTLS`
|
||||
handler does not run, then `#starttls` will not start the TLS session,
|
||||
and the connection is not secured, _but no error is raised._
|
||||
|
||||
We should _also_ attach the response handler before sending the `CRLF`,
|
||||
but that is neither necessary (the response handler will added before
|
||||
the `synchronize` mutex is unlocked) nor sufficient (the fake `OK` can
|
||||
be sent _much_ earlier).
|
||||
|
||||
On the other hand, it _is_ okay for the server to send an error tagged
|
||||
response (`NO` or `BAD`), before the sending the command has completed.
|
||||
---
|
||||
lib/net/imap.rb | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index a8ac7d8..b9072b1 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -3001,6 +3001,7 @@ module Net
|
||||
put_string(" ")
|
||||
send_data(i, tag)
|
||||
end
|
||||
+ guard_against_tagged_response_skipping_handler!(tag)
|
||||
put_string(CRLF)
|
||||
if cmd == "LOGOUT"
|
||||
@logout_command_tag = tag
|
||||
@@ -3016,6 +3017,17 @@ module Net
|
||||
end
|
||||
end
|
||||
end
|
||||
+ rescue InvalidResponseError
|
||||
+ disconnect
|
||||
+ raise
|
||||
+ end
|
||||
+
|
||||
+ def guard_against_tagged_response_skipping_handler!(tag)
|
||||
+ return unless (resp = @tagged_responses[tag])&.name&.upcase == "OK"
|
||||
+ raise(InvalidResponseError,
|
||||
+ "Server sent tagged 'OK' before command was finished: %p. " \
|
||||
+ "This could indicate a malicious server or client-side " \
|
||||
+ "command injection. Disconnecting." % [resp.raw_data.chomp])
|
||||
end
|
||||
|
||||
def generate_tag
|
||||
@ -1,6 +1,6 @@
|
||||
%global major_version 3
|
||||
%global minor_version 3
|
||||
%global teeny_version 10
|
||||
%global teeny_version 12
|
||||
%global major_minor_version %{major_version}.%{minor_version}
|
||||
|
||||
%global ruby_version %{major_minor_version}.%{teeny_version}
|
||||
@ -36,7 +36,7 @@
|
||||
%global rubygems_securerandom_version 0.3.1
|
||||
%global rubygems_timeout_version 0.4.1
|
||||
%global rubygems_tsort_version 0.2.0
|
||||
%global rubygems_uri_version 0.13.1
|
||||
%global rubygems_uri_version 0.13.3
|
||||
|
||||
# Default gems.
|
||||
%global bundler_version 2.5.22
|
||||
@ -47,7 +47,7 @@
|
||||
%global bundler_securerandom_version 0.3.1
|
||||
%global bundler_thor_version 1.3.0
|
||||
%global bundler_tsort_version 0.2.0
|
||||
%global bundler_uri_version 0.13.1
|
||||
%global bundler_uri_version 0.13.3
|
||||
|
||||
%global abbrev_version 0.1.2
|
||||
%global base64_version 0.2.0
|
||||
@ -79,14 +79,14 @@
|
||||
%global nkf_version 0.1.3
|
||||
%global observer_version 0.1.2
|
||||
%global open3_version 0.2.1
|
||||
%global openssl_version 3.2.2
|
||||
%global openssl_version 3.2.4
|
||||
%global open_uri_version 0.4.1
|
||||
%global optparse_version 0.4.0
|
||||
%global ostruct_version 0.6.0
|
||||
%global pathname_version 0.3.0
|
||||
%global pp_version 0.5.0
|
||||
%global prettyprint_version 0.2.0
|
||||
%global pstore_version 0.1.3
|
||||
%global pstore_version 0.2.1
|
||||
%global readline_version 0.0.4
|
||||
%global reline_version 0.5.10
|
||||
%global resolv_version 0.3.1
|
||||
@ -99,7 +99,7 @@
|
||||
%global singleton_version 0.2.0
|
||||
%global stringio_version 3.1.1
|
||||
%global strscan_version 3.0.9
|
||||
%global syntax_suggest_version 2.0.1
|
||||
%global syntax_suggest_version 2.0.3
|
||||
%global syslog_version 0.1.2
|
||||
%global tempfile_version 0.2.1
|
||||
%global time_version 0.3.0
|
||||
@ -112,7 +112,7 @@
|
||||
%global win32ole_version 1.8.10
|
||||
%global yaml_version 0.3.0
|
||||
%global prism_version 0.19.0
|
||||
%global zlib_version 3.1.1
|
||||
%global zlib_version 3.1.2
|
||||
|
||||
# Gemified default gems.
|
||||
%global bigdecimal_version 3.1.5
|
||||
@ -125,7 +125,7 @@
|
||||
# Bundled gems.
|
||||
%global debug_version 1.9.2
|
||||
%global net_ftp_version 0.3.4
|
||||
%global net_imap_version 0.4.21
|
||||
%global net_imap_version 0.4.25
|
||||
%global net_pop_version 0.1.2
|
||||
%global net_smtp_version 0.5.1
|
||||
%global matrix_version 0.4.2
|
||||
@ -169,7 +169,7 @@
|
||||
Summary: An interpreter of object-oriented scripting language
|
||||
Name: ruby
|
||||
Version: %{ruby_version}%{?development_release}
|
||||
Release: 7%{?dist}
|
||||
Release: 8%{?dist}
|
||||
# Licenses, which are likely not included in binary RPMs:
|
||||
# Apache-2.0:
|
||||
# benchmark/gc/redblack.rb
|
||||
@ -278,30 +278,10 @@ Patch9: ruby-3.3.0-Disable-syntax-suggest-test-case.patch
|
||||
# Make sure hardeding flags are correctly applied.
|
||||
# https://bugs.ruby-lang.org/issues/20520
|
||||
Patch12: ruby-3.4.0-Extract-hardening-CFLAGS-to-a-special-hardenflags-variable.patch
|
||||
# Fix arbitrary code execution via deserialization bypass in ERB. (CVE-2026-41316)
|
||||
# Include the version bump here as that's the only change from 4.0.3 to 4.0.3.1
|
||||
# and is expected to be included in next Ruby 3.3.
|
||||
# https://github.com/ruby/ruby/commit/a53f3d57d1c70f35534c457de2c471d84a55956a
|
||||
# https://github.com/ruby/ruby/commit/2f223e90edf40f5d537760cb26c77b608bddff36
|
||||
Patch13: rubygem-erb-4.0.3.1-Fix-arbitrary-code-execution-via-deserialization-bypass-CVE-2026-41316.patch
|
||||
# Test commits from PR were dropped. The gem does not have tests in the ruby tar.
|
||||
# Backported from
|
||||
# https://github.com/ruby/net-imap/commit/f46fe38
|
||||
# https://github.com/ruby/net-imap/commit/0560d26
|
||||
# https://github.com/ruby/net-imap/commit/bfdae21
|
||||
Patch14: rubygem-net-imap-0.4.24-DoS-via-crafted-IMAP-responses-CVE-2026-42245.patch
|
||||
# Test commits from PR were dropped. The gem does not have tests in the ruby tar.
|
||||
# Backported from
|
||||
# https://github.com/ruby/net-imap/commit/705aa59
|
||||
# https://github.com/ruby/net-imap/commit/038ae35
|
||||
Patch15: rubygem-net-imap-0.4.24-Information-disclosure-via-MITM-attack-bypassing-TLS-2026-42246.patch
|
||||
# Tests not included, the gem does not have tests in the ruby tar.
|
||||
# Original source PR#663 but it bunches more fixes together, so we backport less.
|
||||
# https://github.com/ruby/net-imap/pull/663
|
||||
# Backported from the following, the first commit below is requirement for the actual fix:
|
||||
# https://github.com/ruby/net-imap/commit/1eb27278a601be1135910dae6ab6e517559a2e4a
|
||||
# https://github.com/ruby/net-imap/commit/bbd9eb7ecca506fa43b656368f7aebef8ac09182
|
||||
Patch16: rubygem-net-imap-0.4.24-Command-Injection-via-Symbol-Arguments-CVE-2026-42258.patch
|
||||
# Workaround for a weird failure that happens only during mockbuild of Ruby src.rpm
|
||||
# Cannot reproduce sufficiently so far for the issue to appear outside that environment.
|
||||
# See patch's commit message for more information.
|
||||
Patch13: ruby-3.3.12-Allow-up-to-1-send-from-exits-YJIT-stat-for-proc-tes.patch
|
||||
|
||||
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
|
||||
%{?with_rubypick:Suggests: rubypick}
|
||||
@ -779,12 +759,6 @@ analysis result in RBS format, a standard type description format for Ruby
|
||||
%patch -P 12 -p1
|
||||
%patch -P 13 -p1
|
||||
|
||||
pushd .bundle/gems/net-imap-%{net_imap_version}
|
||||
%patch -P 14 -p1
|
||||
%patch -P 15 -p1
|
||||
%patch -P 16 -p1
|
||||
popd
|
||||
|
||||
# Provide an example of usage of the tapset:
|
||||
cp -a %{SOURCE3} .
|
||||
|
||||
@ -1568,7 +1542,6 @@ make -C %{_vpath_builddir} runruby TESTRUN_SCRIPT=" \
|
||||
|
||||
%files doc -f .ruby-doc.en -f .ruby-doc.ja
|
||||
%doc README.md
|
||||
%doc ChangeLog
|
||||
%{?with_systemtap:%doc ruby-exercise.stp}
|
||||
%{_datadir}/ri
|
||||
|
||||
@ -1800,6 +1773,11 @@ make -C %{_vpath_builddir} runruby TESTRUN_SCRIPT=" \
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Jul 23 2026 Jarek Prokop <jprokop@redhat.com> - 3.3.12-8
|
||||
- Upgrade to Ruby 3.3.12.
|
||||
Resolves: RHEL-170929
|
||||
Resolves: RHEL-193664
|
||||
|
||||
* Thu Jun 11 2026 Jarek Prokop <jprokop@redhat.com> - 3.3.10-7
|
||||
- Fix DoS via crafted IMAP responses in net-imap. (CVE-2026-42245)
|
||||
Resolves: RHEL-181682
|
||||
|
||||
Loading…
Reference in New Issue
Block a user