summaryrefslogtreecommitdiff
path: root/ext/psych/lib/psych.rb
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-05-14 17:26:41 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-05-14 17:26:41 +0000
commit7ceafcbdf5bd2155704839f97b869e689f66feeb (patch)
tree278d237513fff700906430468892ede20d3f76c1 /ext/psych/lib/psych.rb
parentd7f06a665c8e5b4ec83b6baa4a7532fc7ad7f24a (diff)
* ext/psych/lib/psych.rb: Adding Psych.safe_load for loading a user
defined, restricted subset of Ruby object types. * ext/psych/lib/psych/class_loader.rb: A class loader for encapsulating the logic for which objects are allowed to be deserialized. * ext/psych/lib/psych/deprecated.rb: Changes to use the class loader * ext/psych/lib/psych/exception.rb: ditto * ext/psych/lib/psych/json/stream.rb: ditto * ext/psych/lib/psych/nodes/node.rb: ditto * ext/psych/lib/psych/scalar_scanner.rb: ditto * ext/psych/lib/psych/stream.rb: ditto * ext/psych/lib/psych/streaming.rb: ditto * ext/psych/lib/psych/visitors/json_tree.rb: ditto * ext/psych/lib/psych/visitors/to_ruby.rb: ditto * ext/psych/lib/psych/visitors/yaml_tree.rb: ditto * ext/psych/psych_to_ruby.c: ditto * test/psych/helper.rb: ditto * test/psych/test_safe_load.rb: tests for restricted subset. * test/psych/test_scalar_scanner.rb: ditto * test/psych/visitors/test_to_ruby.rb: ditto * test/psych/visitors/test_yaml_tree.rb: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40750 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/psych/lib/psych.rb')
-rw-r--r--ext/psych/lib/psych.rb57
1 files changed, 53 insertions, 4 deletions
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index 66a0641f39..711b3c1377 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -246,6 +246,55 @@ module Psych
end
###
+ # Safely load the yaml string in +yaml+. By default, only the following
+ # classes are allowed to be deserialized:
+ #
+ # * TrueClass
+ # * FalseClass
+ # * NilClass
+ # * Numeric
+ # * String
+ # * Array
+ # * Hash
+ #
+ # Recursive data structures are not allowed by default. Arbitrary classes
+ # can be allowed by adding those classes to the +whitelist+. They are
+ # additive. For example, to allow Date deserialization:
+ #
+ # Psych.safe_load(yaml, [Date])
+ #
+ # Now the Date class can be loaded in addition to the classes listed above.
+ #
+ # Aliases can be explicitly allowed by changing the +aliases+ parameter.
+ # For example:
+ #
+ # x = []
+ # x << x
+ # yaml = Psych.dump x
+ # Psych.safe_load yaml # => raises an exception
+ # Psych.safe_load yaml, [], [], true # => loads the aliases
+ #
+ # A Psych::DisallowedClass exception will be raised if the yaml contains a
+ # class that isn't in the whitelist.
+ #
+ # A Psych::BadAlias exception will be raised if the yaml contains aliases
+ # but the +aliases+ parameter is set to false.
+ def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil
+ result = parse(yaml, filename)
+ return unless result
+
+ class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s),
+ whitelist_symbols.map(&:to_s))
+ scanner = ScalarScanner.new class_loader
+ if aliases
+ visitor = Visitors::ToRuby.new scanner, class_loader
+ else
+ visitor = Visitors::NoAliasRuby.new scanner, class_loader
+ end
+ visitor.accept result
+ end
+
+ ###
# Parse a YAML string in +yaml+. Returns the Psych::Nodes::Document.
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
@@ -355,7 +404,7 @@ module Psych
io = nil
end
- visitor = Psych::Visitors::YAMLTree.new options
+ visitor = Psych::Visitors::YAMLTree.create options
visitor << o
visitor.tree.yaml io, options
end
@@ -367,7 +416,7 @@ module Psych
#
# Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
def self.dump_stream *objects
- visitor = Psych::Visitors::YAMLTree.new {}
+ visitor = Psych::Visitors::YAMLTree.create({})
objects.each do |o|
visitor << o
end
@@ -377,7 +426,7 @@ module Psych
###
# Dump Ruby +object+ to a JSON string.
def self.to_json object
- visitor = Psych::Visitors::JSONTree.new
+ visitor = Psych::Visitors::JSONTree.create
visitor << object
visitor.tree.yaml
end
@@ -435,7 +484,7 @@ module Psych
@load_tags = {}
@dump_tags = {}
def self.add_tag tag, klass
- @load_tags[tag] = klass
+ @load_tags[tag] = klass.name
@dump_tags[klass] = tag
end