From 7ceafcbdf5bd2155704839f97b869e689f66feeb Mon Sep 17 00:00:00 2001 From: tenderlove Date: Tue, 14 May 2013 17:26:41 +0000 Subject: * 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 --- ext/psych/lib/psych.rb | 57 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'ext/psych/lib/psych.rb') 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 @@ -245,6 +245,55 @@ module Psych result ? result.to_ruby : result 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 @@ -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 -- cgit v1.2.3