-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsafe_marshal.rb
74 lines (62 loc) · 1.92 KB
/
safe_marshal.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 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