diff options
author | David RodrÃguez <[email protected]> | 2022-08-04 13:02:18 +0200 |
---|---|---|
committer | git <[email protected]> | 2022-08-23 05:50:21 +0900 |
commit | 9819283044b6955f4e3b464e6a99196e84ed107a (patch) | |
tree | 72b22031a41969d4bccd3f4a199735829b86620b | |
parent | f254b673f89c12c42538d84b431116cf5ed0cde7 (diff) |
[rubygems/rubygems] Handle non-gnu libc on linux platforms in RubyGems
Attempting to install a gem published as both *-linux and *-linux-musl
results in the incorrect gem being picked up, causing build failures due
to binary incompatibility. This is caused by the `nil` wildcard
swallowing the libc information upon version comparison.
Handle the linux case by performing only non-wildcard equality on the
version and asserting 'gnu' and nil equivalence, while preserving the
current behaviour for other OSes.
https://github.com/rubygems/rubygems/commit/9eead86abc
Co-authored-by: Loic Nageleisen <[email protected]>
-rw-r--r-- | lib/rubygems/platform.rb | 15 | ||||
-rw-r--r-- | test/rubygems/test_gem_platform.rb | 30 |
2 files changed, 43 insertions, 2 deletions
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb index 0c0520e1db..1f699c23e0 100644 --- a/lib/rubygems/platform.rb +++ b/lib/rubygems/platform.rb @@ -151,10 +151,17 @@ class Gem::Platform ## # Does +other+ match this platform? Two platforms match if they have the # same CPU, or either has a CPU of 'universal', they have the same OS, and - # they have the same version, or either has no version. + # they have the same version, or either one has no version # # Additionally, the platform will match if the local CPU is 'arm' and the # other CPU starts with "arm" (for generic ARM family support). + # + # Of note, this method is not commutative. Indeed the OS 'linux' has a + # special case: the version is the libc name, yet while "no version" stands + # as a wildcard for a binary gem platform (as for other OSes), for the + # runtime platform "no version" stands for 'gnu'. To be able to disinguish + # these, the method receiver is the gem platform, while the argument is + # the runtime platform. def ===(other) return nil unless Gem::Platform === other @@ -171,7 +178,11 @@ class Gem::Platform @os == other.os && # version - (@version.nil? || other.version.nil? || @version == other.version) + ( + (@os != "linux" && (@version.nil? || other.version.nil?)) || + (@os == "linux" && (@version.nil? && !other.version.nil?)) || + @version == other.version + ) end ## diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb index 831079acb2..197f19e53c 100644 --- a/test/rubygems/test_gem_platform.rb +++ b/test/rubygems/test_gem_platform.rb @@ -135,7 +135,9 @@ class TestGemPlatform < Gem::TestCase "i386-solaris2.8" => ["x86", "solaris", "2.8"], "mswin32" => ["x86", "mswin32", nil], "x86_64-linux" => ["x86_64", "linux", nil], + "x86_64-linux-gnu" => ["x86_64", "linux", nil], "x86_64-linux-musl" => ["x86_64", "linux", "musl"], + "x86_64-linux-uclibc" => ["x86_64", "linux", "uclibc"], "x86_64-openbsd3.9" => ["x86_64", "openbsd", "3.9"], "x86_64-openbsd4.0" => ["x86_64", "openbsd", "4.0"], "x86_64-openbsd" => ["x86_64", "openbsd", nil], @@ -263,6 +265,34 @@ class TestGemPlatform < Gem::TestCase assert((with_x86_arch === with_nil_arch), "x86 =~ nil") end + def test_nil_version_is_treated_as_any_version + x86_darwin_8 = Gem::Platform.new "i686-darwin8.0" + x86_darwin_nil = Gem::Platform.new "i686-darwin" + + assert((x86_darwin_8 === x86_darwin_nil), "8.0 =~ nil") + assert((x86_darwin_nil === x86_darwin_8), "nil =~ 8.0") + end + + def test_nil_version_is_stricter_for_linux_os + x86_linux = Gem::Platform.new "i686-linux" + x86_linux_gnu = Gem::Platform.new "i686-linux-gnu" + x86_linux_musl = Gem::Platform.new "i686-linux-musl" + x86_linux_uclibc = Gem::Platform.new "i686-linux-uclibc" + + # a naked linux runtime is implicit gnu, as it represents the common glibc-linked runtime + assert(x86_linux === x86_linux_gnu, "linux =~ linux-gnu") + assert(x86_linux_gnu === x86_linux, "linux-gnu =~ linux") + + # explicit libc differ + refute(x86_linux_uclibc === x86_linux_musl, "linux-uclibc =~ linux-musl") + refute(x86_linux_musl === x86_linux_uclibc, "linux-musl =~ linux-uclibc") + + # musl host runtime accepts libc-generic or statically linked gems... + assert(x86_linux === x86_linux_musl, "linux =~ linux-musl") + # ...but implicit gnu runtime generally does not accept musl-specific gems + refute(x86_linux_musl === x86_linux, "linux-musl =~ linux") + end + def test_equals3_cpu_arm arm = Gem::Platform.new "arm-linux" armv5 = Gem::Platform.new "armv5-linux" |