safe_yaml 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +5 -2
- data/bundle_install_all_ruby_versions.sh +6 -16
- data/lib/safe_yaml/load.rb +1 -1
- data/lib/safe_yaml/resolver.rb +1 -1
- data/lib/safe_yaml/version.rb +1 -1
- data/run_specs_all_ruby_versions.sh +9 -0
- data/spec/libyaml_checker_spec.rb +2 -2
- data/spec/resolver_specs.rb +26 -26
- data/spec/safe_yaml_spec.rb +90 -90
- data/spec/spec_helper.rb +6 -6
- data/spec/transform/base64_spec.rb +2 -2
- data/spec/transform/to_date_spec.rb +17 -17
- data/spec/transform/to_float_spec.rb +10 -10
- data/spec/transform/to_integer_spec.rb +16 -16
- data/spec/transform/to_symbol_spec.rb +7 -7
- data/spec/yaml_spec.rb +2 -2
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbb2ac04a98ae5516c34c7dc2baf6348304c6e17
|
4
|
+
data.tar.gz: 097dd3a02c37a63f7a899b8897839b3c60a82117
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93c0fd49c34c71dfcb0cb76d127aa52e9178a6cf6d9b8a6a94728b1ea336c956c228cc71bbefa4790fe31d35229b0e9783e930f7a97ec69053dcfdd4441571cb
|
7
|
+
data.tar.gz: 5d068fabdc5b89a544958e0a139a82bcc40c38828840f6a9d02baca82e3b574868397fa45b74042320ea403f13388ebd2db32164eef4df97f261475049f4f86f
|
data/Rakefile
CHANGED
@@ -6,18 +6,21 @@ task :spec => ['spec:app', 'spec:lib']
|
|
6
6
|
namespace :spec do
|
7
7
|
desc "Run only specs tagged 'solo'"
|
8
8
|
RSpec::Core::RakeTask.new(:solo) do |t|
|
9
|
+
t.verbose = false
|
9
10
|
t.rspec_opts = %w(--color --tag solo)
|
10
11
|
end
|
11
12
|
|
12
13
|
desc "Run only specs tagged NOT tagged 'libraries' (for applications)"
|
13
14
|
RSpec::Core::RakeTask.new(:app) do |t|
|
14
|
-
|
15
|
+
t.verbose = false
|
16
|
+
ENV["MONKEYPATCH_YAML"] = "true"
|
15
17
|
t.rspec_opts = %w(--color --tag ~libraries)
|
16
18
|
end
|
17
19
|
|
18
20
|
desc "Run only specs tagged 'libraries'"
|
19
21
|
RSpec::Core::RakeTask.new(:lib) do |t|
|
20
|
-
|
22
|
+
t.verbose = false
|
23
|
+
ENV["MONKEYPATCH_YAML"] = "false"
|
21
24
|
t.rspec_opts = %w(--color --tag libraries)
|
22
25
|
end
|
23
26
|
end
|
@@ -2,20 +2,10 @@
|
|
2
2
|
|
3
3
|
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"
|
4
4
|
|
5
|
-
|
6
|
-
bundle install
|
5
|
+
declare -a versions=("1.8.7" "1.9.2" "1.9.3" "2.0.0" "2.1.0" "2.1.1" "2.1.2" "ruby-head" "jruby")
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
rvm use 2.0.0
|
15
|
-
bundle install
|
16
|
-
|
17
|
-
rvm use ruby-head
|
18
|
-
bundle install
|
19
|
-
|
20
|
-
rvm use jruby
|
21
|
-
bundle install
|
7
|
+
for i in "${versions[@]}"
|
8
|
+
do
|
9
|
+
rvm use $i
|
10
|
+
bundle install
|
11
|
+
done
|
data/lib/safe_yaml/load.rb
CHANGED
@@ -4,7 +4,7 @@ require "yaml"
|
|
4
4
|
# This needs to be defined up front in case any internal classes need to base
|
5
5
|
# their behavior off of this.
|
6
6
|
module SafeYAML
|
7
|
-
YAML_ENGINE = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : "syck"
|
7
|
+
YAML_ENGINE = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : (defined?(Psych) && YAML == Psych ? "psych" : "syck")
|
8
8
|
end
|
9
9
|
|
10
10
|
require "safe_yaml/libyaml_checker"
|
data/lib/safe_yaml/resolver.rb
CHANGED
@@ -52,7 +52,7 @@ module SafeYAML
|
|
52
52
|
tag = get_and_check_node_tag(node)
|
53
53
|
arr = @initializers.include?(tag) ? @initializers[tag].call : []
|
54
54
|
|
55
|
-
seq.inject(arr) { |array,
|
55
|
+
seq.inject(arr) { |array, n| array << resolve_node(n) }
|
56
56
|
end
|
57
57
|
|
58
58
|
def resolve_scalar(node)
|
data/lib/safe_yaml/version.rb
CHANGED
@@ -18,6 +18,15 @@ YAMLER=psych bundle exec rake spec
|
|
18
18
|
rvm use 2.0.0
|
19
19
|
bundle exec rake spec
|
20
20
|
|
21
|
+
rvm use 2.1.0
|
22
|
+
bundle exec rake spec
|
23
|
+
|
24
|
+
rvm use 2.1.1
|
25
|
+
bundle exec rake spec
|
26
|
+
|
27
|
+
rvm use 2.1.2
|
28
|
+
bundle exec rake spec
|
29
|
+
|
21
30
|
rvm use ruby-head
|
22
31
|
bundle exec rake spec
|
23
32
|
|
@@ -8,7 +8,7 @@ describe SafeYAML::LibyamlChecker do
|
|
8
8
|
let(:libyaml_patched) { false }
|
9
9
|
|
10
10
|
before :each do
|
11
|
-
SafeYAML::LibyamlChecker.
|
11
|
+
allow(SafeYAML::LibyamlChecker).to receive(:libyaml_patched?).and_return(libyaml_patched)
|
12
12
|
end
|
13
13
|
|
14
14
|
after :each do
|
@@ -22,7 +22,7 @@ describe SafeYAML::LibyamlChecker do
|
|
22
22
|
silence_warnings do
|
23
23
|
SafeYAML.const_set("YAML_ENGINE", yaml_engine)
|
24
24
|
SafeYAML::LibyamlChecker.const_set("LIBYAML_VERSION", libyaml_version)
|
25
|
-
SafeYAML::LibyamlChecker.libyaml_version_ok
|
25
|
+
expect(SafeYAML::LibyamlChecker.libyaml_version_ok?).to eq(expected_result)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
data/spec/resolver_specs.rb
CHANGED
@@ -39,7 +39,7 @@ module ResolverSpecs
|
|
39
39
|
Kernel.warn "#{exception_thrown.inspect}\n"
|
40
40
|
|
41
41
|
else
|
42
|
-
safe_result.
|
42
|
+
expect(safe_result).to eq(unsafe_result)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -50,10 +50,10 @@ module ResolverSpecs
|
|
50
50
|
tomayto: tomahto
|
51
51
|
YAML
|
52
52
|
|
53
|
-
result.
|
53
|
+
expect(result).to eq({
|
54
54
|
"potayto" => "potahto",
|
55
55
|
"tomayto" => "tomahto"
|
56
|
-
}
|
56
|
+
})
|
57
57
|
end
|
58
58
|
|
59
59
|
it "translates sequences to arrays" do
|
@@ -63,32 +63,32 @@ module ResolverSpecs
|
|
63
63
|
- baz
|
64
64
|
YAML
|
65
65
|
|
66
|
-
result.
|
66
|
+
expect(result).to eq(["foo", "bar", "baz"])
|
67
67
|
end
|
68
68
|
|
69
69
|
it "translates most values to strings" do
|
70
70
|
parse "string: value"
|
71
|
-
result.
|
71
|
+
expect(result).to eq({ "string" => "value" })
|
72
72
|
end
|
73
73
|
|
74
74
|
it "does not deserialize symbols" do
|
75
75
|
parse ":symbol: value"
|
76
|
-
result.
|
76
|
+
expect(result).to eq({ ":symbol" => "value" })
|
77
77
|
end
|
78
78
|
|
79
79
|
it "translates valid integral numbers to integers" do
|
80
80
|
parse "integer: 1"
|
81
|
-
result.
|
81
|
+
expect(result).to eq({ "integer" => 1 })
|
82
82
|
end
|
83
83
|
|
84
84
|
it "translates valid decimal numbers to floats" do
|
85
85
|
parse "float: 3.14"
|
86
|
-
result.
|
86
|
+
expect(result).to eq({ "float" => 3.14 })
|
87
87
|
end
|
88
88
|
|
89
89
|
it "translates valid dates" do
|
90
90
|
parse "date: 2013-01-24"
|
91
|
-
result.
|
91
|
+
expect(result).to eq({ "date" => Date.parse("2013-01-24") })
|
92
92
|
end
|
93
93
|
|
94
94
|
it "translates valid true/false values to booleans" do
|
@@ -99,7 +99,7 @@ module ResolverSpecs
|
|
99
99
|
- false
|
100
100
|
YAML
|
101
101
|
|
102
|
-
result.
|
102
|
+
expect(result).to eq([true, true, false, false])
|
103
103
|
end
|
104
104
|
|
105
105
|
it "translates valid nulls to nil" do
|
@@ -109,7 +109,7 @@ module ResolverSpecs
|
|
109
109
|
- null
|
110
110
|
YAML
|
111
111
|
|
112
|
-
result.
|
112
|
+
expect(result).to eq([nil] * 3)
|
113
113
|
end
|
114
114
|
|
115
115
|
it "matches the behavior of the underlying YAML engine w/ respect to capitalization of boolean values" do
|
@@ -143,12 +143,12 @@ module ResolverSpecs
|
|
143
143
|
|
144
144
|
it "translates quoted empty strings to strings (not nil)" do
|
145
145
|
parse "foo: ''"
|
146
|
-
result.
|
146
|
+
expect(result).to eq({ "foo" => "" })
|
147
147
|
end
|
148
148
|
|
149
149
|
it "correctly reverse-translates strings encoded via #to_yaml" do
|
150
150
|
parse "5.10".to_yaml
|
151
|
-
result.
|
151
|
+
expect(result).to eq("5.10")
|
152
152
|
end
|
153
153
|
|
154
154
|
it "does not specially parse any double-quoted strings" do
|
@@ -161,7 +161,7 @@ module ResolverSpecs
|
|
161
161
|
- "2013-02-03 16:27:00 -0600"
|
162
162
|
YAML
|
163
163
|
|
164
|
-
result.
|
164
|
+
expect(result).to eq(["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"])
|
165
165
|
end
|
166
166
|
|
167
167
|
it "does not specially parse any single-quoted strings" do
|
@@ -174,7 +174,7 @@ module ResolverSpecs
|
|
174
174
|
- '2013-02-03 16:27:00 -0600'
|
175
175
|
YAML
|
176
176
|
|
177
|
-
result.
|
177
|
+
expect(result).to eq(["1", "3.14", "true", "false", "2013-02-03", "2013-02-03 16:27:00 -0600"])
|
178
178
|
end
|
179
179
|
|
180
180
|
it "deals just fine with nested maps" do
|
@@ -184,7 +184,7 @@ module ResolverSpecs
|
|
184
184
|
marco: polo
|
185
185
|
YAML
|
186
186
|
|
187
|
-
result.
|
187
|
+
expect(result).to eq({ "foo" => { "bar" => { "marco" => "polo" } } })
|
188
188
|
end
|
189
189
|
|
190
190
|
it "deals just fine with nested sequences" do
|
@@ -198,7 +198,7 @@ module ResolverSpecs
|
|
198
198
|
- baz2
|
199
199
|
YAML
|
200
200
|
|
201
|
-
result.
|
201
|
+
expect(result).to eq(["foo", ["bar1", "bar2", ["baz1", "baz2"]]])
|
202
202
|
end
|
203
203
|
|
204
204
|
it "applies the same transformations to keys as to values" do
|
@@ -210,13 +210,13 @@ module ResolverSpecs
|
|
210
210
|
2013-01-24: date
|
211
211
|
YAML
|
212
212
|
|
213
|
-
result.
|
213
|
+
expect(result).to eq({
|
214
214
|
"foo" => "string",
|
215
215
|
":bar" => "symbol",
|
216
216
|
1 => "integer",
|
217
217
|
3.14 => "float",
|
218
218
|
Date.parse("2013-01-24") => "date",
|
219
|
-
}
|
219
|
+
})
|
220
220
|
end
|
221
221
|
|
222
222
|
it "applies the same transformations to elements in sequences as to all values" do
|
@@ -228,24 +228,24 @@ module ResolverSpecs
|
|
228
228
|
- 2013-01-24
|
229
229
|
YAML
|
230
230
|
|
231
|
-
result.
|
231
|
+
expect(result).to eq(["foo", ":bar", 1, 3.14, Date.parse("2013-01-24")])
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
235
|
context "for Ruby version #{RUBY_VERSION}" do
|
236
236
|
it "translates valid time values" do
|
237
237
|
parse "time: 2013-01-29 05:58:00 -0800"
|
238
|
-
result.
|
238
|
+
expect(result).to eq({ "time" => Time.utc(2013, 1, 29, 13, 58, 0) })
|
239
239
|
end
|
240
240
|
|
241
241
|
it "applies the same transformation to elements in sequences" do
|
242
242
|
parse "- 2013-01-29 05:58:00 -0800"
|
243
|
-
result.
|
243
|
+
expect(result).to eq([Time.utc(2013, 1, 29, 13, 58, 0)])
|
244
244
|
end
|
245
245
|
|
246
246
|
it "applies the same transformation to keys" do
|
247
247
|
parse "2013-01-29 05:58:00 -0800: time"
|
248
|
-
result.
|
248
|
+
expect(result).to eq({ Time.utc(2013, 1, 29, 13, 58, 0) => "time" })
|
249
249
|
end
|
250
250
|
end
|
251
251
|
|
@@ -260,17 +260,17 @@ module ResolverSpecs
|
|
260
260
|
|
261
261
|
it "translates values starting with ':' to symbols" do
|
262
262
|
parse "symbol: :value"
|
263
|
-
result.
|
263
|
+
expect(result).to eq({ "symbol" => :value })
|
264
264
|
end
|
265
265
|
|
266
266
|
it "applies the same transformation to keys" do
|
267
267
|
parse ":bar: symbol"
|
268
|
-
result.
|
268
|
+
expect(result).to eq({ :bar => "symbol" })
|
269
269
|
end
|
270
270
|
|
271
271
|
it "applies the same transformation to elements in sequences" do
|
272
272
|
parse "- :bar"
|
273
|
-
result.
|
273
|
+
expect(result).to eq([:bar])
|
274
274
|
end
|
275
275
|
end
|
276
276
|
end
|
data/spec/safe_yaml_spec.rb
CHANGED
@@ -28,18 +28,18 @@ describe YAML do
|
|
28
28
|
if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3"
|
29
29
|
it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do
|
30
30
|
backdoor = YAML.unsafe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
|
31
|
-
backdoor.
|
31
|
+
expect(backdoor).to be_exploited_through_setter
|
32
32
|
end
|
33
33
|
|
34
34
|
it "allows exploits through objects defined in YAML w/ !ruby/object via the :init_with method" do
|
35
35
|
backdoor = YAML.unsafe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
|
36
|
-
backdoor.
|
36
|
+
expect(backdoor).to be_exploited_through_init_with
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do
|
41
41
|
backdoor = YAML.unsafe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
|
42
|
-
backdoor.
|
42
|
+
expect(backdoor).to be_exploited_through_ivars
|
43
43
|
end
|
44
44
|
|
45
45
|
context "with special whitelisted tags defined" do
|
@@ -55,8 +55,8 @@ describe YAML do
|
|
55
55
|
foo: bar
|
56
56
|
YAML
|
57
57
|
|
58
|
-
result.
|
59
|
-
result.backdoor.
|
58
|
+
expect(result).to be_a(OpenStruct)
|
59
|
+
expect(result.backdoor).to be_exploited_through_ivars
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -64,12 +64,12 @@ describe YAML do
|
|
64
64
|
describe "safe_load" do
|
65
65
|
it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do
|
66
66
|
object = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
|
67
|
-
object.
|
67
|
+
expect(object).not_to be_a(ExploitableBackDoor)
|
68
68
|
end
|
69
69
|
|
70
70
|
it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do
|
71
71
|
object = YAML.safe_load("--- !ruby/object:ExploitableBackDoor\nfoo: bar\n")
|
72
|
-
object.
|
72
|
+
expect(object).not_to be_a(ExploitableBackDoor)
|
73
73
|
end
|
74
74
|
|
75
75
|
context "for YAML engine #{SafeYAML::YAML_ENGINE}" do
|
@@ -79,7 +79,7 @@ describe YAML do
|
|
79
79
|
|
80
80
|
context "when no tags are whitelisted" do
|
81
81
|
it "constructs a SafeYAML::PsychHandler to resolve nodes as they're parsed, for optimal performance" do
|
82
|
-
Psych::Parser.
|
82
|
+
expect(Psych::Parser).to receive(:new).with an_instance_of(SafeYAML::PsychHandler)
|
83
83
|
# This won't work now; we just want to ensure Psych::Parser#parse was in fact called.
|
84
84
|
YAML.safe_load(*arguments) rescue nil
|
85
85
|
end
|
@@ -91,7 +91,7 @@ describe YAML do
|
|
91
91
|
}
|
92
92
|
|
93
93
|
it "instead uses Psych to construct a full tree before examining the nodes" do
|
94
|
-
Psych.
|
94
|
+
expect(Psych).to receive(:parse)
|
95
95
|
# This won't work now; we just want to ensure Psych::Parser#parse was in fact called.
|
96
96
|
YAML.safe_load(*arguments) rescue nil
|
97
97
|
end
|
@@ -100,7 +100,7 @@ describe YAML do
|
|
100
100
|
|
101
101
|
if SafeYAML::YAML_ENGINE == "syck"
|
102
102
|
it "uses Syck internally to parse YAML" do
|
103
|
-
YAML.
|
103
|
+
expect(YAML).to receive(:parse).with("foo: bar")
|
104
104
|
# This won't work now; we just want to ensure YAML::parse was in fact called.
|
105
105
|
YAML.safe_load("foo: bar") rescue nil
|
106
106
|
end
|
@@ -120,7 +120,7 @@ describe YAML do
|
|
120
120
|
- bye
|
121
121
|
YAML
|
122
122
|
|
123
|
-
result.
|
123
|
+
expect(result).to eq({
|
124
124
|
"foo" => {
|
125
125
|
"number" => 1,
|
126
126
|
"boolean" => true,
|
@@ -129,7 +129,7 @@ describe YAML do
|
|
129
129
|
"symbol" => ":blah",
|
130
130
|
"sequence" => ["hi", "bye"]
|
131
131
|
}
|
132
|
-
}
|
132
|
+
})
|
133
133
|
end
|
134
134
|
|
135
135
|
it "works for YAML documents with anchors and aliases" do
|
@@ -139,7 +139,7 @@ describe YAML do
|
|
139
139
|
- *id001
|
140
140
|
YAML
|
141
141
|
|
142
|
-
result.
|
142
|
+
expect(result).to eq([{}, {}, {}])
|
143
143
|
end
|
144
144
|
|
145
145
|
it "works for YAML documents with binary tagged keys" do
|
@@ -152,7 +152,7 @@ describe YAML do
|
|
152
152
|
: "baz"
|
153
153
|
YAML
|
154
154
|
|
155
|
-
result.
|
155
|
+
expect(result).to eq({"foo" => "bar", "bar" => "baz"})
|
156
156
|
end
|
157
157
|
|
158
158
|
it "works for YAML documents with binary tagged values" do
|
@@ -163,7 +163,7 @@ describe YAML do
|
|
163
163
|
YmF6
|
164
164
|
YAML
|
165
165
|
|
166
|
-
result.
|
166
|
+
expect(result).to eq({"foo" => "bar", "bar" => "baz"})
|
167
167
|
end
|
168
168
|
|
169
169
|
it "works for YAML documents with binary tagged array values" do
|
@@ -174,7 +174,7 @@ describe YAML do
|
|
174
174
|
YmFy
|
175
175
|
YAML
|
176
176
|
|
177
|
-
result.
|
177
|
+
expect(result).to eq(["foo", "bar"])
|
178
178
|
end
|
179
179
|
|
180
180
|
it "works for YAML documents with sections" do
|
@@ -191,7 +191,7 @@ describe YAML do
|
|
191
191
|
host: localhost
|
192
192
|
YAML
|
193
193
|
|
194
|
-
result.
|
194
|
+
expect(result).to eq({
|
195
195
|
"mysql" => {
|
196
196
|
"adapter" => "mysql",
|
197
197
|
"pool" => 30
|
@@ -207,7 +207,7 @@ describe YAML do
|
|
207
207
|
"password" => "password123",
|
208
208
|
"host" => "localhost"
|
209
209
|
}
|
210
|
-
}
|
210
|
+
})
|
211
211
|
end
|
212
212
|
|
213
213
|
it "correctly prefers explicitly defined values over default values from included sections" do
|
@@ -225,11 +225,11 @@ describe YAML do
|
|
225
225
|
baz: custom_baz
|
226
226
|
YAML
|
227
227
|
|
228
|
-
result["custom"].
|
228
|
+
expect(result["custom"]).to eq({
|
229
229
|
"foo" => "foo",
|
230
230
|
"bar" => "custom_bar",
|
231
231
|
"baz" => "custom_baz"
|
232
|
-
}
|
232
|
+
})
|
233
233
|
end
|
234
234
|
end
|
235
235
|
|
@@ -247,26 +247,26 @@ describe YAML do
|
|
247
247
|
<<: *custom
|
248
248
|
YAML
|
249
249
|
|
250
|
-
result.
|
250
|
+
expect(result).to eq({
|
251
251
|
"defaults" => { "foo" => "foo", "bar" => "bar", "baz" => "baz" },
|
252
252
|
"custom" => { "foo" => "foo", "bar" => "custom_bar", "baz" => "custom_baz" },
|
253
253
|
"grandcustom" => { "foo" => "foo", "bar" => "custom_bar", "baz" => "custom_baz" }
|
254
|
-
}
|
254
|
+
})
|
255
255
|
end
|
256
256
|
|
257
257
|
it "returns false when parsing an empty document" do
|
258
|
-
[
|
258
|
+
expect([
|
259
259
|
YAML.safe_load(""),
|
260
260
|
YAML.safe_load(" "),
|
261
261
|
YAML.safe_load("\n")
|
262
|
-
].
|
262
|
+
]).to eq([false, false, false])
|
263
263
|
end
|
264
264
|
|
265
265
|
it "returns nil when parsing a single value representing nil" do
|
266
|
-
[
|
266
|
+
expect([
|
267
267
|
YAML.safe_load("~"),
|
268
268
|
YAML.safe_load("null")
|
269
|
-
].
|
269
|
+
]).to eq([nil, nil])
|
270
270
|
end
|
271
271
|
|
272
272
|
context "with custom initializers defined" do
|
@@ -292,8 +292,8 @@ describe YAML do
|
|
292
292
|
- 3
|
293
293
|
YAML
|
294
294
|
|
295
|
-
result.
|
296
|
-
result.to_a.
|
295
|
+
expect(result).to be_a(Set)
|
296
|
+
expect(result.to_a).to match_array([1, 2, 3])
|
297
297
|
end
|
298
298
|
|
299
299
|
it "will use a custom initializer to instantiate a hash-like class upon deserialization" do
|
@@ -302,8 +302,8 @@ describe YAML do
|
|
302
302
|
foo: bar
|
303
303
|
YAML
|
304
304
|
|
305
|
-
result.
|
306
|
-
result.to_hash.
|
305
|
+
expect(result).to be_a(Hashie::Mash)
|
306
|
+
expect(result.to_hash).to eq({ "foo" => "bar" })
|
307
307
|
end
|
308
308
|
end
|
309
309
|
|
@@ -317,14 +317,14 @@ describe YAML do
|
|
317
317
|
|
318
318
|
it "will allow objects to be deserialized for whitelisted tags" do
|
319
319
|
result = YAML.safe_load("--- !ruby/object:OpenStruct\ntable:\n foo: bar\n")
|
320
|
-
result.
|
321
|
-
result.instance_variable_get(:@table).
|
320
|
+
expect(result).to be_a(OpenStruct)
|
321
|
+
expect(result.instance_variable_get(:@table)).to eq({ "foo" => "bar" })
|
322
322
|
end
|
323
323
|
|
324
324
|
it "will not deserialize objects without whitelisted tags" do
|
325
325
|
result = YAML.safe_load("--- !ruby/hash:ExploitableBackDoor\nfoo: bar\n")
|
326
|
-
result.
|
327
|
-
result.
|
326
|
+
expect(result).not_to be_a(ExploitableBackDoor)
|
327
|
+
expect(result).to eq({ "foo" => "bar" })
|
328
328
|
end
|
329
329
|
|
330
330
|
it "will not allow non-whitelisted objects to be embedded within objects with whitelisted tags" do
|
@@ -335,9 +335,9 @@ describe YAML do
|
|
335
335
|
foo: bar
|
336
336
|
YAML
|
337
337
|
|
338
|
-
result.
|
339
|
-
result.backdoor.
|
340
|
-
result.backdoor.
|
338
|
+
expect(result).to be_a(OpenStruct)
|
339
|
+
expect(result.backdoor).not_to be_a(ExploitableBackDoor)
|
340
|
+
expect(result.backdoor).to eq({ "foo" => "bar" })
|
341
341
|
end
|
342
342
|
|
343
343
|
context "with the :raise_on_unknown_tag option enabled" do
|
@@ -350,23 +350,23 @@ describe YAML do
|
|
350
350
|
end
|
351
351
|
|
352
352
|
it "raises an exception if a non-nil, non-whitelisted tag is encountered" do
|
353
|
-
|
353
|
+
expect {
|
354
354
|
YAML.safe_load <<-YAML.unindent
|
355
355
|
--- !ruby/object:Unknown
|
356
356
|
foo: bar
|
357
357
|
YAML
|
358
|
-
}.
|
358
|
+
}.to raise_error
|
359
359
|
end
|
360
360
|
|
361
361
|
it "checks all tags, even those within objects with trusted tags" do
|
362
|
-
|
362
|
+
expect {
|
363
363
|
YAML.safe_load <<-YAML.unindent
|
364
364
|
--- !ruby/object:OpenStruct
|
365
365
|
table:
|
366
366
|
:backdoor: !ruby/object:Unknown
|
367
367
|
foo: bar
|
368
368
|
YAML
|
369
|
-
}.
|
369
|
+
}.to raise_error
|
370
370
|
end
|
371
371
|
|
372
372
|
it "does not raise an exception as long as all tags are whitelisted" do
|
@@ -383,8 +383,8 @@ describe YAML do
|
|
383
383
|
hash: {}
|
384
384
|
YAML
|
385
385
|
|
386
|
-
result.
|
387
|
-
result.backdoor.
|
386
|
+
expect(result).to be_a(OpenStruct)
|
387
|
+
expect(result.backdoor).to eq({
|
388
388
|
"string" => "foo",
|
389
389
|
"integer" => 1,
|
390
390
|
"float" => 3.14,
|
@@ -392,13 +392,13 @@ describe YAML do
|
|
392
392
|
"date" => Date.parse("2013-02-20"),
|
393
393
|
"array" => [],
|
394
394
|
"hash" => {}
|
395
|
-
}
|
395
|
+
})
|
396
396
|
end
|
397
397
|
|
398
398
|
it "does not raise an exception on the non-specific '!' tag" do
|
399
399
|
result = nil
|
400
400
|
expect { result = YAML.safe_load "--- ! 'foo'" }.to_not raise_error
|
401
|
-
result.
|
401
|
+
expect(result).to eq("foo")
|
402
402
|
end
|
403
403
|
|
404
404
|
context "with whitelisted custom class" do
|
@@ -415,7 +415,7 @@ describe YAML do
|
|
415
415
|
it "does not raise an exception on the non-specific '!' tag" do
|
416
416
|
result = nil
|
417
417
|
expect { result = YAML.safe_load(instance.to_yaml) }.to_not raise_error
|
418
|
-
result.foo.
|
418
|
+
expect(result.foo).to eq('with trailing whitespace: ')
|
419
419
|
end
|
420
420
|
end
|
421
421
|
end
|
@@ -433,14 +433,14 @@ describe YAML do
|
|
433
433
|
|
434
434
|
it "goes with the default option when it is not overridden" do
|
435
435
|
silence_warnings do
|
436
|
-
YAML.load(":foo: bar").
|
436
|
+
expect(YAML.load(":foo: bar")).to eq({ :foo => "bar" })
|
437
437
|
end
|
438
438
|
end
|
439
439
|
|
440
440
|
it "allows the default option to be overridden on a per-call basis" do
|
441
441
|
silence_warnings do
|
442
|
-
YAML.load(":foo: bar", :deserialize_symbols => false).
|
443
|
-
YAML.load(":foo: bar", :deserialize_symbols => true).
|
442
|
+
expect(YAML.load(":foo: bar", :deserialize_symbols => false)).to eq({ ":foo" => "bar" })
|
443
|
+
expect(YAML.load(":foo: bar", :deserialize_symbols => true)).to eq({ :foo => "bar" })
|
444
444
|
end
|
445
445
|
end
|
446
446
|
end
|
@@ -457,16 +457,16 @@ describe YAML do
|
|
457
457
|
|
458
458
|
it "goes with the default option when it is not overridden" do
|
459
459
|
result = safe_load_round_trip(OpenStruct.new(:foo => "bar"))
|
460
|
-
result.
|
461
|
-
result.foo.
|
460
|
+
expect(result).to be_a(OpenStruct)
|
461
|
+
expect(result.foo).to eq("bar")
|
462
462
|
end
|
463
463
|
|
464
464
|
it "allows the default option to be overridden on a per-call basis" do
|
465
465
|
result = safe_load_round_trip(OpenStruct.new(:foo => "bar"), :whitelisted_tags => [])
|
466
|
-
result.
|
466
|
+
expect(result).to eq({ "table" => { :foo => "bar" } })
|
467
467
|
|
468
468
|
result = safe_load_round_trip(OpenStruct.new(:foo => "bar"), :deserialize_symbols => false, :whitelisted_tags => [])
|
469
|
-
result.
|
469
|
+
expect(result).to eq({ "table" => { ":foo" => "bar" } })
|
470
470
|
end
|
471
471
|
end
|
472
472
|
end
|
@@ -476,36 +476,36 @@ describe YAML do
|
|
476
476
|
if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.3"
|
477
477
|
it "allows exploits through objects defined in YAML w/ !ruby/hash via custom :[]= methods" do
|
478
478
|
backdoor = YAML.unsafe_load_file "spec/exploit.1.9.3.yaml"
|
479
|
-
backdoor.
|
479
|
+
expect(backdoor).to be_exploited_through_setter
|
480
480
|
end
|
481
481
|
end
|
482
482
|
|
483
483
|
if SafeYAML::YAML_ENGINE == "psych" && RUBY_VERSION >= "1.9.2"
|
484
484
|
it "allows exploits through objects defined in YAML w/ !ruby/object via the :init_with method" do
|
485
485
|
backdoor = YAML.unsafe_load_file "spec/exploit.1.9.2.yaml"
|
486
|
-
backdoor.
|
486
|
+
expect(backdoor).to be_exploited_through_init_with
|
487
487
|
end
|
488
488
|
end
|
489
489
|
|
490
490
|
it "allows exploits through objects w/ sensitive instance variables defined in YAML w/ !ruby/object" do
|
491
491
|
backdoor = YAML.unsafe_load_file "spec/exploit.1.9.2.yaml"
|
492
|
-
backdoor.
|
492
|
+
expect(backdoor).to be_exploited_through_ivars
|
493
493
|
end
|
494
494
|
end
|
495
495
|
|
496
496
|
describe "safe_load_file" do
|
497
497
|
it "does NOT allow exploits through objects defined in YAML w/ !ruby/hash" do
|
498
498
|
object = YAML.safe_load_file "spec/exploit.1.9.3.yaml"
|
499
|
-
object.
|
499
|
+
expect(object).not_to be_a(ExploitableBackDoor)
|
500
500
|
end
|
501
501
|
|
502
502
|
it "does NOT allow exploits through objects defined in YAML w/ !ruby/object" do
|
503
503
|
object = YAML.safe_load_file "spec/exploit.1.9.2.yaml"
|
504
|
-
object.
|
504
|
+
expect(object).not_to be_a(ExploitableBackDoor)
|
505
505
|
end
|
506
506
|
|
507
507
|
it "returns false when parsing an empty file" do
|
508
|
-
YAML.safe_load_file("spec/issue49.yml").
|
508
|
+
expect(YAML.safe_load_file("spec/issue49.yml")).to eq(false)
|
509
509
|
end
|
510
510
|
end
|
511
511
|
|
@@ -523,13 +523,13 @@ describe YAML do
|
|
523
523
|
context "as long as a :default_mode has been specified" do
|
524
524
|
it "doesn't issue a warning for safe mode, since an explicit mode has been set" do
|
525
525
|
SafeYAML::OPTIONS[:default_mode] = :safe
|
526
|
-
Kernel.
|
526
|
+
expect(Kernel).not_to receive(:warn)
|
527
527
|
YAML.load(*arguments)
|
528
528
|
end
|
529
529
|
|
530
530
|
it "doesn't issue a warning for unsafe mode, since an explicit mode has been set" do
|
531
531
|
SafeYAML::OPTIONS[:default_mode] = :unsafe
|
532
|
-
Kernel.
|
532
|
+
expect(Kernel).not_to receive(:warn)
|
533
533
|
YAML.load(*arguments)
|
534
534
|
end
|
535
535
|
end
|
@@ -539,12 +539,12 @@ describe YAML do
|
|
539
539
|
let(:options) { { :safe => safe_mode } }
|
540
540
|
|
541
541
|
it "doesn't issue a warning" do
|
542
|
-
Kernel.
|
542
|
+
expect(Kernel).not_to receive(:warn)
|
543
543
|
YAML.load(*arguments)
|
544
544
|
end
|
545
545
|
|
546
546
|
it "calls #safe_load if the :safe option is set to true" do
|
547
|
-
YAML.
|
547
|
+
expect(YAML).to receive(:safe_load)
|
548
548
|
YAML.load(*arguments)
|
549
549
|
end
|
550
550
|
|
@@ -552,7 +552,7 @@ describe YAML do
|
|
552
552
|
let(:safe_mode) { false }
|
553
553
|
|
554
554
|
it "calls #unsafe_load if the :safe option is set to false" do
|
555
|
-
YAML.
|
555
|
+
expect(YAML).to receive(:unsafe_load)
|
556
556
|
YAML.load(*arguments)
|
557
557
|
end
|
558
558
|
end
|
@@ -560,21 +560,21 @@ describe YAML do
|
|
560
560
|
|
561
561
|
it "issues a warning when the :safe option is omitted" do
|
562
562
|
silence_warnings do
|
563
|
-
Kernel.
|
563
|
+
expect(Kernel).to receive(:warn)
|
564
564
|
YAML.load(*arguments)
|
565
565
|
end
|
566
566
|
end
|
567
567
|
|
568
568
|
it "only issues a warning once (to avoid spamming an app's output)" do
|
569
569
|
silence_warnings do
|
570
|
-
Kernel.
|
570
|
+
expect(Kernel).to receive(:warn).once
|
571
571
|
2.times { YAML.load(*arguments) }
|
572
572
|
end
|
573
573
|
end
|
574
574
|
|
575
575
|
it "defaults to safe mode if the :safe option is omitted" do
|
576
576
|
silence_warnings do
|
577
|
-
YAML.
|
577
|
+
expect(YAML).to receive(:safe_load)
|
578
578
|
YAML.load(*arguments)
|
579
579
|
end
|
580
580
|
end
|
@@ -586,13 +586,13 @@ describe YAML do
|
|
586
586
|
|
587
587
|
it "defaults to unsafe mode if the :safe option is omitted" do
|
588
588
|
silence_warnings do
|
589
|
-
YAML.
|
589
|
+
expect(YAML).to receive(:unsafe_load)
|
590
590
|
YAML.load(*arguments)
|
591
591
|
end
|
592
592
|
end
|
593
593
|
|
594
594
|
it "calls #safe_load if the :safe option is set to true" do
|
595
|
-
YAML.
|
595
|
+
expect(YAML).to receive(:safe_load)
|
596
596
|
YAML.load(*(arguments + [{ :safe => true }]))
|
597
597
|
end
|
598
598
|
end
|
@@ -603,30 +603,30 @@ describe YAML do
|
|
603
603
|
|
604
604
|
it "issues a warning if the :safe option is omitted" do
|
605
605
|
silence_warnings do
|
606
|
-
Kernel.
|
606
|
+
expect(Kernel).to receive(:warn)
|
607
607
|
YAML.load_file(filename)
|
608
608
|
end
|
609
609
|
end
|
610
610
|
|
611
611
|
it "doesn't issue a warning as long as the :safe option is specified" do
|
612
|
-
Kernel.
|
612
|
+
expect(Kernel).not_to receive(:warn)
|
613
613
|
YAML.load_file(filename, :safe => true)
|
614
614
|
end
|
615
615
|
|
616
616
|
it "defaults to safe mode if the :safe option is omitted" do
|
617
617
|
silence_warnings do
|
618
|
-
YAML.
|
618
|
+
expect(YAML).to receive(:safe_load_file)
|
619
619
|
YAML.load_file(filename)
|
620
620
|
end
|
621
621
|
end
|
622
622
|
|
623
623
|
it "calls #safe_load_file if the :safe option is set to true" do
|
624
|
-
YAML.
|
624
|
+
expect(YAML).to receive(:safe_load_file)
|
625
625
|
YAML.load_file(filename, :safe => true)
|
626
626
|
end
|
627
627
|
|
628
628
|
it "calls #unsafe_load_file if the :safe option is set to false" do
|
629
|
-
YAML.
|
629
|
+
expect(YAML).to receive(:unsafe_load_file)
|
630
630
|
YAML.load_file(filename, :safe => false)
|
631
631
|
end
|
632
632
|
|
@@ -637,30 +637,30 @@ describe YAML do
|
|
637
637
|
|
638
638
|
it "defaults to unsafe mode if the :safe option is omitted" do
|
639
639
|
silence_warnings do
|
640
|
-
YAML.
|
640
|
+
expect(YAML).to receive(:unsafe_load_file)
|
641
641
|
YAML.load_file(filename)
|
642
642
|
end
|
643
643
|
end
|
644
644
|
|
645
645
|
it "calls #safe_load if the :safe option is set to true" do
|
646
|
-
YAML.
|
646
|
+
expect(YAML).to receive(:safe_load_file)
|
647
647
|
YAML.load_file(filename, :safe => true)
|
648
648
|
end
|
649
649
|
end
|
650
650
|
|
651
651
|
it "handles files starting with --- (see issue #48)" do
|
652
|
-
YAML.load_file("spec/issue48.txt", :safe => true).
|
652
|
+
expect(YAML.load_file("spec/issue48.txt", :safe => true)).to eq({
|
653
653
|
"title" => "Blah",
|
654
654
|
"key" => "value"
|
655
|
-
}
|
655
|
+
})
|
656
656
|
end
|
657
657
|
|
658
658
|
it "handles content starting with --- (see issue #48)" do
|
659
659
|
yaml = File.read("spec/issue48.txt")
|
660
|
-
YAML.load(yaml, :safe => true).
|
660
|
+
expect(YAML.load(yaml, :safe => true)).to eq({
|
661
661
|
"title" => "Blah",
|
662
662
|
"key" => "value"
|
663
|
-
}
|
663
|
+
})
|
664
664
|
end
|
665
665
|
end
|
666
666
|
|
@@ -668,21 +668,21 @@ describe YAML do
|
|
668
668
|
context "not a class" do
|
669
669
|
it "should raise" do
|
670
670
|
expect { SafeYAML::whitelist! :foo }.to raise_error(/not a Class/)
|
671
|
-
SafeYAML::OPTIONS[:whitelisted_tags].
|
671
|
+
expect(SafeYAML::OPTIONS[:whitelisted_tags]).to be_empty
|
672
672
|
end
|
673
673
|
end
|
674
674
|
|
675
675
|
context "anonymous class" do
|
676
676
|
it "should raise" do
|
677
677
|
expect { SafeYAML::whitelist! Class.new }.to raise_error(/cannot be anonymous/)
|
678
|
-
SafeYAML::OPTIONS[:whitelisted_tags].
|
678
|
+
expect(SafeYAML::OPTIONS[:whitelisted_tags]).to be_empty
|
679
679
|
end
|
680
680
|
end
|
681
681
|
|
682
682
|
context "with a Class as its argument" do
|
683
683
|
it "should configure correctly" do
|
684
684
|
expect { SafeYAML::whitelist! OpenStruct }.to_not raise_error
|
685
|
-
SafeYAML::OPTIONS[:whitelisted_tags].grep(/OpenStruct\Z/).
|
685
|
+
expect(SafeYAML::OPTIONS[:whitelisted_tags].grep(/OpenStruct\Z/)).not_to be_empty
|
686
686
|
end
|
687
687
|
|
688
688
|
it "successfully deserializes the specified class" do
|
@@ -692,23 +692,23 @@ describe YAML do
|
|
692
692
|
SafeYAML::OPTIONS[:deserialize_symbols] = true
|
693
693
|
|
694
694
|
result = safe_load_round_trip(OpenStruct.new(:foo => "bar"))
|
695
|
-
result.
|
696
|
-
result.foo.
|
695
|
+
expect(result).to be_a(OpenStruct)
|
696
|
+
expect(result.foo).to eq("bar")
|
697
697
|
end
|
698
698
|
|
699
699
|
it "works for ranges" do
|
700
700
|
SafeYAML.whitelist!(Range)
|
701
|
-
safe_load_round_trip(1..10).
|
701
|
+
expect(safe_load_round_trip(1..10)).to eq(1..10)
|
702
702
|
end
|
703
703
|
|
704
704
|
it "works for regular expressions" do
|
705
705
|
SafeYAML.whitelist!(Regexp)
|
706
|
-
safe_load_round_trip(/foo/).
|
706
|
+
expect(safe_load_round_trip(/foo/)).to eq(/foo/)
|
707
707
|
end
|
708
708
|
|
709
709
|
it "works for multiple classes" do
|
710
710
|
SafeYAML.whitelist!(Range, Regexp)
|
711
|
-
safe_load_round_trip([(1..10), /bar/]).
|
711
|
+
expect(safe_load_round_trip([(1..10), /bar/])).to eq([(1..10), /bar/])
|
712
712
|
end
|
713
713
|
|
714
714
|
it "works for arbitrary Exception subclasses" do
|
@@ -723,8 +723,8 @@ describe YAML do
|
|
723
723
|
SafeYAML.whitelist!(CustomException)
|
724
724
|
|
725
725
|
ex = safe_load_round_trip(CustomException.new("blah"))
|
726
|
-
ex.
|
727
|
-
ex.custom_message.
|
726
|
+
expect(ex).to be_a(CustomException)
|
727
|
+
expect(ex.custom_message).to eq("blah")
|
728
728
|
end
|
729
729
|
end
|
730
730
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -13,13 +13,13 @@ ruby_version = defined?(JRUBY_VERSION) ? "JRuby #{JRUBY_VERSION} in #{RUBY_VERSI
|
|
13
13
|
yaml_engine = defined?(YAML::ENGINE) ? YAML::ENGINE.yamler : "syck"
|
14
14
|
libyaml_version = yaml_engine == "psych" && Psych.const_defined?("LIBYAML_VERSION", false) ? Psych::LIBYAML_VERSION : "N/A"
|
15
15
|
|
16
|
-
|
16
|
+
env_info = [
|
17
|
+
ruby_version,
|
18
|
+
"YAML: #{yaml_engine} (#{YAML::VERSION}) (libyaml: #{libyaml_version})",
|
19
|
+
"Monkeypatch: #{ENV['MONKEYPATCH_YAML']}"
|
20
|
+
]
|
17
21
|
|
18
|
-
|
19
|
-
YAML engine version: #{YAML::VERSION}
|
20
|
-
libyaml version: #{libyaml_version}
|
21
|
-
|
22
|
-
EOM
|
22
|
+
puts env_info.join(", ")
|
23
23
|
|
24
24
|
# Caching references to these methods before loading safe_yaml in order to test
|
25
25
|
# that they aren't touched unless you actually require safe_yaml (see yaml_spec.rb).
|
@@ -5,7 +5,7 @@ describe SafeYAML::Transform do
|
|
5
5
|
value = "c3VyZS4="
|
6
6
|
decoded = SafeYAML::Transform.to_proper_type(value, false, "!binary")
|
7
7
|
|
8
|
-
decoded.
|
9
|
-
decoded.encoding.
|
8
|
+
expect(decoded).to eq("sure.")
|
9
|
+
expect(decoded.encoding).to eq(value.encoding) if decoded.respond_to?(:encoding)
|
10
10
|
end
|
11
11
|
end
|
@@ -2,19 +2,19 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe SafeYAML::Transform::ToDate do
|
4
4
|
it "returns true when the value matches a valid Date" do
|
5
|
-
subject.transform?("2013-01-01").
|
5
|
+
expect(subject.transform?("2013-01-01")).to eq([true, Date.parse("2013-01-01")])
|
6
6
|
end
|
7
7
|
|
8
8
|
it "returns false when the value does not match a valid Date" do
|
9
|
-
subject.transform?("foobar").
|
9
|
+
expect(subject.transform?("foobar")).to be_falsey
|
10
10
|
end
|
11
11
|
|
12
12
|
it "returns false when the value does not end with a Date" do
|
13
|
-
subject.transform?("2013-01-01\nNOT A DATE").
|
13
|
+
expect(subject.transform?("2013-01-01\nNOT A DATE")).to be_falsey
|
14
14
|
end
|
15
15
|
|
16
16
|
it "returns false when the value does not begin with a Date" do
|
17
|
-
subject.transform?("NOT A DATE\n2013-01-01").
|
17
|
+
expect(subject.transform?("NOT A DATE\n2013-01-01")).to be_falsey
|
18
18
|
end
|
19
19
|
|
20
20
|
it "correctly parses the remaining formats of the YAML spec" do
|
@@ -27,30 +27,30 @@ describe SafeYAML::Transform::ToDate do
|
|
27
27
|
|
28
28
|
equivalent_values.each do |value|
|
29
29
|
success, result = subject.transform?(value)
|
30
|
-
success.
|
31
|
-
result.
|
30
|
+
expect(success).to be_truthy
|
31
|
+
expect(result).to eq(Time.utc(2001, 12, 15, 2, 59, 43, 100000))
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
it "converts times to the local timezone" do
|
36
36
|
success, result = subject.transform?("2012-12-01 10:33:45 +11:00")
|
37
|
-
success.
|
38
|
-
result.
|
39
|
-
result.gmt_offset.
|
37
|
+
expect(success).to be_truthy
|
38
|
+
expect(result).to eq(Time.utc(2012, 11, 30, 23, 33, 45))
|
39
|
+
expect(result.gmt_offset).to eq(Time.local(2012, 11, 30).gmt_offset)
|
40
40
|
end
|
41
41
|
|
42
42
|
it "returns strings for invalid dates" do
|
43
|
-
subject.transform?("0000-00-00").
|
44
|
-
subject.transform?("2013-13-01").
|
45
|
-
subject.transform?("2014-01-32").
|
43
|
+
expect(subject.transform?("0000-00-00")).to eq([true, "0000-00-00"])
|
44
|
+
expect(subject.transform?("2013-13-01")).to eq([true, "2013-13-01"])
|
45
|
+
expect(subject.transform?("2014-01-32")).to eq([true, "2014-01-32"])
|
46
46
|
end
|
47
47
|
|
48
48
|
it "returns strings for invalid date/times" do
|
49
|
-
subject.transform?("0000-00-00 00:00:00 -0000").
|
50
|
-
subject.transform?("2013-13-01 21:59:43 -05:00").
|
51
|
-
subject.transform?("2013-01-32 21:59:43 -05:00").
|
52
|
-
subject.transform?("2013-01-30 25:59:43 -05:00").
|
53
|
-
subject.transform?("2013-01-30 21:69:43 -05:00").
|
49
|
+
expect(subject.transform?("0000-00-00 00:00:00 -0000")).to eq([true, "0000-00-00 00:00:00 -0000"])
|
50
|
+
expect(subject.transform?("2013-13-01 21:59:43 -05:00")).to eq([true, "2013-13-01 21:59:43 -05:00"])
|
51
|
+
expect(subject.transform?("2013-01-32 21:59:43 -05:00")).to eq([true, "2013-01-32 21:59:43 -05:00"])
|
52
|
+
expect(subject.transform?("2013-01-30 25:59:43 -05:00")).to eq([true, "2013-01-30 25:59:43 -05:00"])
|
53
|
+
expect(subject.transform?("2013-01-30 21:69:43 -05:00")).to eq([true, "2013-01-30 21:69:43 -05:00"])
|
54
54
|
|
55
55
|
# Interesting. It seems that in some older Ruby versions, the below actually parses successfully
|
56
56
|
# w/ DateTime.parse; but it fails w/ YAML.load. Whom to follow???
|
@@ -2,41 +2,41 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe SafeYAML::Transform::ToFloat do
|
4
4
|
it "returns true when the value matches a valid Float" do
|
5
|
-
subject.transform?("20.00").
|
5
|
+
expect(subject.transform?("20.00")).to eq([true, 20.0])
|
6
6
|
end
|
7
7
|
|
8
8
|
it "returns false when the value does not match a valid Float" do
|
9
|
-
subject.transform?("foobar").
|
9
|
+
expect(subject.transform?("foobar")).to be_falsey
|
10
10
|
end
|
11
11
|
|
12
12
|
it "returns false when the value spans multiple lines" do
|
13
|
-
subject.transform?("20.00\nNOT A FLOAT").
|
13
|
+
expect(subject.transform?("20.00\nNOT A FLOAT")).to be_falsey
|
14
14
|
end
|
15
15
|
|
16
16
|
it "correctly parses all formats in the YAML spec" do
|
17
17
|
# canonical
|
18
|
-
subject.transform?("6.8523015e+5").
|
18
|
+
expect(subject.transform?("6.8523015e+5")).to eq([true, 685230.15])
|
19
19
|
|
20
20
|
# exponentioal
|
21
|
-
subject.transform?("685.230_15e+03").
|
21
|
+
expect(subject.transform?("685.230_15e+03")).to eq([true, 685230.15])
|
22
22
|
|
23
23
|
# fixed
|
24
|
-
subject.transform?("685_230.15").
|
24
|
+
expect(subject.transform?("685_230.15")).to eq([true, 685230.15])
|
25
25
|
|
26
26
|
# sexagesimal
|
27
|
-
subject.transform?("190:20:30.15").
|
27
|
+
expect(subject.transform?("190:20:30.15")).to eq([true, 685230.15])
|
28
28
|
|
29
29
|
# infinity
|
30
|
-
subject.transform?("-.inf").
|
30
|
+
expect(subject.transform?("-.inf")).to eq([true, (-1.0 / 0.0)])
|
31
31
|
|
32
32
|
# not a number
|
33
33
|
# NOTE: can't use == here since NaN != NaN
|
34
34
|
success, result = subject.transform?(".NaN")
|
35
|
-
success.
|
35
|
+
expect(success).to be_truthy; expect(result).to be_nan
|
36
36
|
end
|
37
37
|
|
38
38
|
# issue 29
|
39
39
|
it "returns false for the string '.'" do
|
40
|
-
subject.transform?(".").
|
40
|
+
expect(subject.transform?(".")).to be_falsey
|
41
41
|
end
|
42
42
|
end
|
@@ -2,63 +2,63 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe SafeYAML::Transform::ToInteger do
|
4
4
|
it "returns true when the value matches a valid Integer" do
|
5
|
-
subject.transform?("10").
|
5
|
+
expect(subject.transform?("10")).to eq([true, 10])
|
6
6
|
end
|
7
7
|
|
8
8
|
it "returns false when the value does not match a valid Integer" do
|
9
|
-
subject.transform?("foobar").
|
9
|
+
expect(subject.transform?("foobar")).to be_falsey
|
10
10
|
end
|
11
11
|
|
12
12
|
it "returns false when the value spans multiple lines" do
|
13
|
-
subject.transform?("10\nNOT AN INTEGER").
|
13
|
+
expect(subject.transform?("10\nNOT AN INTEGER")).to be_falsey
|
14
14
|
end
|
15
15
|
|
16
16
|
it "allows commas in the number" do
|
17
|
-
subject.transform?("1,000").
|
17
|
+
expect(subject.transform?("1,000")).to eq([true, 1000])
|
18
18
|
end
|
19
19
|
|
20
20
|
it "correctly parses numbers in octal format" do
|
21
|
-
subject.transform?("010").
|
21
|
+
expect(subject.transform?("010")).to eq([true, 8])
|
22
22
|
end
|
23
23
|
|
24
24
|
it "correctly parses numbers in hexadecimal format" do
|
25
|
-
subject.transform?("0x1FF").
|
25
|
+
expect(subject.transform?("0x1FF")).to eq([true, 511])
|
26
26
|
end
|
27
27
|
|
28
28
|
it "defaults to a string for a number that resembles octal format but is not" do
|
29
|
-
subject.transform?("09").
|
29
|
+
expect(subject.transform?("09")).to be_falsey
|
30
30
|
end
|
31
31
|
|
32
32
|
it "correctly parses 0 in decimal" do
|
33
|
-
subject.transform?("0").
|
33
|
+
expect(subject.transform?("0")).to eq([true, 0])
|
34
34
|
end
|
35
35
|
|
36
36
|
it "defaults to a string for a number that resembles hexadecimal format but is not" do
|
37
|
-
subject.transform?("0x1G").
|
37
|
+
expect(subject.transform?("0x1G")).to be_falsey
|
38
38
|
end
|
39
39
|
|
40
40
|
it "correctly parses all formats in the YAML spec" do
|
41
41
|
# canonical
|
42
|
-
subject.transform?("685230").
|
42
|
+
expect(subject.transform?("685230")).to eq([true, 685230])
|
43
43
|
|
44
44
|
# decimal
|
45
|
-
subject.transform?("+685_230").
|
45
|
+
expect(subject.transform?("+685_230")).to eq([true, 685230])
|
46
46
|
|
47
47
|
# octal
|
48
|
-
subject.transform?("02472256").
|
48
|
+
expect(subject.transform?("02472256")).to eq([true, 685230])
|
49
49
|
|
50
50
|
# hexadecimal:
|
51
|
-
subject.transform?("0x_0A_74_AE").
|
51
|
+
expect(subject.transform?("0x_0A_74_AE")).to eq([true, 685230])
|
52
52
|
|
53
53
|
# binary
|
54
|
-
subject.transform?("0b1010_0111_0100_1010_1110").
|
54
|
+
expect(subject.transform?("0b1010_0111_0100_1010_1110")).to eq([true, 685230])
|
55
55
|
|
56
56
|
# sexagesimal
|
57
|
-
subject.transform?("190:20:30").
|
57
|
+
expect(subject.transform?("190:20:30")).to eq([true, 685230])
|
58
58
|
end
|
59
59
|
|
60
60
|
# see https://github.com/dtao/safe_yaml/pull/51
|
61
61
|
it "strips out underscores before parsing decimal values" do
|
62
|
-
subject.transform?("_850_").
|
62
|
+
expect(subject.transform?("_850_")).to eq([true, 850])
|
63
63
|
end
|
64
64
|
end
|
@@ -20,32 +20,32 @@ describe SafeYAML::Transform::ToSymbol do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "returns true when the value matches a valid Symbol" do
|
23
|
-
with_symbol_deserialization { subject.transform?(":foo")[0].
|
23
|
+
with_symbol_deserialization { expect(subject.transform?(":foo")[0]).to be_truthy }
|
24
24
|
end
|
25
25
|
|
26
26
|
it "returns true when the value matches a valid String+Symbol" do
|
27
|
-
with_symbol_deserialization { subject.transform?(':"foo"')[0].
|
27
|
+
with_symbol_deserialization { expect(subject.transform?(':"foo"')[0]).to be_truthy }
|
28
28
|
end
|
29
29
|
|
30
30
|
it "returns true when the value matches a valid String+Symbol with 's" do
|
31
|
-
with_symbol_deserialization { subject.transform?(":'foo'")[0].
|
31
|
+
with_symbol_deserialization { expect(subject.transform?(":'foo'")[0]).to be_truthy }
|
32
32
|
end
|
33
33
|
|
34
34
|
it "returns true when the value has special characters and is wrapped in a String" do
|
35
|
-
with_symbol_deserialization { subject.transform?(':"foo.bar"')[0].
|
35
|
+
with_symbol_deserialization { expect(subject.transform?(':"foo.bar"')[0]).to be_truthy }
|
36
36
|
end
|
37
37
|
|
38
38
|
it "returns false when symbol deserialization is disabled" do
|
39
|
-
without_symbol_deserialization { subject.transform?(":foo").
|
39
|
+
without_symbol_deserialization { expect(subject.transform?(":foo")).to be_falsey }
|
40
40
|
end
|
41
41
|
|
42
42
|
it "returns false when the value does not match a valid Symbol" do
|
43
|
-
with_symbol_deserialization { subject.transform?("foo").
|
43
|
+
with_symbol_deserialization { expect(subject.transform?("foo")).to be_falsey }
|
44
44
|
end
|
45
45
|
|
46
46
|
it "returns false when the symbol does not begin the line" do
|
47
47
|
with_symbol_deserialization do
|
48
|
-
subject.transform?("NOT A SYMBOL\n:foo").
|
48
|
+
expect(subject.transform?("NOT A SYMBOL\n:foo")).to be_falsey
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
data/spec/yaml_spec.rb
CHANGED
@@ -5,11 +5,11 @@ require "spec_helper"
|
|
5
5
|
describe YAML do
|
6
6
|
context "when you've only required safe_yaml/load", :libraries => true do
|
7
7
|
it "YAML.load doesn't get monkey patched" do
|
8
|
-
YAML.method(:load).
|
8
|
+
expect(YAML.method(:load)).to eq(ORIGINAL_YAML_LOAD)
|
9
9
|
end
|
10
10
|
|
11
11
|
it "YAML.load_file doesn't get monkey patched" do
|
12
|
-
YAML.method(:load_file).
|
12
|
+
expect(YAML.method(:load_file)).to eq(ORIGINAL_YAML_LOAD_FILE)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_yaml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Tao
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Parse YAML safely
|
14
14
|
email: daniel.tao@gmail.com
|
@@ -17,8 +17,8 @@ executables:
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
-
- .gitignore
|
21
|
-
- .travis.yml
|
20
|
+
- ".gitignore"
|
21
|
+
- ".travis.yml"
|
22
22
|
- CHANGES.md
|
23
23
|
- Gemfile
|
24
24
|
- LICENSE.txt
|
@@ -78,17 +78,17 @@ require_paths:
|
|
78
78
|
- lib
|
79
79
|
required_ruby_version: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: 1.8.7
|
84
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
|
-
- -
|
86
|
+
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
89
|
requirements: []
|
90
90
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.
|
91
|
+
rubygems_version: 2.1.11
|
92
92
|
signing_key:
|
93
93
|
specification_version: 4
|
94
94
|
summary: SameYAML provides an alternative implementation of YAML.load suitable for
|