Skip to content

Commit

Permalink
Move the responsibility of safe loading to Node
Browse files Browse the repository at this point in the history
This change moves the responsibility of safely loading a YAML tree from
an internal detail of `Psych.safe_load` into `Psych::Nodes::Node`.

The advantage of this is that you can now more easily safely load trees
that you're working on without replicating the safety constraints of
`Psych.safe_load`. The delegation of responsibilities also now matches
for safely and unsafely loading a tree.
  • Loading branch information
michaelherold committed Aug 14, 2023
1 parent 9de928f commit 8ae2fc5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
14 changes: 2 additions & 12 deletions lib/psych.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,20 +319,10 @@ def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: fals
# Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
# Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
#
def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false
def self.safe_load yaml, filename: nil, fallback: nil, **kwargs
result = parse(yaml, filename: filename)
return fallback unless result

class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
permitted_symbols.map(&:to_s))
scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
visitor = if aliases
Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
else
Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
end
result = visitor.accept result
result
result.to_safe_ruby(**kwargs)
end

###
Expand Down
17 changes: 17 additions & 0 deletions lib/psych/nodes/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
end
alias :transform :to_ruby

###
# Safely convert this node to Ruby.
#
# See also Psych.safe_load
#
def to_safe_ruby(permitted_classes: [], permitted_symbols: [], aliases: false, symbolize_names: false, freeze: false, strict_integer: false)
class_loader = ClassLoader::Restricted.new(
permitted_classes.map(&:to_s),
permitted_symbols.map(&:to_s)
)
scanner = ScalarScanner.new(class_loader, strict_integer: strict_integer)
visitor_class = aliases ? Visitors::ToRuby : Visitors::NoAliasRuby

visitor_class.new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze).accept(self)
end
alias :safe_transform :to_safe_ruby

###
# Convert this node to YAML.
#
Expand Down

0 comments on commit 8ae2fc5

Please sign in to comment.