Skip to content

Gem::Platform.match no longer behaves properly with a String argument #5938

Closed
@flavorjones

Description

@flavorjones

Describe the problem as clearly as you can

When passing a string to Gem::Platform.match, the behavior of the method is the same as before 1b9f7f5 introduced a fix for musl platforms.

Although Gem::Platform#=~ properly coerces the other argument, the #match method, when passed a String, will instead invoke String#=~.

The interesting bit can be seen in the docstring for String#=~ (from https://ruby-doc.org/core-3.1.2/String.html#method-i-3D~)

If the given object is not a Regexp, returns the value returned by object =~ self.

thereby avoiding the intended behavior change of 1b9f7f5

Did you try upgrading RubyGems?

Present in 3.3.22

Post steps to reproduce the problem

On a x86_64-linux-musl system (e.g., ruby:3.1-alpine image):

#! /usr/bin/env ruby

Gem::VERSION # => "3.3.22"
Gem::Platform.local # => #<Gem::Platform:0x00007fda5ca0e0b8 @cpu="x86_64", @os="linux", @version="musl">

gem_platform_string = "x86_64-linux"
gem_platform = Gem::Platform.new(gem_platform_string)

Gem::Platform.match(gem_platform_string) # => false
Gem::Platform.match(gem_platform) # => true

Run gem env and paste the output below

RubyGems Environment:
  - RUBYGEMS VERSION: 3.3.22
  - RUBY VERSION: 3.1.2 (2022-04-12 patchlevel 20) [x86_64-linux-musl]
  - INSTALLATION DIRECTORY: /usr/local/bundle
  - USER INSTALLATION DIRECTORY: /root/.local/share/gem/ruby/3.1.0
  - RUBY EXECUTABLE: /usr/local/bin/ruby
  - GIT EXECUTABLE: 
  - EXECUTABLE DIRECTORY: /usr/local/bundle/bin
  - SPEC CACHE DIRECTORY: /root/.local/share/gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /usr/local/etc
  - RUBYGEMS PLATFORMS:
     - ruby
     - x86_64-linux-musl
  - GEM PATHS:
     - /usr/local/bundle
     - /root/.local/share/gem/ruby/3.1.0
     - /usr/local/lib/ruby/gems/3.1.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => true
     - :bulk_threshold => 1000
     - "install" => "--no-document"
     - "update" => "--no-document"
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /usr/local/bundle/bin
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin

Proposed fix

I think the right thing to do here is to coerce the argument to a Gem::Platform object, so something like:

diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index 06de5de..1dacc59 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -22,6 +22,7 @@ def self.match(platform)
   end
 
   def self.match_platforms?(platform, platforms)
+    platform = Gem::Platform.new(platform) unless platform.is_a?(Gem::Platform)
     platforms.any? do |local_platform|
       platform.nil? ||
         local_platform == platform ||

I couldn't figure out how to write a nice test for this, but hopefully I've provided enough detail?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions