ruby/lib/rubygems/safe_marshal.rb

75 строки
1.9 KiB
Ruby

# frozen_string_literal: true
require "stringio"
require_relative "safe_marshal/reader"
require_relative "safe_marshal/visitors/to_ruby"
module Gem
###
# This module is used for safely loading Marshal specs from a gem. The
# `safe_load` method defined on this module is specifically designed for
# loading Gem specifications.
module SafeMarshal
PERMITTED_CLASSES = %w[
Date
Time
Rational
Gem::Dependency
Gem::NameTuple
Gem::Platform
Gem::Requirement
Gem::Specification
Gem::Version
Gem::Version::Requirement
YAML::Syck::DefaultKey
YAML::PrivateType
].freeze
private_constant :PERMITTED_CLASSES
PERMITTED_SYMBOLS = %w[
development
runtime
name
number
platform
dependencies
].freeze
private_constant :PERMITTED_SYMBOLS
PERMITTED_IVARS = {
"String" => %w[E encoding @taguri @debug_created_info],
"Time" => %w[
offset zone nano_num nano_den submicro
@_zone @marshal_with_utc_coercion
],
"Gem::Dependency" => %w[
@name @requirement @prerelease @version_requirement @version_requirements @type
@force_ruby_platform
],
"Gem::NameTuple" => %w[@name @version @platform],
"Gem::Platform" => %w[@os @cpu @version],
"Psych::PrivateType" => %w[@value @type_id],
}.freeze
private_constant :PERMITTED_IVARS
def self.safe_load(input)
load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS, permitted_ivars: PERMITTED_IVARS)
end
def self.load(input, permitted_classes: [::Symbol], permitted_symbols: [], permitted_ivars: {})
root = Reader.new(StringIO.new(input, "r").binmode).read!
Visitors::ToRuby.new(
permitted_classes: permitted_classes,
permitted_symbols: permitted_symbols,
permitted_ivars: permitted_ivars,
).visit(root)
end
end
end