Module: Ruby::Rego::Builtins::Yaml::ScalarResolver
- Defined in:
- lib/ruby/rego/builtins/yaml/scalar_resolver.rb,
lib/ruby/rego/builtins/yaml/scalar_resolver/tags.rb,
lib/ruby/rego/builtins/yaml/scalar_resolver/numbers.rb,
lib/ruby/rego/builtins/yaml/scalar_resolver/document.rb
Overview
Walks a parsed Psych document into JSON-compatible Ruby values: node dispatch,
anchors/aliases, << merge keys, JSON object-key stringification, and the
non-finite/DoS rejection pass. Lives apart from the resolution core so the main
file stays under RubyCritic’s complexity budget; constants and self-dispatched
helpers (scalar_value, MAX_DEPTH, …) resolve via lexical scope / the module.
Defined Under Namespace
Classes: ResolveError
Constant Summary collapse
- MAX_YAML_SOURCE =
DoS bounds. OPA relies on Go runtime limits absent here, so an untrusted document exceeding these yields undefined rather than exhausting memory/stack: source byte length, nesting depth (guards a Ruby stack overflow), and total expanded nodes (guards against alias-expansion “billion laughs” bombs).
1_000_000- MAX_DEPTH =
1_000- MAX_NODES =
5_000_000- INT64_MIN =
go-yaml resolves an integer via strconv ParseInt (int64) then ParseUint (uint64). ParseUint rejects a sign, so an explicitly +/- signed value is bounded by int64; only an unsigned value may reach uint64 max. A prefixed 0x/0o/0b literal beyond the accepted range can’t be reparsed as a float, so it falls back to its string text; an out-of-range !!int (any base) is undefined. A bare integer key in the positive uint64-only band decodes to a Go uint64, which sigs.k8s.io/yaml cannot stringify as a JSON key, so that document is undefined.
-(2**63)
- INT64_MAX =
(2**63) - 1
- UINT64_MAX =
(2**64) - 1
- FLOAT64_FINITE_MAX_DIGITS =
A decimal token of at most this many characters is below 10**308 (< float64 max, ~1.8e308), so it cannot overflow float64 — decimal_overflows_float64? uses this to skip the Float() overflow probe for the common (small-integer) case.
308- RESOLVE_MAP =
Plain scalars with a fixed meaning (yaml.v2 resolveMap).
{ "" => nil, "~" => nil, "null" => nil, "Null" => nil, "NULL" => nil, "y" => true, "Y" => true, "yes" => true, "Yes" => true, "YES" => true, "true" => true, "True" => true, "TRUE" => true, "on" => true, "On" => true, "ON" => true, "n" => false, "N" => false, "no" => false, "No" => false, "NO" => false, "false" => false, "False" => false, "FALSE" => false, "off" => false, "Off" => false, "OFF" => false, ".nan" => Float::NAN, ".NaN" => Float::NAN, ".NAN" => Float::NAN, ".inf" => Float::INFINITY, ".Inf" => Float::INFINITY, ".INF" => Float::INFINITY, "+.inf" => Float::INFINITY, "+.Inf" => Float::INFINITY, "+.INF" => Float::INFINITY, "-.inf" => -Float::INFINITY, "-.Inf" => -Float::INFINITY, "-.INF" => -Float::INFINITY }.freeze
- TAG_PREFIX =
Prefix of an explicit core YAML schema tag (e.g. “tag:yaml.org,2002:int”).
"tag:yaml.org,2002:"- NUMBER_LEADS =
First-byte hints that a scalar might be a number (yaml.v2 resolveTable).
"+-.0123456789"- FLOAT_RE =
/\A[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?\z/
Class Method Summary collapse
-
.ambiguous?(string) ⇒ bool
True when a plain scalar would resolve to something other than a string (so the emitter must quote it).
-
.load(string) ⇒ Object
Parses YAML and returns the first document as JSON-compatible Ruby values.
-
.resolve(string) ⇒ Object
Resolves a plain scalar string to its Ruby value (or itself, as a string).
Class Method Details
.ambiguous?(string) ⇒ bool
True when a plain scalar would resolve to something other than a string (so the emitter must quote it).
80 81 82 83 |
# File 'lib/ruby/rego/builtins/yaml/scalar_resolver.rb', line 80 def self.ambiguous?(string) resolved = resolve(string) !(resolved.is_a?(String) && resolved == string) end |
.load(string) ⇒ Object
Parses YAML and returns the first document as JSON-compatible Ruby values.
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ruby/rego/builtins/yaml/scalar_resolver.rb', line 87 def self.load(string) raise ResolveError, "yaml too long" if string.bytesize > MAX_YAML_SOURCE document = Psych.parse_stream(string).children.first # An absent document or one with no root node is an empty document, which # decodes to null (matching yaml.v2 / sigs.k8s.io/yaml), not an error. return nil if document.nil? || document.root.nil? value = build(document.root, {}, 0) reject_non_finite(value, [MAX_NODES], 0) value end |
.resolve(string) ⇒ Object
Resolves a plain scalar string to its Ruby value (or itself, as a string).
70 71 72 73 74 75 |
# File 'lib/ruby/rego/builtins/yaml/scalar_resolver.rb', line 70 def self.resolve(string) return RESOLVE_MAP[string] if RESOLVE_MAP.key?(string) return string unless numeric_lead?(string) numeric(string) || string end |