summaryrefslogtreecommitdiff
path: root/lib/rubygems/safe_marshal.rb
blob: 172b92d5a684c5732a510960e9e72acac67f84e7 (plain)
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
# frozen_string_literal: true

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[
      Time
      Date

      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[
      E

      offset
      zone
      nano_num
      nano_den
      submicro

      @_zone
      @cpu
      @force_ruby_platform
      @marshal_with_utc_coercion
      @name
      @os
      @platform
      @prerelease
      @requirement
      @taguri
      @type
      @type_id
      @value
      @version
      @version_requirement
      @version_requirements

      development
      runtime
    ].freeze
    private_constant :PERMITTED_SYMBOLS

    def self.safe_load(input)
      load(input, permitted_classes: PERMITTED_CLASSES, permitted_symbols: PERMITTED_SYMBOLS)
    end

    def self.load(input, permitted_classes: [::Symbol], permitted_symbols: [])
      root = Reader.new(StringIO.new(input, "r")).read!

      Visitors::ToRuby.new(permitted_classes: permitted_classes, permitted_symbols: permitted_symbols).visit(root)
    end
  end
end