public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/rubygems] f44: Update to RubyGems 4.0.20
@ 2026-09-10 7:15 Mamoru TASAKA
0 siblings, 0 replies; only message in thread
From: Mamoru TASAKA @ 2026-09-10 7:15 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/rubygems
Branch : f44
Commit : 57adcecd3c079dada37ec29de970b071906901cf
Author : Mamoru TASAKA <mtasaka@fedoraproject.org>
Date : 2026-09-03T23:46:39+09:00
Stats : +240/-6 in 4 file(s)
URL : https://src.fedoraproject.org/rpms/rubygems/c/57adcecd3c079dada37ec29de970b071906901cf?branch=f44
Log:
Update to RubyGems 4.0.20
Backport ruby upstream patch to update resolv to 0.7.2
Resolves: CVE-2026-80212 (rhbz#2527309)
Resolves: CVE-2026-80213 (rhbz#2527311)
---
diff --git a/rubygem-4.0.20-update-resolv-0_7_2.patch b/rubygem-4.0.20-update-resolv-0_7_2.patch
new file mode 100644
index 0000000..ff928cf
--- /dev/null
+++ b/rubygem-4.0.20-update-resolv-0_7_2.patch
@@ -0,0 +1,224 @@
+--- rubygems-4.0.20.orig/lib/rubygems/vendor/resolv/lib/resolv.rb 2026-07-14 09:22:10.000000000 +0900
++++ rubygems-4.0.20/lib/rubygems/vendor/resolv/lib/resolv.rb 2026-09-03 17:16:18.543025164 +0900
+@@ -35,7 +35,7 @@
+ class Gem::Resolv
+
+ # The version string
+- VERSION = "0.7.0"
++ VERSION = "0.7.2"
+
+ ##
+ # Looks up the first IP address for +name+.
+@@ -487,13 +487,18 @@ def each_name(address)
+ # * Gem::Resolv::DNS::Resource::IN::A
+ # * Gem::Resolv::DNS::Resource::IN::AAAA
+ # * Gem::Resolv::DNS::Resource::IN::ANY
++ # * Gem::Resolv::DNS::Resource::IN::CAA
+ # * Gem::Resolv::DNS::Resource::IN::CNAME
+ # * Gem::Resolv::DNS::Resource::IN::HINFO
++ # * Gem::Resolv::DNS::Resource::IN::HTTPS
++ # * Gem::Resolv::DNS::Resource::IN::LOC
+ # * Gem::Resolv::DNS::Resource::IN::MINFO
+ # * Gem::Resolv::DNS::Resource::IN::MX
+ # * Gem::Resolv::DNS::Resource::IN::NS
+ # * Gem::Resolv::DNS::Resource::IN::PTR
+ # * Gem::Resolv::DNS::Resource::IN::SOA
++ # * Gem::Resolv::DNS::Resource::IN::SRV
++ # * Gem::Resolv::DNS::Resource::IN::SVCB
+ # * Gem::Resolv::DNS::Resource::IN::TXT
+ # * Gem::Resolv::DNS::Resource::IN::WKS
+ #
+@@ -721,7 +726,8 @@ def request(sender, tout)
+ begin
+ reply, from = recv_reply(select_result[0])
+ rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
+- Errno::ECONNRESET # Windows
++ Errno::ECONNRESET, # Windows
++ EOFError
+ # No name server running on the server?
+ # Don't wait anymore.
+ raise ResolvTimeout
+@@ -930,8 +936,11 @@ def initialize(host, port=Port)
+ end
+
+ def recv_reply(readable_socks)
+- len = readable_socks[0].read(2).unpack('n')[0]
++ len_data = readable_socks[0].read(2)
++ raise EOFError if len_data.nil? || len_data.bytesize != 2
++ len = len_data.unpack('n')[0]
+ reply = @socks[0].read(len)
++ raise EOFError if reply.nil? || reply.bytesize != len
+ return reply, nil
+ end
+
+@@ -1244,6 +1253,13 @@ def self.split(arg)
+
+ class Str # :nodoc:
+ def initialize(string)
++ # A label is limited to 63 octets. [RFC 1035 2.3.4] Checking it here
++ # makes it an invariant of the object: every label, however it was
++ # built, fits in its length octet and cannot wrap it. Callers turn
++ # this into the error their own contract promises.
++ if string.bytesize > 63
++ raise ArgumentError, "DNS label is too long (#{string.bytesize} bytes, max 63): #{string.inspect}"
++ end
+ @string = string
+ # case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
+ # This assumes @string is given in ASCII compatible encoding.
+@@ -1289,7 +1305,26 @@ def self.create(arg)
+ when Name
+ return arg
+ when String
+- return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false)
++ # A hostname is runtime data rather than a programming mistake, so
++ # both size limits surface as ResolvError to stay rescuable alongside
++ # the rest of name resolution. The type check below is a caller
++ # mistake and keeps raising ArgumentError.
++ begin
++ labels = Label.split(arg)
++ rescue ArgumentError => e
++ raise ResolvError.new(e.message)
++ end
++ # Label::Str enforces the per-label limit. Only the total is knowable
++ # here, and it counts the encoded form, so size starts at 1 for the
++ # root label's terminating zero octet. [RFC 1035 2.3.4, 3.1]
++ size = 1
++ labels.each do |label|
++ size += 1 + label.string.bytesize
++ if size > 255
++ raise ResolvError.new("DNS name is too long (#{size} octets, max 255): #{arg.inspect}")
++ end
++ end
++ return Name.new(labels, /\.\z/ =~ arg ? true : false)
+ else
+ raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
+ end
+@@ -1411,12 +1446,24 @@ def ==(other)
+ @rd == other.rd &&
+ @ra == other.ra &&
+ @rcode == other.rcode &&
+- @question == other.question &&
++ question_equal?(other.question) &&
+ @answer == other.answer &&
+ @authority == other.authority &&
+ @additional == other.additional
+ end
+
++ # A question holds the resource class itself, and decoding creates a fresh
++ # class for each unknown type, so the classes cannot be compared by
++ # identity alone.
++ private def question_equal?(other_question) # :nodoc:
++ return false unless @question.length == other_question.length
++ @question.zip(other_question) {|(name, typeclass), (o_name, o_typeclass)|
++ return false unless name == o_name &&
++ Resource::Generic.type_class_equal?(typeclass, o_typeclass)
++ }
++ return true
++ end
++
+ def add_question(name, typeclass)
+ @question << [Name.create(name), typeclass]
+ end
+@@ -1523,8 +1570,15 @@ def put_length16
+ end
+
+ def put_string(d)
+- self.put_pack("C", d.length)
+- @data << d
++ s = d.to_s
++ # A character-string is prefixed by a single length octet, so it can
++ # hold at most 255 octets. [RFC 1035 3.3] Reject anything longer to
++ # avoid silently truncating the length to its low 8 bits (mod 256).
++ if s.bytesize > 255
++ raise ArgumentError, "character-string is too long (#{s.bytesize} bytes, max 255): #{s.inspect}"
++ end
++ self.put_pack("C", s.bytesize)
++ @data << s
+ end
+
+ def put_string_list(ds)
+@@ -1554,7 +1608,17 @@ def put_labels(d, compress: true)
+ end
+
+ def put_label(d)
+- self.put_string(d.to_s)
++ s = d.to_s
++ # Label::Str applies this limit when a label is built, so what is left
++ # for here is a raw string handed straight to put_labels. The two ways
++ # an over-long label goes wrong differ: 64 to 255 octets write a length
++ # octet in the reserved or compression pointer range, and 256 or more
++ # wrap it mod 256. Either way the encoded name stops being the name the
++ # caller asked for. [RFC 1035 2.3.4, 4.1.4]
++ if s.bytesize > 63
++ raise ArgumentError, "DNS label is too long (#{s.bytesize} bytes, max 63): #{s.inspect}"
++ end
++ self.put_string(s)
+ end
+ end
+
+@@ -1680,7 +1744,9 @@ def get_labels
+ prev_index = @index
+ save_index = nil
+ d = []
+- size = -1
++ # size counts the encoded form, so it starts at 1 for the root
++ # label's terminating zero octet. [RFC 1035 3.1]
++ size = 1
+ while true
+ raise DecodeError.new("limit exceeded") if @limit <= @index
+ case @data.getbyte(@index)
+@@ -1711,6 +1777,11 @@ def get_labels
+
+ def get_label
+ return Label::Str.new(self.get_string)
++ rescue ArgumentError => e
++ # A length octet of 64..191 is reserved rather than a label length,
++ # but this decoder used to read it as one. [RFC 1035 4.1.4] Report it
++ # the way the rest of a malformed message is reported.
++ raise DecodeError.new(e.message)
+ end
+
+ def get_question
+@@ -1898,8 +1969,9 @@ def self.create(key_number)
+ key_name = :"key#{key_number}"
+ c.const_set(:KeyName, key_name)
+ c.const_set(:KeyNumber, key_number)
+- self.const_set(:"Key#{key_number}", c)
+- ClassHash[key_name] = ClassHash[key_number] = c
++ # Not registered in a constant or in ClassHash. ClassHash creates a
++ # class for every unknown SvcParamKey, so registering them
++ # permanently would let a malicious response exhaust memory.
+ return c
+ end
+ end
+@@ -2206,12 +2278,28 @@ def self.decode_rdata(msg) # :nodoc:
+ return self.new(msg.get_bytes)
+ end
+
++ # create makes a fresh class for each decoded resource, so the type and
++ # class values have to be compared instead of the class itself.
++ def self.type_class_equal?(klass, other) # :nodoc:
++ return true if klass.equal?(other)
++ Generic > klass && Generic > other &&
++ klass::TypeValue == other::TypeValue &&
++ klass::ClassValue == other::ClassValue
++ end
++
++ def ==(other) # :nodoc:
++ return other.is_a?(Generic) &&
++ Generic.type_class_equal?(self.class, other.class) &&
++ @data == other.data
++ end
++
+ def self.create(type_value, class_value) # :nodoc:
+ c = Class.new(Generic)
+ c.const_set(:TypeValue, type_value)
+ c.const_set(:ClassValue, class_value)
+- Generic.const_set("Type#{type_value}_Class#{class_value}", c)
+- ClassHash[[type_value, class_value]] = c
++ # Not registered in a constant or in ClassHash. get_class creates a
++ # class for every unknown (type, class) pair, so registering them
++ # permanently would let a malicious response exhaust memory.
+ return c
+ end
+ end
diff --git a/rubygems-create-missing-test-files.sh b/rubygems-create-missing-test-files.sh
index ec598a0..7566ab9 100644
--- a/rubygems-create-missing-test-files.sh
+++ b/rubygems-create-missing-test-files.sh
@@ -29,6 +29,7 @@ cd ..
tar czf $CURDIR/${PKGNAME}-${VERSION}-test-missing-files.tar.gz \
${GITTOPDIR}/test/ \
+ ${GITTOPDIR}/bundler/spec/support/*.rb \
popd
rm -rf $TMPDIR
diff --git a/rubygems.spec b/rubygems.spec
index f8859e5..bc7c1a9 100644
--- a/rubygems.spec
+++ b/rubygems.spec
@@ -7,14 +7,14 @@
%global rubygems_net_http_version 0.7.0
%global rubygems_net_protocol_version 0.2.2
%global rubygems_optparse_version 0.8.0
-%global rubygems_resolv_version 0.7.0
+%global rubygems_resolv_version 0.7.2
%global rubygems_securerandom_version 0.4.1
%global rubygems_timeout_version 0.4.4
%global rubygems_tsort_version 0.2.0
%global rubygems_uri_version 1.1.1
# Requires versions
-%global bundler_version 4.0.19
+%global bundler_version 4.0.20
%global psych_version 5.3.1
%global rdoc_version 7.0.3
@@ -38,7 +38,7 @@
Summary: The Ruby standard for packaging ruby libraries
Name: rubygems
-Version: 4.0.19
+Version: 4.0.20
Release: 1%{?dist}
# BSD-2-Clause OR Ruby:
# lib/rubygems/net-http/
@@ -79,7 +79,9 @@ Source12: check_CVE-2013-4363.rb
# https://bugs.ruby-lang.org/issues/11002
# NOTE: Keep this patch in sync with ruby.spec.
Patch0: ruby-2.3.0-ruby_version.patch
-
+# Backport from ruby/ruby_4_0 branch to update resolv to 0.7.2 (fixes CVE-2026-80212 CVE-2026-80213)
+# https://github.com/ruby/ruby/pull/18528
+Patch1: rubygem-4.0.20-update-resolv-0_7_2.patch
Requires: ruby(release)
Recommends: rubygem(bundler) >= 4.0
@@ -132,6 +134,7 @@ Documentation for %{name}.
%setup -q -b 2
%patch 0 -p1
+%patch 1 -p1
%build
# Nothing
@@ -334,6 +337,12 @@ ruby %{SOURCE12}
%changelog
+* Thu Sep 03 2026 Mamoru TASAKA <mtasaka@fedoraproject.org> - 4.0.20-1
+- Update to RubyGems 4.0.20
+- Backport ruby upstream patch to update resolv to 0.7.2
+- Resolves: CVE-2026-80212 (rhbz#2527309)
+- Resolves: CVE-2026-80213 (rhbz#2527311)
+
* Sat Aug 22 2026 Mamoru TASAKA <mtasaka@fedoraproject.org> - 4.0.19-1
- Update to RubyGems 4.0.19
diff --git a/sources b/sources
index abebe88..5866189 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
-SHA512 (rubygems-4.0.19.tgz) = a35400cee5cfb4ce662bbbd7d31cc12f5fe2ab6bf2c7f3bb6d5c3035a9566b82b4fbaeeb8dbdde63ec030da1207e4af41fad423ef8efacc0adbf45927b4631df
-SHA512 (rubygems-4.0.19-test-missing-files.tar.gz) = 3d43998c985e3824cf75cd330f86f10f7f1aeb32a0540a03f7809b014f50588489c028ca29d75b9ed4b36e8eb468cc503c88b15e7844c2206e311f0d921b65ac
+SHA512 (rubygems-4.0.20.tgz) = 224c8feb43dc6d8713c911db07fa4c6a888ed1cc01ca87f1b63e8c70afa728596be329f95add09d5e09d985f741f306911900238c93b67a245be3c69583f0cd9
+SHA512 (rubygems-4.0.20-test-missing-files.tar.gz) = 302964d038c239e38c40c949c887d0daaa108259598d63130a41fb46c7f77ebd13d1c10f78a6ceb0e09c5d11bc12045f659f555a52d8ad5b5ebeae0240cd4f6b
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-10 7:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-10 7:15 [rpms/rubygems] f44: Update to RubyGems 4.0.20 Mamoru TASAKA
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox