diff options
37 files changed, 466 insertions, 1429 deletions
diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml index 3011a04cac..50c7bc190a 100644 --- a/.github/workflows/zjit-macos.yml +++ b/.github/workflows/zjit-macos.yml @@ -93,7 +93,7 @@ jobs: rustup install ${{ matrix.rust_version }} --profile minimal rustup default ${{ matrix.rust_version }} - - uses: taiki-e/install-action@8f531eaecd1898bc3da7d104ad91bee98d1b97bd # v2.79.9 + - uses: taiki-e/install-action@13608cbb45b01feb47ef444ab1a42dc41ad56f1a # v2.79.11 with: tool: nextest@0.9 if: ${{ matrix.test_task == 'zjit-check' }} diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml index d91dfcbeeb..1e7bec3859 100644 --- a/.github/workflows/zjit-ubuntu.yml +++ b/.github/workflows/zjit-ubuntu.yml @@ -119,7 +119,7 @@ jobs: ruby-version: '3.1' bundler: none - - uses: taiki-e/install-action@8f531eaecd1898bc3da7d104ad91bee98d1b97bd # v2.79.9 + - uses: taiki-e/install-action@13608cbb45b01feb47ef444ab1a42dc41ad56f1a # v2.79.11 with: tool: nextest@0.9 if: ${{ matrix.test_task == 'zjit-check' }} @@ -82,8 +82,8 @@ releases. * 6.0.1 to [v6.0.1.1][erb-v6.0.1.1], [v6.0.2][erb-v6.0.2], [v6.0.3][erb-v6.0.3], [v6.0.4][erb-v6.0.4] * ipaddr 1.2.9 * 1.2.8 to [v1.2.9][ipaddr-v1.2.9] -* json 2.19.5 - * 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5] +* json 2.19.7 + * 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5], [v2.19.6][json-v2.19.6] * openssl 4.0.2 * 4.0.0 to [v4.0.1][openssl-v4.0.1], [v4.0.2][openssl-v4.0.2] * prism 1.9.0 @@ -208,6 +208,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [json-v2.19.3]: https://github.com/ruby/json/releases/tag/v2.19.3 [json-v2.19.4]: https://github.com/ruby/json/releases/tag/v2.19.4 [json-v2.19.5]: https://github.com/ruby/json/releases/tag/v2.19.5 +[json-v2.19.6]: https://github.com/ruby/json/releases/tag/v2.19.6 [openssl-v4.0.1]: https://github.com/ruby/openssl/releases/tag/v4.0.1 [openssl-v4.0.2]: https://github.com/ruby/openssl/releases/tag/v4.0.2 [prism-v1.8.0]: https://github.com/ruby/prism/releases/tag/v1.8.0 diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 882d47a611..9260712c9a 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1367,12 +1367,14 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig) if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State"); MEMCPY(objState, origState, JSON_Generator_State, 1); - objState->indent = origState->indent; - objState->space = origState->space; - objState->space_before = origState->space_before; - objState->object_nl = origState->object_nl; - objState->array_nl = origState->array_nl; - objState->as_json = origState->as_json; + + RB_OBJ_WRITTEN(obj, Qundef, objState->indent); + RB_OBJ_WRITTEN(obj, Qundef, objState->space); + RB_OBJ_WRITTEN(obj, Qundef, objState->space_before); + RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl); + RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl); + RB_OBJ_WRITTEN(obj, Qundef, objState->as_json); + return obj; } @@ -1590,6 +1592,9 @@ static long depth_config(VALUE num) if (RB_UNLIKELY(d < 0)) { rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d); } + if (RB_UNLIKELY(d > INT_MAX)) { + rb_raise(rb_eArgError, "depth is too large (got %ld)", d); + } return d; } diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index ebb55656d7..a69590ff9c 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module JSON - VERSION = '2.19.5' + VERSION = '2.19.7' end diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index a740bd42ed..363f109d3a 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1202,7 +1202,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig raise_parse_error_at("invalid number: %s", state, start); } - exponent = negative_exponent ? -abs_exponent : abs_exponent; + if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) { + exponent = negative_exponent ? INT64_MIN : INT64_MAX; + } else { + exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent; + } } if (integer) { @@ -1457,18 +1461,21 @@ static void json_ensure_eof(JSON_ParserState *state) static VALUE convert_encoding(VALUE source) { - int encindex = RB_ENCODING_GET(source); + StringValue(source); + int encindex = RB_ENCODING_GET(source); - if (RB_LIKELY(encindex == utf8_encindex)) { - return source; - } + if (RB_LIKELY(encindex == utf8_encindex)) { + return source; + } - if (encindex == binary_encindex) { - // For historical reason, we silently reinterpret binary strings as UTF-8 - return rb_enc_associate_index(rb_str_dup(source), utf8_encindex); - } + if (encindex == binary_encindex) { + // For historical reason, we silently reinterpret binary strings as UTF-8 + return rb_enc_associate_index(rb_str_dup(source), utf8_encindex); + } - return rb_funcall(source, i_encode, 1, Encoding_UTF_8); + source = rb_funcall(source, i_encode, 1, Encoding_UTF_8); + StringValue(source); + return source; } struct parser_config_init_args { @@ -1583,10 +1590,16 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts) return self; } -static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) +static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src) { - Vsource = convert_encoding(StringValue(Vsource)); - StringValue(Vsource); + VALUE Vsource = convert_encoding(src); + + // Ensure the string isn't mutated under us. + // The classic API to use is `rb_str_locktmp`, but then we'd + // need to use `rb_protect` to make sure we always unlock. + if (Vsource == src) { + Vsource = rb_str_new_frozen(Vsource); + } VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; rvalue_stack stack = { @@ -1597,6 +1610,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) long len; const char *start; + RSTRING_GETMEM(Vsource, start, len); VALUE stack_handle = 0; @@ -1615,6 +1629,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) // it won't cause a leak. rvalue_stack_eagerly_release(stack_handle); RB_GC_GUARD(stack_handle); + RB_GC_GUARD(Vsource); json_ensure_eof(state); return result; @@ -1635,9 +1650,6 @@ static VALUE cParserConfig_parse(VALUE self, VALUE Vsource) static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts) { - Vsource = convert_encoding(StringValue(Vsource)); - StringValue(Vsource); - JSON_ParserConfig _config = {0}; JSON_ParserConfig *config = &_config; parser_config_init(config, opts, false); diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb index 9e21f8f1d2..852fc631f3 100644 --- a/lib/bundler/lockfile_parser.rb +++ b/lib/bundler/lockfile_parser.rb @@ -95,14 +95,14 @@ module Bundler lockfile_contents.split(BUNDLED).last.strip end - def initialize(lockfile, strict: false) + def initialize(lockfile, strict: false, lockfile_path: nil) @platforms = [] @sources = [] @metadata_source = Source::Metadata.new @dependencies = {} @parse_method = nil @specs = {} - @lockfile_path = begin + @lockfile_path = lockfile_path || begin SharedHelpers.relative_lockfile_path rescue GemfileNotFound "Gemfile.lock" diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt index 2729530e8d..1ab1c28f46 100644 --- a/lib/bundler/templates/newgem/newgem.gemspec.tt +++ b/lib/bundler/templates/newgem/newgem.gemspec.tt @@ -47,7 +47,7 @@ Gem::Specification.new do |spec| # Uncomment to register a new dependency of your gem # spec.add_dependency "example-gem", ">= 1.0" <%- if config[:ext] == 'rust' -%> - spec.add_dependency "rb_sys", ">= 0.9.127" + spec.add_dependency "rb_sys", ">= 0.9.128" <%- end -%> <%- if config[:ext] == 'go' -%> spec.add_dependency "go_gem", ">= 0.2" diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index dbebd1af0c..c06ef32da9 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -322,11 +322,8 @@ class Gem::RequestSet @git_set.root_dir = @install_dir lock_file = "#{File.expand_path(path)}.lock" - begin - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file lock_file - parser = tokenizer.make_parser self, [] - parser.parse - rescue Errno::ENOENT + if File.exist?(lock_file) + load_lockfile lock_file end gf = Gem::RequestSet::GemDependencyAPI.new self, path @@ -335,6 +332,63 @@ class Gem::RequestSet gf.load end + def load_lockfile(lock_file) # :nodoc: + require "bundler" + require "bundler/lockfile_parser" + + # Bundler::Source::Path resolves relative `remote:` paths against + # Bundler.root, which raises when there is no Gemfile in the working + # directory. Anchor it to the lockfile's directory so PATH sections in a + # `gem install -g` lockfile can be parsed without a Bundler environment. + previous_root = Bundler.instance_variable_get(:@root) + Bundler.instance_variable_set(:@root, Pathname.new(File.expand_path(File.dirname(lock_file)))) + + parser = Bundler::LockfileParser.new(File.read(lock_file), lockfile_path: lock_file) + + parser.specs.group_by(&:source).each do |source, specs| + case source + when Bundler::Source::Rubygems + remotes = source.remotes.map {|remote| Gem::Source.new(remote.to_s) } + remotes << Gem::Source.new(Gem::DEFAULT_HOST) if remotes.empty? + lock_set = Gem::Resolver::LockSet.new(remotes) + specs.each do |spec| + added = lock_set.add(spec.name, spec.version.to_s, spec.platform) + spec.dependencies.each do |dep| + added.each {|s| s.add_dependency dep } + end + end + @sets << lock_set + when Bundler::Source::Git + git_set = Gem::Resolver::GitSet.new + git_set.root_dir = @install_dir + specs.each do |spec| + git_spec = git_set.add_git_spec( + spec.name, + spec.version.to_s, + source.uri.to_s, + source.revision, + source.submodules || false + ) + spec.dependencies.each {|dep| git_spec.add_dependency dep } + end + @sets << git_set + when Bundler::Source::Path + vendor_set = Gem::Resolver::VendorSet.new + specs.each do |spec| + loaded = vendor_set.add_vendor_gem(spec.name, source.path.to_s) + spec.dependencies.each {|dep| loaded.dependencies << dep } + end + @sets << vendor_set + end + end + + parser.dependencies.each_value do |dep| + gem dep.name, *dep.requirement.as_list + end + ensure + Bundler.instance_variable_set(:@root, previous_root) if defined?(previous_root) + end + def pretty_print(q) # :nodoc: q.group 2, "[RequestSet:", "]" do q.breakable @@ -462,4 +516,3 @@ end require_relative "request_set/gem_dependency_api" require_relative "request_set/lockfile" -require_relative "request_set/lockfile/tokenizer" diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb index da6dd329bc..8b9c9690d6 100644 --- a/lib/rubygems/request_set/lockfile.rb +++ b/lib/rubygems/request_set/lockfile.rb @@ -231,5 +231,3 @@ class Gem::RequestSet::Lockfile @set.sorted_requests end end - -require_relative "lockfile/tokenizer" diff --git a/lib/rubygems/request_set/lockfile/parser.rb b/lib/rubygems/request_set/lockfile/parser.rb deleted file mode 100644 index e751a1445e..0000000000 --- a/lib/rubygems/request_set/lockfile/parser.rb +++ /dev/null @@ -1,344 +0,0 @@ -# frozen_string_literal: true - -class Gem::RequestSet::Lockfile::Parser - ### - # Parses lockfiles - - def initialize(tokenizer, set, platforms, filename = nil) - @tokens = tokenizer - @filename = filename - @set = set - @platforms = platforms - end - - def parse - until @tokens.empty? do - token = get - - case token.type - when :section then - @tokens.skip :newline - - case token.value - when "DEPENDENCIES" then - parse_DEPENDENCIES - when "GIT" then - parse_GIT - when "GEM" then - parse_GEM - when "PATH" then - parse_PATH - when "PLATFORMS" then - parse_PLATFORMS - else - token = get until @tokens.empty? || peek.first == :section - end - else - raise "BUG: unhandled token #{token.type} (#{token.value.inspect}) at line #{token.line} column #{token.column}" - end - end - end - - ## - # Gets the next token for a Lockfile - - def get(expected_types = nil, expected_value = nil) # :nodoc: - token = @tokens.shift - - if expected_types && !Array(expected_types).include?(token.type) - unget token - - message = "unexpected token [#{token.type.inspect}, #{token.value.inspect}], " \ - "expected #{expected_types.inspect}" - - raise Gem::RequestSet::Lockfile::ParseError.new message, token.column, token.line, @filename - end - - if expected_value && expected_value != token.value - unget token - - message = "unexpected token [#{token.type.inspect}, #{token.value.inspect}], " \ - "expected [#{expected_types.inspect}, " \ - "#{expected_value.inspect}]" - - raise Gem::RequestSet::Lockfile::ParseError.new message, token.column, token.line, @filename - end - - token - end - - def parse_DEPENDENCIES # :nodoc: - while !@tokens.empty? && peek.type == :text do - token = get :text - - requirements = [] - - case peek[0] - when :bang then - get :bang - - requirements << pinned_requirement(token.value) - when :l_paren then - get :l_paren - - loop do - op = get(:requirement).value - version = get(:text).value - - requirements << "#{op} #{version}" - - break unless peek.type == :comma - - get :comma - end - - get :r_paren - - if peek[0] == :bang - requirements.clear - requirements << pinned_requirement(token.value) - - get :bang - end - end - - @set.gem token.value, *requirements - - skip :newline - end - end - - def parse_GEM # :nodoc: - sources = [] - - while peek.first(2) == [:entry, "remote"] do - get :entry, "remote" - data = get(:text).value - skip :newline - - sources << Gem::Source.new(data) - end - - sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty? - - get :entry, "specs" - - skip :newline - - set = Gem::Resolver::LockSet.new sources - last_specs = nil - - while !@tokens.empty? && peek.type == :text do - token = get :text - name = token.value - column = token.column - - case peek[0] - when :newline then - last_specs.each do |spec| - spec.add_dependency Gem::Dependency.new name if column == 6 - end - when :l_paren then - get :l_paren - - token = get [:text, :requirement] - type = token.type - data = token.value - - if type == :text && column == 4 - version, platform = data.split "-", 2 - - platform = - platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY - - last_specs = set.add name, version, platform - else - dependency = parse_dependency name, data - - last_specs.each do |spec| - spec.add_dependency dependency - end - end - - get :r_paren - else - raise "BUG: unknown token #{peek}" - end - - skip :newline - end - - @set.sets << set - end - - def parse_GIT # :nodoc: - get :entry, "remote" - repository = get(:text).value - - skip :newline - - get :entry, "revision" - revision = get(:text).value - - skip :newline - - type = peek.type - value = peek.value - if type == :entry && %w[branch ref tag].include?(value) - get - get :text - - skip :newline - end - - get :entry, "specs" - - skip :newline - - set = Gem::Resolver::GitSet.new - set.root_dir = @set.install_dir - - last_spec = nil - - while !@tokens.empty? && peek.type == :text do - token = get :text - name = token.value - column = token.column - - case peek[0] - when :newline then - last_spec.add_dependency Gem::Dependency.new name if column == 6 - when :l_paren then - get :l_paren - - token = get [:text, :requirement] - type = token.type - data = token.value - - if type == :text && column == 4 - last_spec = set.add_git_spec name, data, repository, revision, true - else - dependency = parse_dependency name, data - - last_spec.add_dependency dependency - end - - get :r_paren - else - raise "BUG: unknown token #{peek}" - end - - skip :newline - end - - @set.sets << set - end - - def parse_PATH # :nodoc: - get :entry, "remote" - directory = get(:text).value - - skip :newline - - get :entry, "specs" - - skip :newline - - set = Gem::Resolver::VendorSet.new - last_spec = nil - - while !@tokens.empty? && peek.first == :text do - token = get :text - name = token.value - column = token.column - - case peek[0] - when :newline then - last_spec.add_dependency Gem::Dependency.new name if column == 6 - when :l_paren then - get :l_paren - - token = get [:text, :requirement] - type = token.type - data = token.value - - if type == :text && column == 4 - last_spec = set.add_vendor_gem name, directory - else - dependency = parse_dependency name, data - - last_spec.dependencies << dependency - end - - get :r_paren - else - raise "BUG: unknown token #{peek}" - end - - skip :newline - end - - @set.sets << set - end - - def parse_PLATFORMS # :nodoc: - while !@tokens.empty? && peek.first == :text do - name = get(:text).value - - @platforms << name - - skip :newline - end - end - - ## - # Parses the requirements following the dependency +name+ and the +op+ for - # the first token of the requirements and returns a Gem::Dependency object. - - def parse_dependency(name, op) # :nodoc: - return Gem::Dependency.new name, op unless peek[0] == :text - - version = get(:text).value - - requirements = ["#{op} #{version}"] - - while peek.type == :comma do - get :comma - op = get(:requirement).value - version = get(:text).value - - requirements << "#{op} #{version}" - end - - Gem::Dependency.new name, requirements - end - - private - - def skip(type) # :nodoc: - @tokens.skip type - end - - ## - # Peeks at the next token for Lockfile - - def peek # :nodoc: - @tokens.peek - end - - def pinned_requirement(name) # :nodoc: - requirement = Gem::Dependency.new name - specification = @set.sets.flat_map do |set| - set.find_all(requirement) - end.compact.first - - specification&.version - end - - ## - # Ungets the last token retrieved by #get - - def unget(token) # :nodoc: - @tokens.unshift token - end -end diff --git a/lib/rubygems/request_set/lockfile/tokenizer.rb b/lib/rubygems/request_set/lockfile/tokenizer.rb deleted file mode 100644 index 65cef3baa0..0000000000 --- a/lib/rubygems/request_set/lockfile/tokenizer.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: true - -# ) frozen_string_literal: true -require_relative "parser" - -class Gem::RequestSet::Lockfile::Tokenizer - Token = Struct.new :type, :value, :column, :line - EOF = Token.new :EOF - - def self.from_file(file) - new File.read(file), file - end - - def initialize(input, filename = nil, line = 0, pos = 0) - @line = line - @line_pos = pos - @tokens = [] - @filename = filename - tokenize input - end - - def make_parser(set, platforms) - Gem::RequestSet::Lockfile::Parser.new self, set, platforms, @filename - end - - def to_a - @tokens.map {|token| [token.type, token.value, token.column, token.line] } - end - - def skip(type) - @tokens.shift while !@tokens.empty? && peek.type == type - end - - ## - # Calculates the column (by byte) and the line of the current token based on - # +byte_offset+. - - def token_pos(byte_offset) # :nodoc: - [byte_offset - @line_pos, @line] - end - - def empty? - @tokens.empty? - end - - def unshift(token) - @tokens.unshift token - end - - def next_token - @tokens.shift - end - alias_method :shift, :next_token - - def peek - @tokens.first || EOF - end - - private - - def tokenize(input) - require "strscan" - s = StringScanner.new input - - until s.eos? do - pos = s.pos - - pos = s.pos if leading_whitespace = s.scan(/ +/) - - if s.scan(/[<|=>]{7}/) - message = "your #{@filename} contains merge conflict markers" - column, line = token_pos pos - - raise Gem::RequestSet::Lockfile::ParseError.new message, column, line, @filename - end - - @tokens << - if s.scan(/\r?\n/) - - token = Token.new(:newline, nil, *token_pos(pos)) - @line_pos = s.pos - @line += 1 - token - elsif s.scan(/[A-Z]+/) - - if leading_whitespace - text = s.matched - text += s.scan(/[^\s)]*/).to_s # in case of no match - Token.new(:text, text, *token_pos(pos)) - else - Token.new(:section, s.matched, *token_pos(pos)) - end - elsif s.scan(/([a-z]+):\s/) - - s.pos -= 1 # rewind for possible newline - Token.new(:entry, s[1], *token_pos(pos)) - elsif s.scan(/\(/) - - Token.new(:l_paren, nil, *token_pos(pos)) - elsif s.scan(/\)/) - - Token.new(:r_paren, nil, *token_pos(pos)) - elsif s.scan(/<=|>=|=|~>|<|>|!=/) - - Token.new(:requirement, s.matched, *token_pos(pos)) - elsif s.scan(/,/) - - Token.new(:comma, nil, *token_pos(pos)) - elsif s.scan(/!/) - - Token.new(:bang, nil, *token_pos(pos)) - elsif s.scan(/[^\s),!]*/) - - Token.new(:text, s.matched, *token_pos(pos)) - else - raise "BUG: can't create token for: #{s.string[s.pos..-1].inspect}" - end - end - - @tokens - end -end diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb index a1d5c94fc5..b2547b136b 100644 --- a/lib/rubygems/yaml_serializer.rb +++ b/lib/rubygems/yaml_serializer.rb @@ -72,9 +72,7 @@ module Gem def parse_node(base_indent) @depth += 1 - if @depth > MAX_NESTING_DEPTH - raise Psych::SyntaxError, "exceeded maximum nesting depth (#{MAX_NESTING_DEPTH})" - end + raise_max_nesting! if @depth > MAX_NESTING_DEPTH skip_blank_and_comments return nil if @lines.empty? @@ -285,7 +283,9 @@ module Gem Scalar.new(value: result) end - def coerce(val) + def coerce(val, depth = 0) + raise_max_nesting! if depth > MAX_NESTING_DEPTH + val = val.sub(/^! /, "") if val.start_with?("! ") if val =~ /^"(.*)"$/ @@ -311,7 +311,7 @@ module Gem elsif val =~ /^\[(.*)\]$/ inner = $1.strip return Sequence.new if inner.empty? - items = inner.split(/\s*,\s*/).reject(&:empty?).map {|e| Scalar.new(value: coerce(e)) } + items = inner.split(/\s*,\s*/).reject(&:empty?).map {|e| Scalar.new(value: coerce(e, depth + 1)) } Sequence.new(items: items) elsif /\A\d{4}-\d{2}-\d{2}([ T]\d{2}:\d{2}:\d{2})?/.match?(val) begin @@ -392,6 +392,15 @@ module Gem node end + def raise_max_nesting! + message = "exceeded maximum nesting depth (#{MAX_NESTING_DEPTH})" + if defined?(Psych::VERSION) + raise Psych::SyntaxError.new(nil, 0, 0, 0, message, nil) + else + raise Psych::SyntaxError, message + end + end + def skip_blank_and_comments while @lines.any? line = @lines[0] @@ -454,9 +463,7 @@ module Gem result = build_node(node) - if result.is_a?(Hash) && - (result[:tag] == "!ruby/object:Gem::Specification" || - result["tag"] == "!ruby/object:Gem::Specification") + if result.is_a?(Hash) && result[:tag] == "!ruby/object:Gem::Specification" build_specification(result) else result @@ -482,7 +489,11 @@ module Gem if @alias_count > MAX_ALIAS_RESOLUTIONS raise Psych::BadAlias, "exceeded maximum alias resolutions (#{MAX_ALIAS_RESOLUTIONS})" end - @anchor_values.fetch(node.name, nil) + unless @anchor_values.key?(node.name) + klass = defined?(Psych::AnchorNotDefined) ? Psych::AnchorNotDefined : Psych::BadAlias + raise klass, "An alias referenced an unknown anchor: #{node.name}" + end + @anchor_values.fetch(node.name) end def store_anchor(name, value) @@ -491,7 +502,6 @@ module Gem end def build_mapping(node) - check_anchor!(node) validate_tag!(node.tag) if node.tag result = case node.tag @@ -592,9 +602,14 @@ module Gem d.instance_variable_set(:@requirement, hash["requirement"] || hash["version_requirements"]) - type = hash["type"] - type = type ? type.to_s.sub(/^:/, "").to_sym : :runtime - validate_symbol!(type) + raw_type = hash["type"] + if raw_type + name = raw_type.to_s.sub(/^:/, "") + validate_symbol!(name) + type = name.to_sym + else + type = :runtime + end d.instance_variable_set(:@type, type) d.instance_variable_set(:@prerelease, ["true", true].include?(hash["prerelease"])) @@ -634,19 +649,14 @@ module Gem end end - def validate_symbol!(sym) - if @permitted_symbols.any? && !@permitted_symbols.include?(sym.to_s) - if defined?(Psych::VERSION) - raise Psych::DisallowedClass.new("load", sym.inspect) - else - raise Psych::DisallowedClass, "Tried to load unspecified class: #{sym.inspect}" - end - end - end + def validate_symbol!(name) + return if @permitted_symbols.empty? || @permitted_symbols.include?(name) - def check_anchor!(node) - if node.anchor - raise Psych::AliasesNotEnabled unless @aliases + label = ":#{name}" + if defined?(Psych::VERSION) + raise Psych::DisallowedClass.new("load", label) + else + raise Psych::DisallowedClass, "Tried to load unspecified class: #{label}" end end @@ -1242,6 +1242,7 @@ rb_marshal_dump_limited(VALUE obj, VALUE port, int limit) struct load_arg { VALUE src; char *buf; + long bufsize; long buflen; long readable; long offset; @@ -1327,15 +1328,23 @@ static unsigned char r_byte1_buffered(struct load_arg *arg) { if (arg->buflen == 0) { - long readable = arg->readable < BUFSIZ ? arg->readable : BUFSIZ; + long readable = arg->readable < arg->bufsize ? arg->readable : arg->bufsize; + long read_len; VALUE str, n = LONG2NUM(readable); str = load_funcall(arg, arg->src, s_read, 1, &n); if (NIL_P(str)) too_short(); StringValue(str); - memcpy(arg->buf, RSTRING_PTR(str), RSTRING_LEN(str)); + read_len = RSTRING_LEN(str); + if (UNLIKELY(read_len < readable)) too_short(); + if (UNLIKELY(read_len > arg->bufsize)) { + arg->buf = ruby_sized_realloc_n(arg->buf, read_len, 1, arg->bufsize); + arg->bufsize = read_len; + } + memcpy(arg->buf, RSTRING_PTR(str), read_len); arg->offset = 0; - arg->buflen = RSTRING_LEN(str); + arg->buflen = read_len; + RB_GC_GUARD(str); } arg->buflen--; return arg->buf[arg->offset++]; @@ -1422,6 +1431,18 @@ ruby_marshal_read_long(const char **buf, long len) return x; } +static long +r_keep_readable(struct load_arg *arg, long len, size_t size) +{ + if (UNLIKELY(len < 0)) { + rb_raise(rb_eArgError, "negative length"); + } + if (UNLIKELY((unsigned long)len > SIZE_MAX / size || arg->readable >= LONG_MAX - len)) { + rb_raise(rb_eArgError, "marshaled data too big"); + } + return len; +} + static VALUE r_bytes1(long len, struct load_arg *arg) { @@ -1451,7 +1472,7 @@ r_bytes1_buffered(long len, struct load_arg *arg) long tmp_len, read_len, need_len = len - buflen; VALUE tmp, n; - readable = readable < BUFSIZ ? readable : BUFSIZ; + readable = readable < arg->bufsize ? readable : arg->bufsize; read_len = need_len > readable ? need_len : readable; n = LONG2NUM(read_len); tmp = load_funcall(arg, arg->src, s_read, 1, &n); @@ -2005,7 +2026,10 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE klass, VALUE ex int sign; sign = r_byte(arg); - len = r_long(arg); + if (sign != '+' && sign != '-') { + rb_raise(rb_eArgError, "invalid Bignum sign"); + } + len = r_keep_readable(arg, r_long(arg), 2); if (SIZEOF_VALUE >= 8 && len <= 4) { // Representable within uintptr, likely FIXNUM @@ -2083,7 +2107,7 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE klass, VALUE ex case TYPE_ARRAY: { - long len = r_long(arg); + long len = r_keep_readable(arg, r_long(arg), 1); v = rb_ary_new2(len); v = r_entry(v, arg); @@ -2101,7 +2125,7 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE klass, VALUE ex case TYPE_HASH_DEF: type_hash: { - long len = r_long(arg); + long len = r_keep_readable(arg, r_long(arg), 2); v = hash_new_with_size(len); v = r_entry(v, arg); @@ -2127,7 +2151,7 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE klass, VALUE ex VALUE slot; st_index_t idx = r_prepare(arg); VALUE klass = path2class(r_unique(arg)); - long len = r_long(arg); + long len = r_keep_readable(arg, r_long(arg), 2); v = rb_obj_alloc(klass); if (!RB_TYPE_P(v, T_STRUCT)) { @@ -2344,8 +2368,9 @@ r_object(struct load_arg *arg) static void clear_load_arg(struct load_arg *arg) { - ruby_xfree_sized(arg->buf, BUFSIZ); + ruby_xfree_sized(arg->buf, arg->bufsize); arg->buf = NULL; + arg->bufsize = 0; arg->buflen = 0; arg->offset = 0; arg->readable = 0; @@ -2391,10 +2416,14 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc, bool freeze) arg->readable = 0; arg->freeze = freeze; - if (NIL_P(v)) + if (NIL_P(v)) { + arg->bufsize = BUFSIZ; arg->buf = xmalloc(BUFSIZ); - else + } + else { + arg->bufsize = 0; arg->buf = 0; + } major = r_byte(arg); minor = r_byte(arg); diff --git a/spec/bundler/bundler/lockfile_parser_spec.rb b/spec/bundler/bundler/lockfile_parser_spec.rb index 4b493a3757..7364ab98e5 100644 --- a/spec/bundler/bundler/lockfile_parser_spec.rb +++ b/spec/bundler/bundler/lockfile_parser_spec.rb @@ -252,6 +252,27 @@ RSpec.describe Bundler::LockfileParser do end end + context "when lockfile_path is given" do + it "uses the provided path in error messages instead of looking up Bundler.default_lockfile" do + expect(Bundler::SharedHelpers).not_to receive(:relative_lockfile_path) + parser = described_class.new(lockfile_contents, lockfile_path: "custom/path.lock") + expect(parser.valid?).to be(true) + rake_spec = parser.specs.last + checksums = parser.sources.last.checksum_store.to_lock(rake_spec) + expected_checksum = Bundler::Checksum.from_lock( + "sha256=814828c34f1315d7e7b7e8295184577cc4e969bad6156ac069d02d63f58d82e8", + "custom/path.lock:20:17" + ) + expect(checksums).to eq("#{rake_spec.lock_name} #{expected_checksum.to_lock}") + end + + it "raises with the provided path when the lockfile contains merge conflicts" do + expect do + described_class.new("<<<<<<<\n", lockfile_path: "custom/path.lock") + end.to raise_error(Bundler::LockfileError, %r{custom/path\.lock contains merge conflicts}) + end + end + context "when CHECKSUMS has duplicate checksums in the lockfile that don't match" do let(:bad_checksum) { "sha256=c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11c0ffee11" } let(:lockfile_contents) { super().split(/(?<=CHECKSUMS\n)/m).insert(1, " rake (10.3.2) #{bad_checksum}\n").join } diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb index 33ae503a5a..16b7f18788 100644 --- a/spec/bundler/quality_spec.rb +++ b/spec/bundler/quality_spec.rb @@ -109,7 +109,7 @@ RSpec.describe "The library itself" do it "does not include any unresolved merge conflicts" do error_messages = [] - exempt = %r{lock/lockfile_spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser\.rb} + exempt = %r{lock/lockfile_spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser} tracked_files.each do |filename| next if filename&.match?(exempt) error_messages << check_for_git_merge_conflicts(filename) diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb index 67d86a0b35..1969e79b31 100644 --- a/test/json/json_parser_test.rb +++ b/test/json/json_parser_test.rb @@ -878,6 +878,22 @@ class JSONParserTest < Test::Unit::TestCase end end + def test_mutating_source_string_during_parsing + expected = ([1] * 100) + [2.3] + ([1] * 100) + source = JSON.generate(expected) + expected.delete_at(100) + + fake_decimal_class = Class.new + fake_decimal_class.define_method(:initialize) do |number| + source.tr!('1', '0') + number.to_f + end + + actual = JSON.parse(source, decimal_class: fake_decimal_class) + actual.delete_at(100) + assert_equal expected, actual + end + private def assert_equal_float(expected, actual, delta = 1e-2) diff --git a/test/json/json_ryu_fallback_test.rb b/test/json/json_ryu_fallback_test.rb index 152de7e360..a61b3e668d 100644 --- a/test/json/json_ryu_fallback_test.rb +++ b/test/json/json_ryu_fallback_test.rb @@ -179,5 +179,13 @@ class JSONRyuFallbackTest < Test::Unit::TestCase assert_equal(-0.0, JSON.parse("-99999999999999999e-4294967296")) assert_equal(-Float::INFINITY, JSON.parse("-1e4294967295")) assert_equal(-Float::INFINITY, JSON.parse("-1e4294967297")) + + assert_equal(Float::INFINITY, JSON.parse("1e9223372036854775808")) + assert_equal(Float::INFINITY, JSON.parse("1e9999999999999999999")) + assert_equal(Float::INFINITY, JSON.parse("1e18446744073709551616")) + assert_equal(Float::INFINITY, JSON.parse("1e10000000000000000000")) + assert_equal(Float::INFINITY, JSON.parse("1e184467440737095516160")) + assert_equal 0.0, JSON.parse("1e-18446744073709551615") + assert_equal 0.0, JSON.parse("1e-9223372036854775809") end end diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index 1e4de74503..48a67e1dc5 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -933,6 +933,41 @@ class TestMarshal < Test::Unit::TestCase end end + def test_load_overread + input = Struct.new(:bytes, :used) do + def initialize + super("\x04\x08[\x07".bytes, false) + end + + def getbyte + bytes.shift + end + + def read(_len, _outbuf = nil) + return nil if used + self.used = true + "0" * (1024 * 128) + end + end.new + + assert_equal([nil, nil], Marshal.load(input)) + end + + def test_bignum_len_overflow + assert_raise(ArgumentError) do + Marshal.load("\x04\x08l+\x04\x00\x00\x00\x40") + end + assert_raise(ArgumentError) do + Marshal.load("\x04\x08l+\xfc\x00\x00\x00\x80") + end + end + + def test_bignum_invalid_sign + assert_raise(ArgumentError) do + Marshal.load("\x04\bl?") + end + end + class TestMarshalFreezeProc < Test::Unit::TestCase include MarshalTestLib diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index 989b0b0412..d6c49c3de1 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -153,18 +153,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.127" +version = "0.9.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7d7c9560fe42dcffa576941394075f18a17dce89fcf718a2fa90b7dc2134d12" +checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.127" +version = "0.9.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1688e8f32967ba48c89e4dfa283b57f901075f542fc7ee9c3d7c5f9091ca1d9" +checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml index 47e978ceb4..056567c708 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.127" +rb-sys = "0.9.128" diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index e8ee8f237c..806d51d3a1 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -146,18 +146,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.127" +version = "0.9.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7d7c9560fe42dcffa576941394075f18a17dce89fcf718a2fa90b7dc2134d12" +checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.127" +version = "0.9.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1688e8f32967ba48c89e4dfa283b57f901075f542fc7ee9c3d7c5f9091ca1d9" +checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml index 6595b6aafa..f0ddeeb91c 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.127" +rb-sys = "0.9.128" diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb index 9aa244892c..6ebc95ea20 100644 --- a/test/rubygems/test_gem_request_set.rb +++ b/test/rubygems/test_gem_request_set.rb @@ -311,6 +311,110 @@ ruby "0" assert_empty rs.dependencies end + def test_load_gemdeps_with_lockfile_gem_section + rs = Gem::RequestSet.new + + File.open "gem.deps.rb", "w" do |io| + io.puts 'gem "b"' + end + + File.open "gem.deps.rb.lock", "w" do |io| + io.puts <<~LOCKFILE + GEM + remote: #{@gem_repo} + specs: + a (1) + b (1) + a (~> 1.0) + + PLATFORMS + #{Gem::Platform::RUBY} + + DEPENDENCIES + b + LOCKFILE + end + + rs.load_gemdeps "gem.deps.rb" + + lock_set = rs.sets.find {|set| Gem::Resolver::LockSet === set } + refute_nil lock_set, "LockSet should be created from GEM section" + assert_equal %w[a-1 b-1], lock_set.specs.map(&:full_name).sort + end + + def test_load_gemdeps_with_lockfile_git_section + rs = Gem::RequestSet.new + + File.open "gem.deps.rb", "w" do |io| + io.puts 'gem "a", :git => "git://example/a.git"' + end + + File.open "gem.deps.rb.lock", "w" do |io| + io.puts <<~LOCKFILE + GIT + remote: git://example/a.git + revision: deadbeef + specs: + a (1) + + PLATFORMS + #{Gem::Platform::RUBY} + + DEPENDENCIES + a! + LOCKFILE + end + + rs.load_gemdeps "gem.deps.rb" + + git_set = rs.sets.find {|set| Gem::Resolver::GitSet === set } + refute_nil git_set, "GitSet should be created from GIT section" + assert_includes git_set.specs.keys, "a" + end + + def test_load_gemdeps_with_lockfile_path_section + _, _, directory = vendor_gem + + rs = Gem::RequestSet.new + + File.open "gem.deps.rb", "w" do |io| + io.puts "gem \"a\", :path => #{directory.inspect}" + end + + File.open "gem.deps.rb.lock", "w" do |io| + io.puts <<~LOCKFILE + PATH + remote: #{directory} + specs: + a (1) + + PLATFORMS + #{Gem::Platform::RUBY} + + DEPENDENCIES + a! + LOCKFILE + end + + rs.load_gemdeps "gem.deps.rb" + + vendor_set = rs.sets.find {|set| Gem::Resolver::VendorSet === set } + refute_nil vendor_set, "VendorSet should be created from PATH section" + assert_equal %w[a-1], vendor_set.specs.values.map(&:full_name) + end + + def test_load_gemdeps_with_missing_lockfile + rs = Gem::RequestSet.new + + File.open "gem.deps.rb", "w" do |io| + io.puts 'gem "a"' + end + + rs.load_gemdeps "gem.deps.rb" + + assert_equal [dep("a")], rs.dependencies + end + def test_resolve a = util_spec "a", "2", "b" => ">= 2" b = util_spec "b", "2" diff --git a/test/rubygems/test_gem_request_set_lockfile_parser.rb b/test/rubygems/test_gem_request_set_lockfile_parser.rb deleted file mode 100644 index 253a59b243..0000000000 --- a/test/rubygems/test_gem_request_set_lockfile_parser.rb +++ /dev/null @@ -1,544 +0,0 @@ -# frozen_string_literal: true - -require_relative "helper" -require "rubygems/request_set" -require "rubygems/request_set/lockfile" -require "rubygems/request_set/lockfile/tokenizer" -require "rubygems/request_set/lockfile/parser" - -class TestGemRequestSetLockfileParser < Gem::TestCase - def setup - super - @gem_deps_file = "gem.deps.rb" - @lock_file = File.expand_path "#{@gem_deps_file}.lock" - @set = Gem::RequestSet.new - end - - def test_get - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n" - parser = tokenizer.make_parser nil, nil - - assert_equal :newline, parser.get.first - end - - def test_get_type_mismatch - filename = File.expand_path("#{@gem_deps_file}.lock") - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "foo", filename, 1, 0 - parser = tokenizer.make_parser nil, nil - - e = assert_raise Gem::RequestSet::Lockfile::ParseError do - parser.get :section - end - - expected = - 'unexpected token [:text, "foo"], expected :section (at line 1 column 0)' - - assert_equal expected, e.message - - assert_equal 1, e.line - assert_equal 0, e.column - assert_equal filename, e.path - end - - def test_get_type_multiple - filename = File.expand_path("#{@gem_deps_file}.lock") - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "x", filename, 1 - parser = tokenizer.make_parser nil, nil - - assert parser.get [:text, :section] - end - - def test_get_type_value_mismatch - filename = File.expand_path("#{@gem_deps_file}.lock") - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "x", filename, 1 - parser = tokenizer.make_parser nil, nil - - e = assert_raise Gem::RequestSet::Lockfile::ParseError do - parser.get :text, "y" - end - - expected = - 'unexpected token [:text, "x"], expected [:text, "y"] (at line 1 column 0)' - - assert_equal expected, e.message - - assert_equal 1, e.line - assert_equal 0, e.column - assert_equal File.expand_path("#{@gem_deps_file}.lock"), e.path - end - - def test_parse - write_lockfile <<-LOCKFILE.strip -GEM - remote: #{@gem_repo} - specs: - a (2) - -PLATFORMS - #{Gem::Platform::RUBY} - -DEPENDENCIES - a - LOCKFILE - - platforms = [] - parse_lockfile @set, platforms - - assert_equal [dep("a")], @set.dependencies - - assert_equal [Gem::Platform::RUBY], platforms - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - assert lockfile_set, "could not find a LockSet" - - assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) - end - - def test_parse_dependencies - write_lockfile <<-LOCKFILE -GEM - remote: #{@gem_repo} - specs: - a (2) - -PLATFORMS - #{Gem::Platform::RUBY} - -DEPENDENCIES - a (>= 1, <= 2) - LOCKFILE - - platforms = [] - parse_lockfile @set, platforms - - assert_equal [dep("a", ">= 1", "<= 2")], @set.dependencies - - assert_equal [Gem::Platform::RUBY], platforms - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - assert lockfile_set, "could not find a LockSet" - - assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) - end - - def test_parse_DEPENDENCIES_git - write_lockfile <<-LOCKFILE -GIT - remote: git://git.example/josevalim/rails-footnotes.git - revision: 3a6ac1971e91d822f057650cc5916ebfcbd6ee37 - specs: - rails-footnotes (3.7.9) - rails (>= 3.0.0) - -GIT - remote: git://git.example/svenfuchs/i18n-active_record.git - revision: 55507cf59f8f2173d38e07e18df0e90d25b1f0f6 - specs: - i18n-active_record (0.0.2) - i18n (>= 0.5.0) - -GEM - remote: http://gems.example/ - specs: - i18n (0.6.9) - rails (4.0.0) - -PLATFORMS - ruby - -DEPENDENCIES - i18n-active_record! - rails-footnotes! - LOCKFILE - - parse_lockfile @set, [] - - expected = [ - dep("i18n-active_record", "= 0.0.2"), - dep("rails-footnotes", "= 3.7.9"), - ] - - assert_equal expected, @set.dependencies - end - - def test_parse_DEPENDENCIES_git_version - write_lockfile <<-LOCKFILE -GIT - remote: git://github.com/progrium/ruby-jwt.git - revision: 8d74770c6cd92ea234b428b5d0c1f18306a4f41c - specs: - jwt (1.1) - -GEM - remote: http://gems.example/ - specs: - -PLATFORMS - ruby - -DEPENDENCIES - jwt (= 1.1)! - LOCKFILE - - parse_lockfile @set, [] - - expected = [ - dep("jwt", "= 1.1"), - ] - - assert_equal expected, @set.dependencies - end - - def test_parse_GEM - write_lockfile <<-LOCKFILE -GEM - specs: - a (2) - -PLATFORMS - ruby - -DEPENDENCIES - a - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", ">= 0")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - assert lockfile_set, "found a LockSet" - - assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) - end - - def test_parse_GEM_remote_multiple - write_lockfile <<-LOCKFILE -GEM - remote: https://gems.example/ - remote: https://other.example/ - specs: - a (2) - -PLATFORMS - ruby - -DEPENDENCIES - a - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", ">= 0")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - assert lockfile_set, "found a LockSet" - - assert_equal %w[a-2], lockfile_set.specs.map(&:full_name) - - assert_equal %w[https://gems.example/ https://other.example/], - lockfile_set.specs.flat_map {|s| s.sources.map {|src| src.uri.to_s } } - end - - def test_parse_GIT - @set.instance_variable_set :@install_dir, "install_dir" - - write_lockfile <<-LOCKFILE -GIT - remote: git://example/a.git - revision: abranch - specs: - a (2) - b (>= 3) - c - -DEPENDENCIES - a! - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", "= 2")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - refute lockfile_set, "found a LockSet" - - git_set = @set.sets.find do |set| - Gem::Resolver::GitSet === set - end - - assert git_set, "could not find a GitSet" - - assert_equal %w[a-2], git_set.specs.values.map(&:full_name) - - assert_equal [dep("b", ">= 3"), dep("c")], - git_set.specs.values.first.dependencies - - expected = { - "a" => %w[git://example/a.git abranch], - } - - assert_equal expected, git_set.repositories - assert_equal "install_dir", git_set.root_dir - end - - def test_parse_GIT_branch - write_lockfile <<-LOCKFILE -GIT - remote: git://example/a.git - revision: 1234abc - branch: 0-9-12-stable - specs: - a (2) - b (>= 3) - -DEPENDENCIES - a! - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", "= 2")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - refute lockfile_set, "found a LockSet" - - git_set = @set.sets.find do |set| - Gem::Resolver::GitSet === set - end - - assert git_set, "could not find a GitSet" - - expected = { - "a" => %w[git://example/a.git 1234abc], - } - - assert_equal expected, git_set.repositories - end - - def test_parse_GIT_ref - write_lockfile <<-LOCKFILE -GIT - remote: git://example/a.git - revision: 1234abc - ref: 1234abc - specs: - a (2) - b (>= 3) - -DEPENDENCIES - a! - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", "= 2")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - refute lockfile_set, "found a LockSet" - - git_set = @set.sets.find do |set| - Gem::Resolver::GitSet === set - end - - assert git_set, "could not find a GitSet" - - expected = { - "a" => %w[git://example/a.git 1234abc], - } - - assert_equal expected, git_set.repositories - end - - def test_parse_GIT_tag - write_lockfile <<-LOCKFILE -GIT - remote: git://example/a.git - revision: 1234abc - tag: v0.9.12 - specs: - a (2) - b (>= 3) - -DEPENDENCIES - a! - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", "= 2")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - refute lockfile_set, "found a LockSet" - - git_set = @set.sets.find do |set| - Gem::Resolver::GitSet === set - end - - assert git_set, "could not find a GitSet" - - expected = { - "a" => %w[git://example/a.git 1234abc], - } - - assert_equal expected, git_set.repositories - end - - def test_parse_PATH - _, _, directory = vendor_gem - - write_lockfile <<-LOCKFILE -PATH - remote: #{directory} - specs: - a (1) - b (2) - -DEPENDENCIES - a! - LOCKFILE - - parse_lockfile @set, [] - - assert_equal [dep("a", "= 1")], @set.dependencies - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - refute lockfile_set, "found a LockSet" - - vendor_set = @set.sets.find do |set| - Gem::Resolver::VendorSet === set - end - - assert vendor_set, "could not find a VendorSet" - - assert_equal %w[a-1], vendor_set.specs.values.map(&:full_name) - - spec = vendor_set.load_spec "a", nil, nil, nil - - assert_equal [dep("b", "= 2")], spec.dependencies - end - - def test_parse_dependency - write_lockfile " 1)" - - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file - parser = tokenizer.make_parser nil, nil - - parsed = parser.parse_dependency "a", "=" - - assert_equal dep("a", "= 1"), parsed - - write_lockfile ")" - - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file - parser = tokenizer.make_parser nil, nil - - parsed = parser.parse_dependency "a", "2" - - assert_equal dep("a", "= 2"), parsed - end - - def test_parse_gem_specs_dependency - write_lockfile <<-LOCKFILE -GEM - remote: #{@gem_repo} - specs: - a (2) - b (= 3) - c (~> 4) - d - e (~> 5.0, >= 5.0.1) - b (3-x86_64-linux) - -PLATFORMS - #{Gem::Platform::RUBY} - -DEPENDENCIES - a - LOCKFILE - - platforms = [] - parse_lockfile @set, platforms - - assert_equal [dep("a")], @set.dependencies - - assert_equal [Gem::Platform::RUBY], platforms - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - assert lockfile_set, "could not find a LockSet" - - assert_equal %w[a-2 b-3], lockfile_set.specs.map(&:full_name) - - expected = [ - Gem::Platform::RUBY, - Gem::Platform.new("x86_64-linux"), - ] - - assert_equal expected, lockfile_set.specs.map(&:platform) - - spec = lockfile_set.specs.first - - expected = [ - dep("b", "= 3"), - dep("c", "~> 4"), - dep("d"), - dep("e", "~> 5.0", ">= 5.0.1"), - ] - - assert_equal expected, spec.dependencies - end - - def test_parse_missing - assert_raise(Errno::ENOENT) do - parse_lockfile @set, [] - end - - lockfile_set = @set.sets.find do |set| - Gem::Resolver::LockSet === set - end - - refute lockfile_set - end - - def write_lockfile(lockfile) - File.open @lock_file, "w" do |io| - io.write lockfile - end - end - - def parse_lockfile(set, platforms) - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file - parser = tokenizer.make_parser set, platforms - parser.parse - end -end diff --git a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb deleted file mode 100644 index dce8c9ada5..0000000000 --- a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +++ /dev/null @@ -1,307 +0,0 @@ -# frozen_string_literal: true - -require_relative "helper" -require "rubygems/request_set" -require "rubygems/request_set/lockfile" -require "rubygems/request_set/lockfile/tokenizer" -require "rubygems/request_set/lockfile/parser" - -class TestGemRequestSetLockfileTokenizer < Gem::TestCase - def setup - super - - @gem_deps_file = "gem.deps.rb" - @lock_file = File.expand_path "#{@gem_deps_file}.lock" - end - - def test_peek - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n" - - assert_equal :newline, tokenizer.peek.first - - assert_equal :newline, tokenizer.next_token.first - - assert_equal :EOF, tokenizer.peek.first - end - - def test_skip - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n" - - refute_predicate tokenizer, :empty? - - tokenizer.skip :newline - - assert_empty tokenizer - end - - def test_token_pos - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "" - assert_equal [5, 0], tokenizer.token_pos(5) - - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "", nil, 1, 2 - assert_equal [3, 1], tokenizer.token_pos(5) - end - - def test_tokenize - write_lockfile <<-LOCKFILE -GEM - remote: #{@gem_repo} - specs: - a (2) - b (= 2) - c (!= 3) - d (> 4) - e (< 5) - f (>= 6) - g (<= 7) - h (~> 8) - -PLATFORMS - #{Gem::Platform::RUBY} - -DEPENDENCIES - a - LOCKFILE - - expected = [ - [:section, "GEM", 0, 0], - [:newline, nil, 3, 0], - - [:entry, "remote", 2, 1], - [:text, @gem_repo, 10, 1], - [:newline, nil, 34, 1], - - [:entry, "specs", 2, 2], - [:newline, nil, 8, 2], - - [:text, "a", 4, 3], - [:l_paren, nil, 6, 3], - [:text, "2", 7, 3], - [:r_paren, nil, 8, 3], - [:newline, nil, 9, 3], - - [:text, "b", 6, 4], - [:l_paren, nil, 8, 4], - [:requirement, "=", 9, 4], - [:text, "2", 11, 4], - [:r_paren, nil, 12, 4], - [:newline, nil, 13, 4], - - [:text, "c", 6, 5], - [:l_paren, nil, 8, 5], - [:requirement, "!=", 9, 5], - [:text, "3", 12, 5], - [:r_paren, nil, 13, 5], - [:newline, nil, 14, 5], - - [:text, "d", 6, 6], - [:l_paren, nil, 8, 6], - [:requirement, ">", 9, 6], - [:text, "4", 11, 6], - [:r_paren, nil, 12, 6], - [:newline, nil, 13, 6], - - [:text, "e", 6, 7], - [:l_paren, nil, 8, 7], - [:requirement, "<", 9, 7], - [:text, "5", 11, 7], - [:r_paren, nil, 12, 7], - [:newline, nil, 13, 7], - - [:text, "f", 6, 8], - [:l_paren, nil, 8, 8], - [:requirement, ">=", 9, 8], - [:text, "6", 12, 8], - [:r_paren, nil, 13, 8], - [:newline, nil, 14, 8], - - [:text, "g", 6, 9], - [:l_paren, nil, 8, 9], - [:requirement, "<=", 9, 9], - [:text, "7", 12, 9], - [:r_paren, nil, 13, 9], - [:newline, nil, 14, 9], - - [:text, "h", 6, 10], - [:l_paren, nil, 8, 10], - [:requirement, "~>", 9, 10], - [:text, "8", 12, 10], - [:r_paren, nil, 13, 10], - [:newline, nil, 14, 10], - - [:newline, nil, 0, 11], - - [:section, "PLATFORMS", 0, 12], - [:newline, nil, 9, 12], - - [:text, Gem::Platform::RUBY, 2, 13], - [:newline, nil, 6, 13], - - [:newline, nil, 0, 14], - - [:section, "DEPENDENCIES", 0, 15], - [:newline, nil, 12, 15], - - [:text, "a", 2, 16], - [:newline, nil, 3, 16], - ] - - assert_equal expected, tokenize_lockfile - end - - def test_tokenize_capitals - write_lockfile <<-LOCKFILE -GEM - remote: #{@gem_repo} - specs: - Ab (2) - -PLATFORMS - #{Gem::Platform::RUBY} - -DEPENDENCIES - Ab - LOCKFILE - - expected = [ - [:section, "GEM", 0, 0], - [:newline, nil, 3, 0], - [:entry, "remote", 2, 1], - [:text, @gem_repo, 10, 1], - [:newline, nil, 34, 1], - [:entry, "specs", 2, 2], - [:newline, nil, 8, 2], - [:text, "Ab", 4, 3], - [:l_paren, nil, 7, 3], - [:text, "2", 8, 3], - [:r_paren, nil, 9, 3], - [:newline, nil, 10, 3], - [:newline, nil, 0, 4], - [:section, "PLATFORMS", 0, 5], - [:newline, nil, 9, 5], - [:text, Gem::Platform::RUBY, 2, 6], - [:newline, nil, 6, 6], - [:newline, nil, 0, 7], - [:section, "DEPENDENCIES", 0, 8], - [:newline, nil, 12, 8], - [:text, "Ab", 2, 9], - [:newline, nil, 4, 9], - ] - - assert_equal expected, tokenize_lockfile - end - - def test_tokenize_conflict_markers - write_lockfile "<<<<<<<" - - e = assert_raise Gem::RequestSet::Lockfile::ParseError do - tokenize_lockfile - end - - assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", - e.message - - write_lockfile "|||||||" - - e = assert_raise Gem::RequestSet::Lockfile::ParseError do - tokenize_lockfile - end - - assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", - e.message - - write_lockfile "=======" - - e = assert_raise Gem::RequestSet::Lockfile::ParseError do - tokenize_lockfile - end - - assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", - e.message - - write_lockfile ">>>>>>>" - - e = assert_raise Gem::RequestSet::Lockfile::ParseError do - tokenize_lockfile - end - - assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)", - e.message - end - - def test_tokenize_git - write_lockfile <<-LOCKFILE -DEPENDENCIES - a! - LOCKFILE - - expected = [ - [:section, "DEPENDENCIES", 0, 0], - [:newline, nil, 12, 0], - - [:text, "a", 2, 1], - [:bang, nil, 3, 1], - [:newline, nil, 4, 1], - ] - - assert_equal expected, tokenize_lockfile - end - - def test_tokenize_multiple - write_lockfile <<-LOCKFILE -GEM - remote: #{@gem_repo} - specs: - a (2) - b (~> 3.0, >= 3.0.1) - LOCKFILE - - expected = [ - [:section, "GEM", 0, 0], - [:newline, nil, 3, 0], - - [:entry, "remote", 2, 1], - [:text, @gem_repo, 10, 1], - [:newline, nil, 34, 1], - - [:entry, "specs", 2, 2], - [:newline, nil, 8, 2], - - [:text, "a", 4, 3], - [:l_paren, nil, 6, 3], - [:text, "2", 7, 3], - [:r_paren, nil, 8, 3], - [:newline, nil, 9, 3], - - [:text, "b", 6, 4], - [:l_paren, nil, 8, 4], - [:requirement, "~>", 9, 4], - [:text, "3.0", 12, 4], - [:comma, nil, 15, 4], - [:requirement, ">=", 17, 4], - [:text, "3.0.1", 20, 4], - [:r_paren, nil, 25, 4], - [:newline, nil, 26, 4], - ] - - assert_equal expected, tokenize_lockfile - end - - def test_unget - tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "\n" - tokenizer.unshift :token - parser = tokenizer.make_parser nil, nil - - assert_equal :token, parser.get - end - - def write_lockfile(lockfile) - File.open @lock_file, "w" do |io| - io.write lockfile - end - end - - def tokenize_lockfile - Gem::RequestSet::Lockfile::Tokenizer.from_file(@lock_file).to_a - end -end diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb index d6fef1d7de..8d0ac63c41 100644 --- a/test/rubygems/test_gem_safe_yaml.rb +++ b/test/rubygems/test_gem_safe_yaml.rb @@ -70,6 +70,19 @@ class TestGemSafeYAML < Gem::TestCase assert_match(/unspecified class/, exception.message) end + def test_plain_tag_key_does_not_construct_specification + yaml = <<~YAML + tag: "!ruby/object:Gem::Specification" + name: pwned + arbitrary_ivar: hello + YAML + + result = Gem::SafeYAML.safe_load(yaml) + assert_kind_of Hash, result + assert_equal "!ruby/object:Gem::Specification", result["tag"] + assert_equal "pwned", result["name"] + end + def test_disallowed_symbol_rejected yaml = <<~YAML --- !ruby/object:Gem::Dependency @@ -94,6 +107,66 @@ class TestGemSafeYAML < Gem::TestCase assert_match(/unspecified class/, exception.message) end + def test_disallowed_symbol_not_interned + unique = "rejected_symbol_#{rand(1 << 30)}" + yaml = <<~YAML + --- !ruby/object:Gem::Dependency + name: test + requirement: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 0 + type: :#{unique} + prerelease: false + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 0 + YAML + + assert_raise(Psych::DisallowedClass) do + Gem::YAMLSerializer.load(yaml, + permitted_classes: Gem::SafeYAML::PERMITTED_CLASSES, + permitted_symbols: Gem::SafeYAML::PERMITTED_SYMBOLS) + end + refute_includes Symbol.all_symbols.map(&:to_s), unique + end + + def test_inline_array_nesting_capped + depth = Gem::YAMLSerializer::Parser::MAX_NESTING_DEPTH + 1 + yaml = "x: " + ("[" * depth) + "a" + ("]" * depth) + "\n" + + expected = [Psych::SyntaxError] + # JRuby's JVM stack overflows before the Ruby-level nesting cap fires. + expected << ::Java::JavaLang::StackOverflowError if RUBY_ENGINE == "jruby" + + assert_raise(*expected) do + Gem::YAMLSerializer.load(yaml, permitted_classes: []) + end + end + + def test_unknown_alias_raises + yaml = <<~YAML + foo: 1 + bar: *missing + YAML + + expected_error = defined?(Psych::AnchorNotDefined) ? Psych::AnchorNotDefined : Psych::BadAlias + assert_raise(expected_error) { Gem::SafeYAML.safe_load(yaml) } + end + + def test_unused_anchor_with_aliases_disabled_is_allowed + aliases_enabled = Gem::SafeYAML.aliases_enabled? + Gem::SafeYAML.aliases_enabled = false + + result = Gem::SafeYAML.safe_load("foo: &unused 1\nbar: 2\n") + assert_equal({ "foo" => 1, "bar" => 2 }, result) + ensure + Gem::SafeYAML.aliases_enabled = aliases_enabled + end + def test_yaml_serializer_aliases_disabled aliases_enabled = Gem::SafeYAML.aliases_enabled? Gem::SafeYAML.aliases_enabled = false diff --git a/tool/bundler/dev_gems.rb b/tool/bundler/dev_gems.rb index bb1e64742c..c8e4d5345c 100644 --- a/tool/bundler/dev_gems.rb +++ b/tool/bundler/dev_gems.rb @@ -5,7 +5,7 @@ source "https://rubygems.org" gem "test-unit", "~> 3.0" gem "test-unit-ruby-core" gem "rake", "~> 13.1" -gem "rb_sys", ">= 0.9.127" +gem "rb_sys", ">= 0.9.128" gem "turbo_tests", "~> 2.2.3" gem "parallel_tests", "~> 4.10.1" diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock index 49c43fe84a..ee91c8baff 100644 --- a/tool/bundler/dev_gems.rb.lock +++ b/tool/bundler/dev_gems.rb.lock @@ -35,7 +35,7 @@ GEM racc (1.8.1-java) rake (13.4.2) rake-compiler-dock (1.12.0) - rb_sys (0.9.127) + rb_sys (0.9.128) rake-compiler-dock (= 1.12.0) rexml (3.4.4) ronn-ng (0.10.1) @@ -90,7 +90,7 @@ DEPENDENCIES parallel (~> 1.19) parallel_tests (~> 4.10.1) rake (~> 13.1) - rb_sys (>= 0.9.127) + rb_sys (>= 0.9.128) ronn-ng (~> 0.10.1) rspec-core (~> 3.12) rspec-expectations (~> 3.12) @@ -124,7 +124,7 @@ CHECKSUMS racc (1.8.1-java) sha256=54f2e6d1e1b91c154013277d986f52a90e5ececbe91465d29172e49342732b98 rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701 rake-compiler-dock (1.12.0) sha256=f13205c2738f3d2053afcd03491a9e4541b22a59a0bfc53fc8bc883bd8188023 - rb_sys (0.9.127) sha256=e9f90df3bb0577472d26d96127d5b5774b98f44de881e7d36aeefd28d6337847 + rb_sys (0.9.128) sha256=9ab81f4d6d4e1895de18762232362d1264475aa7035756b50441e442130538fd rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142 ronn-ng (0.10.1) sha256=4eeb0185c0fbfa889efed923b5b50e949cd869e7d82ac74138acd0c9c7165ec0 rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587 diff --git a/tool/bundler/rubocop_gems.rb b/tool/bundler/rubocop_gems.rb index 4608228ced..c71b862318 100644 --- a/tool/bundler/rubocop_gems.rb +++ b/tool/bundler/rubocop_gems.rb @@ -10,4 +10,4 @@ gem "rake" gem "rake-compiler" gem "rspec" gem "test-unit" -gem "rb_sys", ">= 0.9.127" +gem "rb_sys", ">= 0.9.128" diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock index 170c636cc7..f265e7c9eb 100644 --- a/tool/bundler/rubocop_gems.rb.lock +++ b/tool/bundler/rubocop_gems.rb.lock @@ -42,7 +42,7 @@ GEM rake-compiler (1.3.1) rake rake-compiler-dock (1.12.0) - rb_sys (0.9.127) + rb_sys (0.9.128) rake-compiler-dock (= 1.12.0) rdoc (7.2.0) erb @@ -103,7 +103,7 @@ DEPENDENCIES minitest (~> 5.1) rake rake-compiler - rb_sys (>= 0.9.127) + rb_sys (>= 0.9.128) rspec rubocop (>= 1.52.1, < 2) test-unit @@ -138,7 +138,7 @@ CHECKSUMS rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701 rake-compiler (1.3.1) sha256=6b351612b6e2d73ddd5563ee799bb58685176e05363db6758504bd11573d670a rake-compiler-dock (1.12.0) sha256=f13205c2738f3d2053afcd03491a9e4541b22a59a0bfc53fc8bc883bd8188023 - rb_sys (0.9.127) sha256=e9f90df3bb0577472d26d96127d5b5774b98f44de881e7d36aeefd28d6337847 + rb_sys (0.9.128) sha256=9ab81f4d6d4e1895de18762232362d1264475aa7035756b50441e442130538fd rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192 regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 diff --git a/tool/bundler/standard_gems.rb b/tool/bundler/standard_gems.rb index 86abf1375f..84028a385d 100644 --- a/tool/bundler/standard_gems.rb +++ b/tool/bundler/standard_gems.rb @@ -10,4 +10,4 @@ gem "rake" gem "rake-compiler" gem "rspec" gem "test-unit" -gem "rb_sys", ">= 0.9.127" +gem "rb_sys", ">= 0.9.128" diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock index 1f3d22f86e..8ef7806bcc 100644 --- a/tool/bundler/standard_gems.rb.lock +++ b/tool/bundler/standard_gems.rb.lock @@ -42,7 +42,7 @@ GEM rake-compiler (1.3.1) rake rake-compiler-dock (1.12.0) - rb_sys (0.9.127) + rb_sys (0.9.128) rake-compiler-dock (= 1.12.0) rdoc (7.2.0) erb @@ -119,7 +119,7 @@ DEPENDENCIES minitest (~> 5.1) rake rake-compiler - rb_sys (>= 0.9.127) + rb_sys (>= 0.9.128) rspec standard (~> 1.0) test-unit @@ -154,7 +154,7 @@ CHECKSUMS rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701 rake-compiler (1.3.1) sha256=6b351612b6e2d73ddd5563ee799bb58685176e05363db6758504bd11573d670a rake-compiler-dock (1.12.0) sha256=f13205c2738f3d2053afcd03491a9e4541b22a59a0bfc53fc8bc883bd8188023 - rb_sys (0.9.127) sha256=e9f90df3bb0577472d26d96127d5b5774b98f44de881e7d36aeefd28d6337847 + rb_sys (0.9.128) sha256=9ab81f4d6d4e1895de18762232362d1264475aa7035756b50441e442130538fd rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192 regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 diff --git a/tool/bundler/test_gems.rb b/tool/bundler/test_gems.rb index fc3ccf4f56..384ff85d1f 100644 --- a/tool/bundler/test_gems.rb +++ b/tool/bundler/test_gems.rb @@ -8,7 +8,7 @@ gem "compact_index", "~> 0.15.0" gem "sinatra", "~> 4.1" gem "rake", "~> 13.1" gem "builder", "~> 3.2" -gem "rb_sys", ">= 0.9.127" +gem "rb_sys", ">= 0.9.128" gem "fiddle" gem "rubygems-generate_index", "~> 1.1" gem "concurrent-ruby" diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock index bb5dcbb581..a8352f3070 100644 --- a/tool/bundler/test_gems.rb.lock +++ b/tool/bundler/test_gems.rb.lock @@ -31,7 +31,7 @@ GEM rack (>= 1.3) rake (13.4.2) rake-compiler-dock (1.12.0) - rb_sys (0.9.127) + rb_sys (0.9.128) rake-compiler-dock (= 1.12.0) rubygems-generate_index (1.1.3) compact_index (~> 0.15.0) @@ -66,7 +66,7 @@ DEPENDENCIES rack (~> 3.1) rack-test (~> 2.1) rake (~> 13.1) - rb_sys (>= 0.9.127) + rb_sys (>= 0.9.128) rubygems-generate_index (~> 1.1) shellwords sinatra (~> 4.1) @@ -92,7 +92,7 @@ CHECKSUMS rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463 rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701 rake-compiler-dock (1.12.0) sha256=f13205c2738f3d2053afcd03491a9e4541b22a59a0bfc53fc8bc883bd8188023 - rb_sys (0.9.127) sha256=e9f90df3bb0577472d26d96127d5b5774b98f44de881e7d36aeefd28d6337847 + rb_sys (0.9.128) sha256=9ab81f4d6d4e1895de18762232362d1264475aa7035756b50441e442130538fd rubygems-generate_index (1.1.3) sha256=3571424322666598e9586a906485e1543b617f87644913eaf137d986a3393f5c shellwords (0.2.2) sha256=b8695a791de2f71472de5abdc3f4332f6535a4177f55d8f99e7e44266cd32f94 sinatra (4.2.1) sha256=b7aeb9b11d046b552972ade834f1f9be98b185fa8444480688e3627625377080 diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index ddd164425d..86078f4ac8 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -4147,7 +4147,6 @@ impl Function { if let Some(replacement) = (props.inline)(self, tmp_block, recv, &args, state) { // Copy contents of tmp_block to block assert_ne!(block, tmp_block); - emit_super_call_guards(self, block, super_cme, current_cme, mid, state); let insns = std::mem::take(&mut self.blocks[tmp_block.0].insns); self.blocks[block.0].insns.extend(insns); self.count(block, Counter::inline_cfunc_optimized_send_count); diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index 2c992a8725..74c0af710e 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -10010,11 +10010,6 @@ mod hir_opt_tests { v20:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v19, Value(VALUE(0x1040)) v21:RubyValue = LoadField v18, :VM_ENV_DATA_INDEX_SPECVAL@0x1048 v22:FalseClass = GuardBitEquals v21, Value(false) - v30:CPtr = GetEP 0 - v31:RubyValue = LoadField v30, :VM_ENV_DATA_INDEX_ME_CREF@0x1038 - v32:CallableMethodEntry[VALUE(0x1040)] = GuardBitEquals v31, Value(VALUE(0x1040)) - v33:RubyValue = LoadField v30, :VM_ENV_DATA_INDEX_SPECVAL@0x1048 - v34:FalseClass = GuardBitEquals v33, Value(false) v23:Array = GuardType v6, Array v24:CUInt64 = LoadField v23, :RBASIC_FLAGS@0x1049 v25:CUInt64 = GuardNoBitsSet v24, RUBY_FL_FREEZE=CUInt64(2048) @@ -10054,11 +10049,6 @@ mod hir_opt_tests { v25:CallableMethodEntry[VALUE(0x1048)] = GuardBitEquals v24, Value(VALUE(0x1048)) v26:RubyValue = LoadField v23, :VM_ENV_DATA_INDEX_SPECVAL@0x1050 v27:FalseClass = GuardBitEquals v26, Value(false) - v38:CPtr = GetEP 0 - v39:RubyValue = LoadField v38, :VM_ENV_DATA_INDEX_ME_CREF@0x1040 - v40:CallableMethodEntry[VALUE(0x1048)] = GuardBitEquals v39, Value(VALUE(0x1048)) - v41:RubyValue = LoadField v38, :VM_ENV_DATA_INDEX_SPECVAL@0x1050 - v42:FalseClass = GuardBitEquals v41, Value(false) v28:Array = GuardType v9, Array v29:Fixnum = GuardType v10, Fixnum v30:CInt64 = UnboxFixnum v29 |
