summaryrefslogtreecommitdiff
path: root/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec')
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.2.yaml2
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.3.yaml2
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue48.txt20
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue49.yml0
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/libyaml_checker_spec.rb69
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/psych_resolver_spec.rb10
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/resolver_specs.rb278
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/safe_yaml_spec.rb731
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/spec_helper.rb42
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/store_spec.rb57
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/support/exploitable_back_door.rb29
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/syck_resolver_spec.rb10
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/base64_spec.rb11
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_date_spec.rb60
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_float_spec.rb42
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_integer_spec.rb64
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_symbol_spec.rb51
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/yaml_spec.rb15
18 files changed, 1493 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.2.yaml b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.2.yaml
new file mode 100644
index 0000000..bdd70cc
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.2.yaml
@@ -0,0 +1,2 @@
+--- !ruby/object:ExploitableBackDoor
+foo: bar
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.3.yaml b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.3.yaml
new file mode 100644
index 0000000..c24e04b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/exploit.1.9.3.yaml
@@ -0,0 +1,2 @@
+--- !ruby/hash:ExploitableBackDoor
+foo: bar
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue48.txt b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue48.txt
new file mode 100644
index 0000000..97d1f68
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue48.txt
@@ -0,0 +1,20 @@
+---
+title: Blah
+key: value
+---
+
+I'm going to inject a bunch of YAML-looking stuff below and it should all just get ignored.
+
+foo: bar
+
+- foo
+- bar
+
+:foo
+42
+~
+
+---
+text: |
+ Look, I'm another YAML document!
+---
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue49.yml b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue49.yml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/issue49.yml
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/libyaml_checker_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/libyaml_checker_spec.rb
new file mode 100644
index 0000000..b5b290b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/libyaml_checker_spec.rb
@@ -0,0 +1,69 @@
+require "spec_helper"
+
+describe SafeYAML::LibyamlChecker do
+ describe "check_libyaml_version" do
+ REAL_YAML_ENGINE = SafeYAML::YAML_ENGINE
+ REAL_LIBYAML_VERSION = SafeYAML::LibyamlChecker::LIBYAML_VERSION
+
+ let(:libyaml_patched) { false }
+
+ before :each do
+ allow(SafeYAML::LibyamlChecker).to receive(:libyaml_patched?).and_return(libyaml_patched)
+ end
+
+ after :each do
+ silence_warnings do
+ SafeYAML::YAML_ENGINE = REAL_YAML_ENGINE
+ SafeYAML::LibyamlChecker::LIBYAML_VERSION = REAL_LIBYAML_VERSION
+ end
+ end
+
+ def test_libyaml_version_ok(expected_result, yaml_engine, libyaml_version=nil)
+ silence_warnings do
+ SafeYAML.const_set("YAML_ENGINE", yaml_engine)
+ SafeYAML::LibyamlChecker.const_set("LIBYAML_VERSION", libyaml_version)
+ expect(SafeYAML::LibyamlChecker.libyaml_version_ok?).to eq(expected_result)
+ end
+ end
+
+ unless defined?(JRUBY_VERSION)
+ it "issues no warnings when 'Syck' is the YAML engine" do
+ test_libyaml_version_ok(true, "syck")
+ end
+
+ it "issues a warning if Psych::LIBYAML_VERSION is not defined" do
+ test_libyaml_version_ok(false, "psych")
+ end
+
+ it "issues a warning if Psych::LIBYAML_VERSION is < 0.1.6" do
+ test_libyaml_version_ok(false, "psych", "0.1.5")
+ end
+
+ it "issues no warning if Psych::LIBYAML_VERSION is == 0.1.6" do
+ test_libyaml_version_ok(true, "psych", "0.1.6")
+ end
+
+ it "issues no warning if Psych::LIBYAML_VERSION is > 0.1.6" do
+ test_libyaml_version_ok(true, "psych", "1.0.0")
+ end
+
+ it "does a proper version comparison (not just a string comparison)" do
+ test_libyaml_version_ok(true, "psych", "0.1.10")
+ end
+
+ context "when the system has a known patched libyaml version" do
+ let(:libyaml_patched) { true }
+
+ it "issues no warning, even when Psych::LIBYAML_VERSION < 0.1.6" do
+ test_libyaml_version_ok(true, "psych", "0.1.4")
+ end
+ end
+ end
+
+ if defined?(JRUBY_VERSION)
+ it "issues no warning, as JRuby doesn't use libyaml" do
+ test_libyaml_version_ok(true, "psych", "0.1.4")
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/psych_resolver_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/psych_resolver_spec.rb
new file mode 100644
index 0000000..a9e76b5
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/psych_resolver_spec.rb
@@ -0,0 +1,10 @@
+require "spec_helper"
+
+if SafeYAML::YAML_ENGINE == "psych"
+ require "safe_yaml/psych_resolver"
+
+ describe SafeYAML::PsychResolver do
+ include ResolverSpecs
+ let(:resolver) { SafeYAML::PsychResolver.new }
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/resolver_specs.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/resolver_specs.rb
new file mode 100644
index 0000000..1b981e5
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/resolver_specs.rb
@@ -0,0 +1,278 @@
+module ResolverSpecs
+ def self.included(base)
+ base.module_eval do
+ let(:resolver) { nil }
+ let(:result) { @result }
+
+ before :each do
+ # See the comment in the first before :each block in safe_yaml_spec.rb.
+ require "safe_yaml"
+ end
+
+ def parse(yaml)
+ tree = YAML.parse(yaml.unindent)
+ @result = resolver.resolve_node(tree)
+ end
+
+ # Isn't this how I should've been doing it all along?
+ def parse_and_test(yaml)
+ safe_result = parse(yaml)
+
+ exception_thrown = nil
+
+ unsafe_result = begin
+ YAML.unsafe_load(yaml)
+ rescue Exception => e
+ exception_thrown = e
+ end
+
+ if exception_thrown
+ # If the underlying YAML parser (e.g. Psych) threw an exception, I'm
+ # honestly not sure what the right thing to do is. For now I'll just
+ # print a warning. Should SafeYAML fail when Psych fails?
+ Kernel.warn "\n"
+ Kernel.warn "Discrepancy between SafeYAML and #{SafeYAML::YAML_ENGINE} on input:\n"
+ Kernel.warn "#{yaml.unindent}\n"
+ Kernel.warn "SafeYAML result:"
+ Kernel.warn "#{safe_result.inspect}\n"
+ Kernel.warn "#{SafeYAML::YAML_ENGINE} result:"
+ Kernel.warn "#{exception_thrown.inspect}\n"
+
+ else
+ expect(safe_result).to eq(unsafe_result)
+ end
+ end
+
+ context "by default" do
+ it "translates maps to hashes" do
+ parse <<-YAML
+ potayto: potahto
+ tomayto: tomahto
+ YAML
+
+ expect(result).to eq({
+ "potayto" => "potahto",
+ "tomayto" => "tomahto"
+ })
+ end
+
+ it "translates sequences to arrays" do
+ parse <<-YAML
+ - foo
+ - bar
+ - baz
+ YAML
+
+ expect(result).to eq(["foo", "bar", "baz"])
+ end
+
+ it "translates most values to strings" do
+ parse "string: value"
+ expect(result).to eq({ "string" => "value" })
+ end
+
+ it "does not deserialize symbols" do
+ parse ":symbol: value"
+ expect(result).to eq({ ":symbol" => "value" })
+ end
+
+ it "translates valid integral numbers to integers" do
+ parse "integer: 1"
+ expect(result).to eq({ "integer" => 1 })
+ end
+
+ it "translates valid decimal numbers to floats" do
+ parse "float: 3.14"
+ expect(result).to eq({ "float" => 3.14 })
+ end
+
+ it "translates valid dates" do
+ parse "date: 2013-01-24"
+ expect(result).to eq({ "date" => Date.parse("2013-01-24") })
+ end
+
+ it "translates valid true/false values to booleans" do
+ parse <<-YAML
+ - yes
+ - true
+ - no
+ - false
+ YAML
+
+ expect(result).to eq([true, true, false, false])
+ end
+
+ it "translates valid nulls to nil" do
+ parse <<-YAML
+ -
+ - ~
+ - null
+ YAML
+
+ expect(result).to eq([nil] * 3)
+ end
+
+ it "matches the behavior of the underlying YAML engine w/ respect to capitalization of boolean values" do
+ parse_and_test <<-YAML
+ - true
+ - True
+ - TRUE
+ - tRue
+ - TRue
+ - False
+ - FALSE
+ - fAlse
+ - FALse
+ YAML
+
+ # using Syck: [true, true, true, "tRue", "TRue", false, false, "fAlse", "FALse"]
+ # using Psych: all booleans
+ end
+
+ it "matches the behavior of the underlying YAML engine w/ respect to capitalization of nil values" do
+ parse_and_test <<-YAML
+ - Null
+ - NULL
+ - nUll
+ - NUll
+ YAML
+
+ # using Syck: [nil, nil, "nUll", "NUll"]
+ # using Psych: all nils
+ end
+
+ it "translates quoted empty strings to strings (not nil)" do
+ parse "foo: ''"
+ expect(result).to eq({ "foo" => "" })
+ end
+
+ it "correctly reverse-translates strings encoded via #to_yaml" do
+ parse "5.10".to_yaml
+ expect(result).to eq("5.10")
+ end
+
+ it "does not specially parse any double-quoted strings" do
+ parse <<-YAML
+ - "1"
+ - "3.14"
+ - "true"
+ - "false"
+ - "2013-02-03"
+ - "2013-02-03 16:27:00 -0600"
+ YAML
+
+ expect(result).to eq(["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"])
+ end
+
+ it "does not specially parse any single-quoted strings" do
+ parse <<-YAML
+ - '1'
+ - '3.14'
+ - 'true'
+ - 'false'
+ - '2013-02-03'
+ - '2013-02-03 16:27:00 -0600'
+ YAML
+
+ expect(result).to eq(["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"])
+ end
+
+ it "deals just fine with nested maps" do
+ parse <<-YAML
+ foo:
+ bar:
+ marco: polo
+ YAML
+
+ expect(result).to eq({ "foo" => { "bar" => { "marco" => "polo" } } })
+ end
+
+ it "deals just fine with nested sequences" do
+ parse <<-YAML
+ - foo
+ -
+ - bar1
+ - bar2
+ -
+ - baz1
+ - baz2
+ YAML
+
+ expect(result).to eq(["foo", ["bar1", "bar2", ["baz1", "baz2"]]])
+ end
+
+ it "applies the same transformations to keys as to values" do
+ parse <<-YAML
+ foo: string
+ :bar: symbol
+ 1: integer
+ 3.14: float
+ 2013-01-24: date
+ YAML
+
+ expect(result).to eq({
+ "foo" => "string",
+ ":bar" => "symbol",
+ 1 => "integer",
+ 3.14 => "float",
+ Date.parse("2013-01-24") => "date",
+ })
+ end
+
+ it "applies the same transformations to elements in sequences as to all values" do
+ parse <<-YAML
+ - foo
+ - :bar
+ - 1
+ - 3.14
+ - 2013-01-24
+ YAML
+
+ expect(result).to eq(["foo", ":bar", 1, 3.14, Date.parse("2013-01-24")])
+ end
+ end
+
+ context "for Ruby version #{RUBY_VERSION}" do
+ it "translates valid time values" do
+ parse "time: 2013-01-29 05:58:00 -0800"
+ expect(result).to eq({ "time" => Time.utc(2013, 1, 29, 13, 58, 0) })
+ end
+
+ it "applies the same transformation to elements in sequences" do
+ parse "- 2013-01-29 05:58:00 -0800"
+ expect(result).to eq([Time.utc(2013, 1, 29, 13, 58, 0)])
+ end
+
+ it "applies the same transformation to keys" do
+ parse "2013-01-29 05:58:00 -0800: time"
+ expect(result).to eq({ Time.utc(2013, 1, 29, 13, 58, 0) => "time" })
+ end
+ end
+
+ context "with symbol deserialization enabled" do
+ before :each do
+ SafeYAML::OPTIONS[:deserialize_symbols] = true
+ end
+
+ after :each do
+ SafeYAML.restore_defaults!
+ end
+
+ it "translates values starting with ':' to symbols" do
+ parse "symbol: :value"
+ expect(result).to eq({ "symbol" => :value })
+ end
+
+ it "applies the same transformation to keys" do
+ parse ":bar: symbol"
+ expect(result).to eq({ :bar => "symbol" })
+ end
+
+ it "applies the same transformation to elements in sequences" do
+ parse "- :bar"
+ expect(result).to eq([:bar])
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/safe_yaml_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/safe_yaml_spec.rb
new file mode 100644
index 0000000..aa701a4
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/safe_yaml_spec.rb
@@ -0,0 +1,731 @@
+require "spec_helper"
+
+describe YAML do
+ def safe_load_round_trip(object, options={})
+ yaml = object.to_yaml
+ if SafeYAML::YAML_ENGINE == "psych"
+ YAML.safe_load(yaml, nil, options)
+ else
+ YAML.safe_load(yaml, options)
+ end
+ end
+
+ before :each do
+ # Need to require this here (as opposed to somewhere up higher in the file)
+ # to ensure that safe_yaml isn't loaded and therefore YAML isn't monkey-
+ # patched, for tests that require only safe_yaml/load.
+ require "safe_yaml"
+ require "exploitable_back_door"
+
+ SafeYAML.restore_defaults!
+ end
+
+ after :each do
+ SafeYAML.restore_defaults!
+ end
+
+ describe "unsafe_load" do
+ if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3"
+ it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do
+ backdoor = YAML.unsafe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
+ expect(backdoor).to be_exploited_through_setter
+ end
+
+ it "allows exploits through objects defined in YAML w/ !ruby/object via the :init_with method" do
+ backdoor = YAML.unsafe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
+ expect(backdoor).to be_exploited_through_init_with
+ end
+ end
+
+ it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do
+ backdoor = YAML.unsafe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
+ expect(backdoor).to be_exploited_through_ivars
+ end
+
+ context "with special whitelisted tags defined" do
+ before :each do
+ SafeYAML::whitelist!(OpenStruct)
+ end
+
+ it "effectively ignores the whitelist (since everything is whitelisted)" do
+ result = YAML.unsafe_load <<-YAML.unindent
+ --- !ruby/object:OpenStruct
+ table:
+ :backdoor: !ruby/object:ExploitableBackDoor
+ foo: bar
+ YAML
+
+ expect(result).to be_a(OpenStruct)
+ expect(result.backdoor).to be_exploited_through_ivars
+ end
+ end
+ end
+
+ describe "safe_load" do
+ it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do
+ object = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
+ expect(object).not_to be_a(ExploitableBackDoor)
+ end
+
+ it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do
+ object = YAML.safe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
+ expect(object).not_to be_a(ExploitableBackDoor)
+ end
+
+ context "for YAML engine #{SafeYAML::YAML_ENGINE}" do
+ if SafeYAML::YAML_ENGINE == "psych"
+ let(:options) { nil }
+ let(:arguments) { ["foo: bar", nil, options] }
+
+ context "when no tags are whitelisted" do
+ it "constructs a SafeYAML::PsychHandler to resolve nodes as they're parsed, for optimal performance" do
+ expect(Psych::Parser).to receive(:new).with an_instance_of(SafeYAML::PsychHandler)
+ # This won't work now; we just want to ensure Psych::Parser#parse was in fact called.
+ YAML.safe_load(*arguments) rescue nil
+ end
+ end
+
+ context "when whitelisted tags are specified" do
+ let(:options) {
+ { :whitelisted_tags => ["foo"] }
+ }
+
+ it "instead uses Psych to construct a full tree before examining the nodes" do
+ expect(Psych).to receive(:parse)
+ # This won't work now; we just want to ensure Psych::Parser#parse was in fact called.
+ YAML.safe_load(*arguments) rescue nil
+ end
+ end
+ end
+
+ if SafeYAML::YAML_ENGINE == "syck"
+ it "uses Syck internally to parse YAML" do
+ expect(YAML).to receive(:parse).with("foo: bar")
+ # This won't work now; we just want to ensure YAML::parse was in fact called.
+ YAML.safe_load("foo: bar") rescue nil
+ end
+ end
+ end
+
+ it "loads a plain ol' YAML document just fine" do
+ result = YAML.safe_load <<-YAML.unindent
+ foo:
+ number: 1
+ boolean: true
+ nil: ~
+ string: Hello, there!
+ symbol: :blah
+ sequence:
+ - hi
+ - bye
+ YAML
+
+ expect(result).to eq({
+ "foo" => {
+ "number" => 1,
+ "boolean" => true,
+ "nil" => nil,
+ "string" => "Hello, there!",
+ "symbol" => ":blah",
+ "sequence" => ["hi", "bye"]
+ }
+ })
+ end
+
+ it "works for YAML documents with anchors and aliases" do
+ result = YAML.safe_load <<-YAML
+ - &id001 {}
+ - *id001
+ - *id001
+ YAML
+
+ expect(result).to eq([{}, {}, {}])
+ end
+
+ it "works for YAML documents with binary tagged keys" do
+ result = YAML.safe_load <<-YAML
+ ? !!binary >
+ Zm9v
+ : "bar"
+ ? !!binary >
+ YmFy
+ : "baz"
+ YAML
+
+ expect(result).to eq({"foo" => "bar", "bar" => "baz"})
+ end
+
+ it "works for YAML documents with binary tagged values" do
+ result = YAML.safe_load <<-YAML
+ "foo": !!binary >
+ YmFy
+ "bar": !!binary >
+ YmF6
+ YAML
+
+ expect(result).to eq({"foo" => "bar", "bar" => "baz"})
+ end
+
+ it "works for YAML documents with binary tagged array values" do
+ result = YAML.safe_load <<-YAML
+ - !binary |-
+ Zm9v
+ - !binary |-
+ YmFy
+ YAML
+
+ expect(result).to eq(["foo", "bar"])
+ end
+
+ it "works for YAML documents with sections" do
+ result = YAML.safe_load <<-YAML
+ mysql: &mysql
+ adapter: mysql
+ pool: 30
+ login: &login
+ username: user
+ password: password123
+ development: &development
+ <<: *mysql
+ <<: *login
+ host: localhost
+ YAML
+
+ expect(result).to eq({
+ "mysql" => {
+ "adapter" => "mysql",
+ "pool" => 30
+ },
+ "login" => {
+ "username" => "user",
+ "password" => "password123"
+ },
+ "development" => {
+ "adapter" => "mysql",
+ "pool" => 30,
+ "username" => "user",
+ "password" => "password123",
+ "host" => "localhost"
+ }
+ })
+ end
+
+ it "correctly prefers explicitly defined values over default values from included sections" do
+ # Repeating this test 100 times to increase the likelihood of running into an issue caused by
+ # non-deterministic hash key enumeration.
+ 100.times do
+ result = YAML.safe_load <<-YAML
+ defaults: &defaults
+ foo: foo
+ bar: bar
+ baz: baz
+ custom:
+ <<: *defaults
+ bar: custom_bar
+ baz: custom_baz
+ YAML
+
+ expect(result["custom"]).to eq({
+ "foo" => "foo",
+ "bar" => "custom_bar",
+ "baz" => "custom_baz"
+ })
+ end
+ end
+
+ it "works with multi-level inheritance" do
+ result = YAML.safe_load <<-YAML
+ defaults: &defaults
+ foo: foo
+ bar: bar
+ baz: baz
+ custom: &custom
+ <<: *defaults
+ bar: custom_bar
+ baz: custom_baz
+ grandcustom: &grandcustom
+ <<: *custom
+ YAML
+
+ expect(result).to eq({
+ "defaults" => { "foo" => "foo", "bar" => "bar", "baz" => "baz" },
+ "custom" => { "foo" => "foo", "bar" => "custom_bar", "baz" => "custom_baz" },
+ "grandcustom" => { "foo" => "foo", "bar" => "custom_bar", "baz" => "custom_baz" }
+ })
+ end
+
+ it "returns false when parsing an empty document" do
+ expect([
+ YAML.safe_load(""),
+ YAML.safe_load(" "),
+ YAML.safe_load("\n")
+ ]).to eq([false, false, false])
+ end
+
+ it "returns nil when parsing a single value representing nil" do
+ expect([
+ YAML.safe_load("~"),
+ YAML.safe_load("null")
+ ]).to eq([nil, nil])
+ end
+
+ context "with custom initializers defined" do
+ before :each do
+ if SafeYAML::YAML_ENGINE == "psych"
+ SafeYAML::OPTIONS[:custom_initializers] = {
+ "!set" => lambda { Set.new },
+ "!hashiemash" => lambda { Hashie::Mash.new }
+ }
+ else
+ SafeYAML::OPTIONS[:custom_initializers] = {
+ "tag:yaml.org,2002:set" => lambda { Set.new },
+ "tag:yaml.org,2002:hashiemash" => lambda { Hashie::Mash.new }
+ }
+ end
+ end
+
+ it "will use a custom initializer to instantiate an array-like class upon deserialization" do
+ result = YAML.safe_load <<-YAML.unindent
+ --- !set
+ - 1
+ - 2
+ - 3
+ YAML
+
+ expect(result).to be_a(Set)
+ expect(result.to_a).to match_array([1, 2, 3])
+ end
+
+ it "will use a custom initializer to instantiate a hash-like class upon deserialization" do
+ result = YAML.safe_load <<-YAML.unindent
+ --- !hashiemash
+ foo: bar
+ YAML
+
+ expect(result).to be_a(Hashie::Mash)
+ expect(result.to_hash).to eq({ "foo" => "bar" })
+ end
+ end
+
+ context "with special whitelisted tags defined" do
+ before :each do
+ SafeYAML::whitelist!(OpenStruct)
+
+ # Necessary for deserializing OpenStructs properly.
+ SafeYAML::OPTIONS[:deserialize_symbols] = true
+ end
+
+ it "will allow objects to be deserialized for whitelisted tags" do
+ result = YAML.safe_load("--- !ruby/object:OpenStruct\ntable:\n foo: bar\n")
+ expect(result).to be_a(OpenStruct)
+ expect(result.instance_variable_get(:@table)).to eq({ "foo" => "bar" })
+ end
+
+ it "will not deserialize objects without whitelisted tags" do
+ result = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
+ expect(result).not_to be_a(ExploitableBackDoor)
+ expect(result).to eq({ "foo" => "bar" })
+ end
+
+ it "will not allow non-whitelisted objects to be embedded within objects with whitelisted tags" do
+ result = YAML.safe_load <<-YAML.unindent
+ --- !ruby/object:OpenStruct
+ table:
+ :backdoor: !ruby/object:ExploitableBackDoor
+ foo: bar
+ YAML
+
+ expect(result).to be_a(OpenStruct)
+ expect(result.backdoor).not_to be_a(ExploitableBackDoor)
+ expect(result.backdoor).to eq({ "foo" => "bar" })
+ end
+
+ context "with the :raise_on_unknown_tag option enabled" do
+ before :each do
+ SafeYAML::OPTIONS[:raise_on_unknown_tag] = true
+ end
+
+ after :each do
+ SafeYAML.restore_defaults!
+ end
+
+ it "raises an exception if a non-nil, non-whitelisted tag is encountered" do
+ expect {
+ YAML.safe_load <<-YAML.unindent
+ --- !ruby/object:Unknown
+ foo: bar
+ YAML
+ }.to raise_error
+ end
+
+ it "checks all tags, even those within objects with trusted tags" do
+ expect {
+ YAML.safe_load <<-YAML.unindent
+ --- !ruby/object:OpenStruct
+ table:
+ :backdoor: !ruby/object:Unknown
+ foo: bar
+ YAML
+ }.to raise_error
+ end
+
+ it "does not raise an exception as long as all tags are whitelisted" do
+ result = YAML.safe_load <<-YAML.unindent
+ --- !ruby/object:OpenStruct
+ table:
+ :backdoor:
+ string: foo
+ integer: 1
+ float: 3.14
+ symbol: :bar
+ date: 2013-02-20
+ array: []
+ hash: {}
+ YAML
+
+ expect(result).to be_a(OpenStruct)
+ expect(result.backdoor).to eq({
+ "string" => "foo",
+ "integer" => 1,
+ "float" => 3.14,
+ "symbol" => :bar,
+ "date" => Date.parse("2013-02-20"),
+ "array" => [],
+ "hash" => {}
+ })
+ end
+
+ it "does not raise an exception on the non-specific '!' tag" do
+ result = nil
+ expect { result = YAML.safe_load "--- ! 'foo'" }.to_not raise_error
+ expect(result).to eq("foo")
+ end
+
+ context "with whitelisted custom class" do
+ class SomeClass
+ attr_accessor :foo
+ end
+ let(:instance) { SomeClass.new }
+
+ before do
+ SafeYAML::whitelist!(SomeClass)
+ instance.foo = 'with trailing whitespace: '
+ end
+
+ it "does not raise an exception on the non-specific '!' tag" do
+ result = nil
+ expect { result = YAML.safe_load(instance.to_yaml) }.to_not raise_error
+ expect(result.foo).to eq('with trailing whitespace: ')
+ end
+ end
+ end
+ end
+
+ context "when options are passed direclty to #load which differ from the defaults" do
+ let(:default_options) { {} }
+
+ before :each do
+ SafeYAML::OPTIONS.merge!(default_options)
+ end
+
+ context "(for example, when symbol deserialization is enabled by default)" do
+ let(:default_options) { { :deserialize_symbols => true } }
+
+ it "goes with the default option when it is not overridden" do
+ silence_warnings do
+ expect(YAML.load(":foo: bar")).to eq({ :foo => "bar" })
+ end
+ end
+
+ it "allows the default option to be overridden on a per-call basis" do
+ silence_warnings do
+ expect(YAML.load(":foo: bar", :deserialize_symbols => false)).to eq({ ":foo" => "bar" })
+ expect(YAML.load(":foo: bar", :deserialize_symbols => true)).to eq({ :foo => "bar" })
+ end
+ end
+ end
+
+ context "(or, for example, when certain tags are whitelisted)" do
+ let(:default_options) {
+ {
+ :deserialize_symbols => true,
+ :whitelisted_tags => SafeYAML::YAML_ENGINE == "psych" ?
+ ["!ruby/object:OpenStruct"] :
+ ["tag:ruby.yaml.org,2002:object:OpenStruct"]
+ }
+ }
+
+ it "goes with the default option when it is not overridden" do
+ result = safe_load_round_trip(OpenStruct.new(:foo => "bar"))
+ expect(result).to be_a(OpenStruct)
+ expect(result.foo).to eq("bar")
+ end
+
+ it "allows the default option to be overridden on a per-call basis" do
+ result = safe_load_round_trip(OpenStruct.new(:foo => "bar"), :whitelisted_tags => [])
+ expect(result).to eq({ "table" => { :foo => "bar" } })
+
+ result = safe_load_round_trip(OpenStruct.new(:foo => "bar"), :deserialize_symbols => false, :whitelisted_tags => [])
+ expect(result).to eq({ "table" => { ":foo" => "bar" } })
+ end
+ end
+ end
+ end
+
+ describe "unsafe_load_file" do
+ if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3"
+ it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do
+ backdoor = YAML.unsafe_load_file "spec/exploit.1.9.3.yaml"
+ expect(backdoor).to be_exploited_through_setter
+ end
+ end
+
+ if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.2"
+ it "allows exploits through objects defined in YAML w/ !ruby/object via the :init_with method" do
+ backdoor = YAML.unsafe_load_file "spec/exploit.1.9.2.yaml"
+ expect(backdoor).to be_exploited_through_init_with
+ end
+ end
+
+ it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do
+ backdoor = YAML.unsafe_load_file "spec/exploit.1.9.2.yaml"
+ expect(backdoor).to be_exploited_through_ivars
+ end
+ end
+
+ describe "safe_load_file" do
+ it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do
+ object = YAML.safe_load_file "spec/exploit.1.9.3.yaml"
+ expect(object).not_to be_a(ExploitableBackDoor)
+ end
+
+ it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do
+ object = YAML.safe_load_file "spec/exploit.1.9.2.yaml"
+ expect(object).not_to be_a(ExploitableBackDoor)
+ end
+
+ it "returns false when parsing an empty file" do
+ expect(YAML.safe_load_file("spec/issue49.yml")).to eq(false)
+ end
+ end
+
+ describe "load" do
+ let(:options) { {} }
+
+ let (:arguments) {
+ if SafeYAML::MULTI_ARGUMENT_YAML_LOAD
+ ["foo: bar", nil, options]
+ else
+ ["foo: bar", options]
+ end
+ }
+
+ context "as long as a :default_mode has been specified" do
+ it "doesn't issue a warning for safe mode, since an explicit mode has been set" do
+ SafeYAML::OPTIONS[:default_mode] = :safe
+ expect(Kernel).not_to receive(:warn)
+ YAML.load(*arguments)
+ end
+
+ it "doesn't issue a warning for unsafe mode, since an explicit mode has been set" do
+ SafeYAML::OPTIONS[:default_mode] = :unsafe
+ expect(Kernel).not_to receive(:warn)
+ YAML.load(*arguments)
+ end
+ end
+
+ context "when the :safe options is specified" do
+ let(:safe_mode) { true }
+ let(:options) { { :safe => safe_mode } }
+
+ it "doesn't issue a warning" do
+ expect(Kernel).not_to receive(:warn)
+ YAML.load(*arguments)
+ end
+
+ it "calls #safe_load if the :safe option is set to true" do
+ expect(YAML).to receive(:safe_load)
+ YAML.load(*arguments)
+ end
+
+ context "when the :safe option is set to false" do
+ let(:safe_mode) { false }
+
+ it "calls #unsafe_load if the :safe option is set to false" do
+ expect(YAML).to receive(:unsafe_load)
+ YAML.load(*arguments)
+ end
+ end
+ end
+
+ it "issues a warning when the :safe option is omitted" do
+ silence_warnings do
+ expect(Kernel).to receive(:warn)
+ YAML.load(*arguments)
+ end
+ end
+
+ it "only issues a warning once (to avoid spamming an app's output)" do
+ silence_warnings do
+ expect(Kernel).to receive(:warn).once
+ 2.times { YAML.load(*arguments) }
+ end
+ end
+
+ it "defaults to safe mode if the :safe option is omitted" do
+ silence_warnings do
+ expect(YAML).to receive(:safe_load)
+ YAML.load(*arguments)
+ end
+ end
+
+ context "with the default mode set to :unsafe" do
+ before :each do
+ SafeYAML::OPTIONS[:default_mode] = :unsafe
+ end
+
+ it "defaults to unsafe mode if the :safe option is omitted" do
+ silence_warnings do
+ expect(YAML).to receive(:unsafe_load)
+ YAML.load(*arguments)
+ end
+ end
+
+ it "calls #safe_load if the :safe option is set to true" do
+ expect(YAML).to receive(:safe_load)
+ YAML.load(*(arguments + [{ :safe => true }]))
+ end
+ end
+ end
+
+ describe "load_file" do
+ let(:filename) { "spec/exploit.1.9.2.yaml" } # doesn't really matter
+
+ it "issues a warning if the :safe option is omitted" do
+ silence_warnings do
+ expect(Kernel).to receive(:warn)
+ YAML.load_file(filename)
+ end
+ end
+
+ it "doesn't issue a warning as long as the :safe option is specified" do
+ expect(Kernel).not_to receive(:warn)
+ YAML.load_file(filename, :safe => true)
+ end
+
+ it "defaults to safe mode if the :safe option is omitted" do
+ silence_warnings do
+ expect(YAML).to receive(:safe_load_file)
+ YAML.load_file(filename)
+ end
+ end
+
+ it "calls #safe_load_file if the :safe option is set to true" do
+ expect(YAML).to receive(:safe_load_file)
+ YAML.load_file(filename, :safe => true)
+ end
+
+ it "calls #unsafe_load_file if the :safe option is set to false" do
+ expect(YAML).to receive(:unsafe_load_file)
+ YAML.load_file(filename, :safe => false)
+ end
+
+ context "with arbitrary object deserialization enabled by default" do
+ before :each do
+ SafeYAML::OPTIONS[:default_mode] = :unsafe
+ end
+
+ it "defaults to unsafe mode if the :safe option is omitted" do
+ silence_warnings do
+ expect(YAML).to receive(:unsafe_load_file)
+ YAML.load_file(filename)
+ end
+ end
+
+ it "calls #safe_load if the :safe option is set to true" do
+ expect(YAML).to receive(:safe_load_file)
+ YAML.load_file(filename, :safe => true)
+ end
+ end
+
+ it "handles files starting with --- (see issue #48)" do
+ expect(YAML.load_file("spec/issue48.txt", :safe => true)).to eq({
+ "title" => "Blah",
+ "key" => "value"
+ })
+ end
+
+ it "handles content starting with --- (see issue #48)" do
+ yaml = File.read("spec/issue48.txt")
+ expect(YAML.load(yaml, :safe => true)).to eq({
+ "title" => "Blah",
+ "key" => "value"
+ })
+ end
+ end
+
+ describe "whitelist!" do
+ context "not a class" do
+ it "should raise" do
+ expect { SafeYAML::whitelist! :foo }.to raise_error(/not a Class/)
+ expect(SafeYAML::OPTIONS[:whitelisted_tags]).to be_empty
+ end
+ end
+
+ context "anonymous class" do
+ it "should raise" do
+ expect { SafeYAML::whitelist! Class.new }.to raise_error(/cannot be anonymous/)
+ expect(SafeYAML::OPTIONS[:whitelisted_tags]).to be_empty
+ end
+ end
+
+ context "with a Class as its argument" do
+ it "should configure correctly" do
+ expect { SafeYAML::whitelist! OpenStruct }.to_not raise_error
+ expect(SafeYAML::OPTIONS[:whitelisted_tags].grep(/OpenStruct\Z/)).not_to be_empty
+ end
+
+ it "successfully deserializes the specified class" do
+ SafeYAML.whitelist!(OpenStruct)
+
+ # necessary for properly assigning OpenStruct attributes
+ SafeYAML::OPTIONS[:deserialize_symbols] = true
+
+ result = safe_load_round_trip(OpenStruct.new(:foo => "bar"))
+ expect(result).to be_a(OpenStruct)
+ expect(result.foo).to eq("bar")
+ end
+
+ it "works for ranges" do
+ SafeYAML.whitelist!(Range)
+ expect(safe_load_round_trip(1..10)).to eq(1..10)
+ end
+
+ it "works for regular expressions" do
+ SafeYAML.whitelist!(Regexp)
+ expect(safe_load_round_trip(/foo/)).to eq(/foo/)
+ end
+
+ it "works for multiple classes" do
+ SafeYAML.whitelist!(Range, Regexp)
+ expect(safe_load_round_trip([(1..10), /bar/])).to eq([(1..10), /bar/])
+ end
+
+ it "works for arbitrary Exception subclasses" do
+ class CustomException < Exception
+ attr_reader :custom_message
+
+ def initialize(custom_message)
+ @custom_message = custom_message
+ end
+ end
+
+ SafeYAML.whitelist!(CustomException)
+
+ ex = safe_load_round_trip(CustomException.new("blah"))
+ expect(ex).to be_a(CustomException)
+ expect(ex.custom_message).to eq("blah")
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/spec_helper.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/spec_helper.rb
new file mode 100644
index 0000000..967b2d3
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/spec_helper.rb
@@ -0,0 +1,42 @@
+HERE = File.dirname(__FILE__) unless defined?(HERE)
+ROOT = File.join(HERE, "..") unless defined?(ROOT)
+
+$LOAD_PATH << File.join(ROOT, "lib")
+$LOAD_PATH << File.join(HERE, "support")
+
+require "yaml"
+if ENV["YAMLER"] && defined?(YAML::ENGINE)
+ YAML::ENGINE.yamler = ENV["YAMLER"]
+end
+
+ruby_version = defined?(JRUBY_VERSION) ? "JRuby #{JRUBY_VERSION} in #{RUBY_VERSION} mode" : "Ruby #{RUBY_VERSION}"
+yaml_engine = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : "syck"
+libyaml_version = yaml_engine == "psych" && Psych.const_defined?("LIBYAML_VERSION", false) ? Psych::LIBYAML_VERSION : "N/A"
+
+env_info = [
+ ruby_version,
+ "YAML: #{yaml_engine} (#{YAML::VERSION}) (libyaml: #{libyaml_version})",
+ "Monkeypatch: #{ENV['MONKEYPATCH_YAML']}"
+]
+
+puts env_info.join(", ")
+
+# Caching references to these methods before loading safe_yaml in order to test
+# that they aren't touched unless you actually require safe_yaml (see yaml_spec.rb).
+ORIGINAL_YAML_LOAD = YAML.method(:load)
+ORIGINAL_YAML_LOAD_FILE = YAML.method(:load_file)
+
+require "safe_yaml/load"
+require "ostruct"
+require "hashie"
+require "heredoc_unindent"
+
+# Stolen from Rails:
+# https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L10-25
+def silence_warnings
+ $VERBOSE = nil; yield
+ensure
+ $VERBOSE = true
+end
+
+require File.join(HERE, "resolver_specs")
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/store_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/store_spec.rb
new file mode 100644
index 0000000..aafcfd4
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/store_spec.rb
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+require 'safe_yaml/store'
+
+describe SafeYAML::Store do
+
+ let(:file) { 'spec/store.yaml' }
+ let(:content) { "--- \nfoo: 42\n:bar: \"party\"\n" }
+
+ before do
+ # Rewrite file on every test, as its contents are potentially modified by
+ # SafeYAML::Store#transaction
+ File.open(file, 'w') { |f| f.write(content) }
+ end
+
+ def expect_safe_load(options = {})
+ load_args = [content, options]
+ load_args.insert(1, nil) if SafeYAML::YAML_ENGINE == 'psych'
+
+ expect(SafeYAML).to receive(:load).with(*load_args).and_call_original
+ expect(YAML).not_to receive(:load)
+ end
+
+ let(:init_args) { [file] }
+ subject { described_class.new(*init_args) }
+
+ it 'should be a YAML::Store' do
+ expect(subject).to be_a(YAML::Store)
+ end
+
+ it 'should be a SafeYAML::Store' do
+ expect(subject).to be_a(SafeYAML::Store)
+ end
+
+ it 'should use SafeYAML.load instead of YAML.load' do
+ expect_safe_load
+ expect(subject.transaction { subject['foo'] }).to eq(42)
+ end
+
+ it 'preserves default SafeYAML behavior' do
+ expect(subject.transaction { subject[:bar] }).to eq(nil)
+ expect(subject.transaction { subject[':bar'] }).to eq('party')
+ end
+
+
+ describe 'with options' do
+
+ let(:init_args) { super().insert(2, :deserialize_symbols => true) }
+
+ it 'should accept options for SafeYAML.load' do
+ expect_safe_load(:deserialize_symbols => true)
+ expect(subject.transaction { subject[:bar] }).to eq('party')
+ end
+
+ end
+
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/support/exploitable_back_door.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/support/exploitable_back_door.rb
new file mode 100644
index 0000000..48754b4
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/support/exploitable_back_door.rb
@@ -0,0 +1,29 @@
+class ExploitableBackDoor
+ def exploited?
+ @exploited_through_setter || @exploited_through_init_with || @exploited_through_ivars
+ end
+
+ def exploited_through_setter?
+ @exploited_through_setter
+ end
+
+ def exploited_through_init_with?
+ @exploited_through_init_with
+ end
+
+ def exploited_through_ivars?
+ self.instance_variables.any?
+ end
+
+ def init_with(command)
+ # Note: this is how bad this COULD be.
+ # system("#{command}")
+ @exploited_through_init_with = true
+ end
+
+ def []=(command, arguments)
+ # Note: this is how bad this COULD be.
+ # system("#{command} #{arguments}")
+ @exploited_through_setter = true
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/syck_resolver_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/syck_resolver_spec.rb
new file mode 100644
index 0000000..bec729b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/syck_resolver_spec.rb
@@ -0,0 +1,10 @@
+require "spec_helper"
+
+if SafeYAML::YAML_ENGINE == "syck"
+ require "safe_yaml/syck_resolver"
+
+ describe SafeYAML::SyckResolver do
+ include ResolverSpecs
+ let(:resolver) { SafeYAML::SyckResolver.new }
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/base64_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/base64_spec.rb
new file mode 100644
index 0000000..f4d83d0
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/base64_spec.rb
@@ -0,0 +1,11 @@
+require "spec_helper"
+
+describe SafeYAML::Transform do
+ it "should return the same encoding when decoding Base64" do
+ value = "c3VyZS4="
+ decoded = SafeYAML::Transform.to_proper_type(value, false, "!binary")
+
+ expect(decoded).to eq("sure.")
+ expect(decoded.encoding).to eq(value.encoding) if decoded.respond_to?(:encoding)
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_date_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_date_spec.rb
new file mode 100644
index 0000000..31bdb41
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_date_spec.rb
@@ -0,0 +1,60 @@
+require "spec_helper"
+
+describe SafeYAML::Transform::ToDate do
+ it "returns true when the value matches a valid Date" do
+ expect(subject.transform?("2013-01-01")).to eq([true, Date.parse("2013-01-01")])
+ end
+
+ it "returns false when the value does not match a valid Date" do
+ expect(subject.transform?("foobar")).to be_falsey
+ end
+
+ it "returns false when the value does not end with a Date" do
+ expect(subject.transform?("2013-01-01\nNOT A DATE")).to be_falsey
+ end
+
+ it "returns false when the value does not begin with a Date" do
+ expect(subject.transform?("NOT A DATE\n2013-01-01")).to be_falsey
+ end
+
+ it "correctly parses the remaining formats of the YAML spec" do
+ equivalent_values = [
+ "2001-12-15T02:59:43.1Z", # canonical
+ "2001-12-14t21:59:43.10-05:00", # iso8601
+ "2001-12-14 21:59:43.10 -5", # space separated
+ "2001-12-15 2:59:43.10" # no time zone (Z)
+ ]
+
+ equivalent_values.each do |value|
+ success, result = subject.transform?(value)
+ expect(success).to be_truthy
+ expect(result).to eq(Time.utc(2001, 12, 15, 2, 59, 43, 100000))
+ end
+ end
+
+ it "converts times to the local timezone" do
+ success, result = subject.transform?("2012-12-01 10:33:45 +11:00")
+ expect(success).to be_truthy
+ expect(result).to eq(Time.utc(2012, 11, 30, 23, 33, 45))
+ expect(result.gmt_offset).to eq(Time.local(2012, 11, 30).gmt_offset)
+ end
+
+ it "returns strings for invalid dates" do
+ expect(subject.transform?("0000-00-00")).to eq([true, "0000-00-00"])
+ expect(subject.transform?("2013-13-01")).to eq([true, "2013-13-01"])
+ expect(subject.transform?("2014-01-32")).to eq([true, "2014-01-32"])
+ end
+
+ it "returns strings for invalid date/times" do
+ expect(subject.transform?("0000-00-00 00:00:00 -0000")).to eq([true, "0000-00-00 00:00:00 -0000"])
+ expect(subject.transform?("2013-13-01 21:59:43 -05:00")).to eq([true, "2013-13-01 21:59:43 -05:00"])
+ expect(subject.transform?("2013-01-32 21:59:43 -05:00")).to eq([true, "2013-01-32 21:59:43 -05:00"])
+ expect(subject.transform?("2013-01-30 25:59:43 -05:00")).to eq([true, "2013-01-30 25:59:43 -05:00"])
+ expect(subject.transform?("2013-01-30 21:69:43 -05:00")).to eq([true, "2013-01-30 21:69:43 -05:00"])
+
+ # Interesting. It seems that in some older Ruby versions, the below actually parses successfully
+ # w/ DateTime.parse; but it fails w/ YAML.load. Whom to follow???
+
+ # subject.transform?("2013-01-30 21:59:63 -05:00").should == [true, "2013-01-30 21:59:63 -05:00"]
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_float_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_float_spec.rb
new file mode 100644
index 0000000..d4d813f
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_float_spec.rb
@@ -0,0 +1,42 @@
+require "spec_helper"
+
+describe SafeYAML::Transform::ToFloat do
+ it "returns true when the value matches a valid Float" do
+ expect(subject.transform?("20.00")).to eq([true, 20.0])
+ end
+
+ it "returns false when the value does not match a valid Float" do
+ expect(subject.transform?("foobar")).to be_falsey
+ end
+
+ it "returns false when the value spans multiple lines" do
+ expect(subject.transform?("20.00\nNOT A FLOAT")).to be_falsey
+ end
+
+ it "correctly parses all formats in the YAML spec" do
+ # canonical
+ expect(subject.transform?("6.8523015e+5")).to eq([true, 685230.15])
+
+ # exponentioal
+ expect(subject.transform?("685.230_15e+03")).to eq([true, 685230.15])
+
+ # fixed
+ expect(subject.transform?("685_230.15")).to eq([true, 685230.15])
+
+ # sexagesimal
+ expect(subject.transform?("190:20:30.15")).to eq([true, 685230.15])
+
+ # infinity
+ expect(subject.transform?("-.inf")).to eq([true, (-1.0 / 0.0)])
+
+ # not a number
+ # NOTE: can't use == here since NaN != NaN
+ success, result = subject.transform?(".NaN")
+ expect(success).to be_truthy; expect(result).to be_nan
+ end
+
+ # issue 29
+ it "returns false for the string '.'" do
+ expect(subject.transform?(".")).to be_falsey
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_integer_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_integer_spec.rb
new file mode 100644
index 0000000..6c6723b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_integer_spec.rb
@@ -0,0 +1,64 @@
+require "spec_helper"
+
+describe SafeYAML::Transform::ToInteger do
+ it "returns true when the value matches a valid Integer" do
+ expect(subject.transform?("10")).to eq([true, 10])
+ end
+
+ it "returns false when the value does not match a valid Integer" do
+ expect(subject.transform?("foobar")).to be_falsey
+ end
+
+ it "returns false when the value spans multiple lines" do
+ expect(subject.transform?("10\nNOT AN INTEGER")).to be_falsey
+ end
+
+ it "allows commas in the number" do
+ expect(subject.transform?("1,000")).to eq([true, 1000])
+ end
+
+ it "correctly parses numbers in octal format" do
+ expect(subject.transform?("010")).to eq([true, 8])
+ end
+
+ it "correctly parses numbers in hexadecimal format" do
+ expect(subject.transform?("0x1FF")).to eq([true, 511])
+ end
+
+ it "defaults to a string for a number that resembles octal format but is not" do
+ expect(subject.transform?("09")).to be_falsey
+ end
+
+ it "correctly parses 0 in decimal" do
+ expect(subject.transform?("0")).to eq([true, 0])
+ end
+
+ it "defaults to a string for a number that resembles hexadecimal format but is not" do
+ expect(subject.transform?("0x1G")).to be_falsey
+ end
+
+ it "correctly parses all formats in the YAML spec" do
+ # canonical
+ expect(subject.transform?("685230")).to eq([true, 685230])
+
+ # decimal
+ expect(subject.transform?("+685_230")).to eq([true, 685230])
+
+ # octal
+ expect(subject.transform?("02472256")).to eq([true, 685230])
+
+ # hexadecimal:
+ expect(subject.transform?("0x_0A_74_AE")).to eq([true, 685230])
+
+ # binary
+ expect(subject.transform?("0b1010_0111_0100_1010_1110")).to eq([true, 685230])
+
+ # sexagesimal
+ expect(subject.transform?("190:20:30")).to eq([true, 685230])
+ end
+
+ # see https://github.com/dtao/safe_yaml/pull/51
+ it "strips out underscores before parsing decimal values" do
+ expect(subject.transform?("_850_")).to eq([true, 850])
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_symbol_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_symbol_spec.rb
new file mode 100644
index 0000000..59cd242
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/transform/to_symbol_spec.rb
@@ -0,0 +1,51 @@
+require "spec_helper"
+
+describe SafeYAML::Transform::ToSymbol do
+ def with_symbol_deserialization_value(value)
+ symbol_deserialization_flag = SafeYAML::OPTIONS[:deserialize_symbols]
+ SafeYAML::OPTIONS[:deserialize_symbols] = value
+
+ yield
+
+ ensure
+ SafeYAML::OPTIONS[:deserialize_symbols] = symbol_deserialization_flag
+ end
+
+ def with_symbol_deserialization(&block)
+ with_symbol_deserialization_value(true, &block)
+ end
+
+ def without_symbol_deserialization(&block)
+ with_symbol_deserialization_value(false, &block)
+ end
+
+ it "returns true when the value matches a valid Symbol" do
+ with_symbol_deserialization { expect(subject.transform?(":foo")[0]).to be_truthy }
+ end
+
+ it "returns true when the value matches a valid String+Symbol" do
+ with_symbol_deserialization { expect(subject.transform?(':"foo"')[0]).to be_truthy }
+ end
+
+ it "returns true when the value matches a valid String+Symbol with 's" do
+ with_symbol_deserialization { expect(subject.transform?(":'foo'")[0]).to be_truthy }
+ end
+
+ it "returns true when the value has special characters and is wrapped in a String" do
+ with_symbol_deserialization { expect(subject.transform?(':"foo.bar"')[0]).to be_truthy }
+ end
+
+ it "returns false when symbol deserialization is disabled" do
+ without_symbol_deserialization { expect(subject.transform?(":foo")).to be_falsey }
+ end
+
+ it "returns false when the value does not match a valid Symbol" do
+ with_symbol_deserialization { expect(subject.transform?("foo")).to be_falsey }
+ end
+
+ it "returns false when the symbol does not begin the line" do
+ with_symbol_deserialization do
+ expect(subject.transform?("NOT A SYMBOL\n:foo")).to be_falsey
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/yaml_spec.rb b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/yaml_spec.rb
new file mode 100644
index 0000000..2c2bd18
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/safe_yaml-1.0.5/spec/yaml_spec.rb
@@ -0,0 +1,15 @@
+# See https://github.com/dtao/safe_yaml/issues/47
+
+require "spec_helper"
+
+describe YAML do
+ context "when you've only required safe_yaml/load", :libraries => true do
+ it "YAML.load doesn't get monkey patched" do
+ expect(YAML.method(:load)).to eq(ORIGINAL_YAML_LOAD)
+ end
+
+ it "YAML.load_file doesn't get monkey patched" do
+ expect(YAML.method(:load_file)).to eq(ORIGINAL_YAML_LOAD_FILE)
+ end
+ end
+end