summaryrefslogtreecommitdiff
path: root/ext/psych/lib
diff options
context:
space:
mode:
authorSeth Boyles <sethboyles@gmail.com>2022-01-14 19:58:20 +0000
committergit <svn-admin@ruby-lang.org>2022-01-22 10:00:51 +0900
commitc1a6ff046d4f27c972adf96f9a6724abc2f0647a (patch)
treef3924a5c026669589d07d2eab9a9e6673684c8f8 /ext/psych/lib
parentb815a0bd75b660652bf05479467904fa06399092 (diff)
[ruby/psych] Add strict_integer option to parse numbers with commas as strings
Authored-by: Seth Boyles <sethboyles@gmail.com> https://github.com/ruby/psych/commit/75bebb37b8
Diffstat (limited to 'ext/psych/lib')
-rw-r--r--ext/psych/lib/psych.rb13
-rw-r--r--ext/psych/lib/psych/nodes/node.rb4
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb22
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb4
4 files changed, 26 insertions, 17 deletions
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index 1a95408ca0..42d79efb83 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -268,10 +268,10 @@ module Psych
# YAML documents that are supplied via user input. Instead, please use the
# load method or the safe_load method.
#
- def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false
+ def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false
result = parse(yaml, filename: filename)
return fallback unless result
- result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer)
end
###
@@ -319,13 +319,13 @@ module Psych
# 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
+ def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false
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
+ 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
@@ -365,14 +365,15 @@ module Psych
# Raises a TypeError when `yaml` parameter is NilClass. This method is
# similar to `safe_load` except that `Symbol` objects are allowed by default.
#
- def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
+ def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false
safe_load yaml, permitted_classes: permitted_classes,
permitted_symbols: permitted_symbols,
aliases: aliases,
filename: filename,
fallback: fallback,
symbolize_names: symbolize_names,
- freeze: freeze
+ freeze: freeze,
+ strict_integer: strict_integer
end
###
diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb
index 1f841625ca..f44fce5f05 100644
--- a/ext/psych/lib/psych/nodes/node.rb
+++ b/ext/psych/lib/psych/nodes/node.rb
@@ -46,8 +46,8 @@ module Psych
# Convert this node to Ruby.
#
# See also Psych::Visitors::ToRuby
- def to_ruby(symbolize_names: false, freeze: false)
- Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze).accept(self)
+ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self)
end
alias :transform :to_ruby
diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb
index 604cb3e399..58deea3baa 100644
--- a/ext/psych/lib/psych/scalar_scanner.rb
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -12,24 +12,32 @@ module Psych
FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
# Taken from http://yaml.org/type/int.html
- INTEGER = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
- |[-+]?0[0-7_,]+ (?# base 8)
- |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
- |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
+ INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2)
+ |[-+]?0[0-7_]+ (?# base 8)
+ |[-+]?(0|[1-9][0-9_]*) (?# base 10)
+ |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
+
+ # Same as above, but allows commas.
+ # Not to YML spec, but kept for backwards compatibility
+ INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
+ |[-+]?0[0-7_,]+ (?# base 8)
+ |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
+ |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
attr_reader :class_loader
# Create a new scanner
- def initialize class_loader
+ def initialize class_loader, strict_integer: false
@symbol_cache = {}
@class_loader = class_loader
+ @strict_integer = strict_integer
end
# Tokenize +string+ returning the Ruby object
def tokenize string
return nil if string.empty?
return @symbol_cache[string] if @symbol_cache.key?(string)
-
+ integer_regex = @strict_integer ? INTEGER_STRICT : INTEGER_LEGACY
# Check for a String type, being careful not to get caught by hash keys, hex values, and
# special floats (e.g., -.inf).
if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
@@ -89,7 +97,7 @@ module Psych
else
Float(string.gsub(/[,_]|\.([Ee]|$)/, '\1'))
end
- elsif string.match?(INTEGER)
+ elsif string.match?(integer_regex)
parse_int string
else
string
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 4c1f561070..935bc74f21 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -12,9 +12,9 @@ module Psych
###
# This class walks a YAML AST, converting each node to Ruby
class ToRuby < Psych::Visitors::Visitor
- def self.create(symbolize_names: false, freeze: false)
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false)
class_loader = ClassLoader.new
- scanner = ScalarScanner.new class_loader
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
end