ndr_support 5.9.6 → 5.10.0
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/CHANGELOG.md +11 -0
- data/code_safety.yml +4 -4
- data/lib/ndr_support/version.rb +1 -1
- data/lib/ndr_support/yaml/serialization_migration.rb +39 -9
- data/test/yaml/serialization_test.rb +46 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 452da481cc47dceb02b62e7eb832db07ba61985fb2cdc8267a40b6194d0ef108
|
4
|
+
data.tar.gz: e06b9a9845389b639c2fbe55aab1f4008d6dad69843a24113bf55b2b88fd7d56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d06a0fb2e4adae1cbc71b7e89fd4fc45b527a419ad313d6440dd199ddb845df637b4dd505dce4220dae16bc6f059e96a2faddc455c1901a54bd8acba86b4b3e
|
7
|
+
data.tar.gz: d5abcaa621cf18823123cd1241a519c2c2a9dd856ac6659a9f4d4497adcd11ec4b57beeade25c7e799b9924de02736344b91ef079b2bef5a65785a41a6d20333
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
* No unreleased changes
|
3
3
|
|
4
|
+
## 5.10.0 / 2023-11-17
|
5
|
+
## Changed
|
6
|
+
* Generate UTF-8 encoded YAML by default. Disable with `utf8_storage = false`
|
7
|
+
* Use `YAML.safe_load` by default. Override with
|
8
|
+
`self.yaml_safe_classes = yaml_safe_classes + [Klass1, Klass2]` and revert to
|
9
|
+
unsafe loading with `yaml_safe_classes = :unsafe` and `gem 'psych', '< 4'`
|
10
|
+
|
11
|
+
## 5.9.7 / 2023-11-16
|
12
|
+
## Fixed
|
13
|
+
* YAMLSupport should preserve escaped backslashes in YAML text
|
14
|
+
|
4
15
|
## 5.9.6 / 2023-11-14
|
5
16
|
## Fixed
|
6
17
|
* YAMLSupport should preserve escape sequences in JSON text
|
data/code_safety.yml
CHANGED
@@ -23,7 +23,7 @@ file safety:
|
|
23
23
|
CHANGELOG.md:
|
24
24
|
comments:
|
25
25
|
reviewed_by: brian.shand
|
26
|
-
safe_revision:
|
26
|
+
safe_revision: 646eaebdf824490150e991225f9e15abb67dd4c1
|
27
27
|
CODE_OF_CONDUCT.md:
|
28
28
|
comments:
|
29
29
|
reviewed_by: timgentry
|
@@ -171,7 +171,7 @@ file safety:
|
|
171
171
|
lib/ndr_support/version.rb:
|
172
172
|
comments:
|
173
173
|
reviewed_by: brian.shand
|
174
|
-
safe_revision:
|
174
|
+
safe_revision: 765520ebaf3652bed7105995c815afe681dd5363
|
175
175
|
lib/ndr_support/working_days.rb:
|
176
176
|
comments:
|
177
177
|
reviewed_by: josh.pencheon
|
@@ -179,7 +179,7 @@ file safety:
|
|
179
179
|
lib/ndr_support/yaml/serialization_migration.rb:
|
180
180
|
comments:
|
181
181
|
reviewed_by: brian.shand
|
182
|
-
safe_revision:
|
182
|
+
safe_revision: 646eaebdf824490150e991225f9e15abb67dd4c1
|
183
183
|
ndr_support.gemspec:
|
184
184
|
comments:
|
185
185
|
reviewed_by: brian.shand
|
@@ -283,4 +283,4 @@ file safety:
|
|
283
283
|
test/yaml/serialization_test.rb:
|
284
284
|
comments:
|
285
285
|
reviewed_by: brian.shand
|
286
|
-
safe_revision:
|
286
|
+
safe_revision: 646eaebdf824490150e991225f9e15abb67dd4c1
|
data/lib/ndr_support/version.rb
CHANGED
@@ -12,8 +12,29 @@ module NdrSupport
|
|
12
12
|
# accepted by load_yaml
|
13
13
|
YAML_SAFE_CLASSES = [Date, DateTime, Time, Symbol].freeze
|
14
14
|
|
15
|
+
# Set list of YAML safe classes, or :unsafe to use unsafe load
|
16
|
+
def yaml_safe_classes=(yaml_safe_classes)
|
17
|
+
@yaml_safe_classes = yaml_safe_classes
|
18
|
+
end
|
19
|
+
|
20
|
+
def yaml_safe_classes
|
21
|
+
@yaml_safe_classes || YAML_SAFE_CLASSES
|
22
|
+
end
|
23
|
+
|
24
|
+
# Allow emitted YAML to contain UTF-8 characters
|
25
|
+
# Defaults to true. (Defaulted to false in ndr_support versions < 6)
|
26
|
+
def utf8_storage=(utf8_storage)
|
27
|
+
@utf8_storage = utf8_storage
|
28
|
+
end
|
29
|
+
|
30
|
+
def utf8_storage
|
31
|
+
return @utf8_storage if @utf8_storage == false
|
32
|
+
|
33
|
+
true # New ndr_support default for versions >= 6, previously false
|
34
|
+
end
|
35
|
+
|
15
36
|
# Wrapper around: YAML.load(string)
|
16
|
-
def load_yaml(string, coerce_invalid_chars = false)
|
37
|
+
def load_yaml(string, coerce_invalid_chars = false) # rubocop:disable Style/OptionalBooleanParameter
|
17
38
|
fix_encoding!(string, coerce_invalid_chars)
|
18
39
|
|
19
40
|
# Achieve same behaviour using `syck` and `psych`:
|
@@ -21,10 +42,14 @@ module NdrSupport
|
|
21
42
|
fix_encoding!(string, coerce_invalid_chars)
|
22
43
|
|
23
44
|
# TODO: Bump NdrSupport major version, and switch to safe_load by default
|
24
|
-
object = if
|
45
|
+
object = if yaml_safe_classes == :unsafe
|
46
|
+
unless Psych::VERSION.start_with?('3.')
|
47
|
+
raise(SecurityError, 'Unsafe YAML no longer supported')
|
48
|
+
end
|
49
|
+
|
25
50
|
Psych.load(string)
|
26
51
|
else
|
27
|
-
Psych.safe_load(string, permitted_classes:
|
52
|
+
Psych.safe_load(string, permitted_classes: yaml_safe_classes)
|
28
53
|
end
|
29
54
|
|
30
55
|
# Ensure that any string related to the object
|
@@ -37,8 +62,10 @@ module NdrSupport
|
|
37
62
|
|
38
63
|
# Wrapper around: YAML.dump(object)
|
39
64
|
def dump_yaml(object)
|
40
|
-
|
41
|
-
|
65
|
+
return Psych.dump(object) if utf8_storage
|
66
|
+
|
67
|
+
# Psych produces UTF-8 encoded output; historically we
|
68
|
+
# preferred YAML that can be safely stored in stores with
|
42
69
|
# other encodings. If #load_yaml is used, the binary
|
43
70
|
# encoding of the object will be reversed on load.
|
44
71
|
Psych.dump binary_encode_any_high_ascii(object)
|
@@ -56,14 +83,17 @@ module NdrSupport
|
|
56
83
|
# Within double quotes, YAML allows special characters.
|
57
84
|
# While `psych` emits UTF-8 YAML, `syck` double escapes
|
58
85
|
# higher characters. We need to unescape any we find:
|
86
|
+
# Both `psych` and `syck` escape lower control characters.
|
59
87
|
def handle_special_characters!(string, coerce_invalid_chars)
|
60
|
-
# TODO: Change to only handle syck control characters
|
61
88
|
return unless string.start_with?('---') # Only handle YAML that is not JSON
|
62
89
|
|
63
90
|
# Replace any encoded hex chars with their actual value:
|
64
|
-
string.gsub!(/((?:\\x[0-9A-F]{2})+)/) do
|
65
|
-
|
66
|
-
|
91
|
+
string.gsub!(/(?<!\\)((?:\\\\)*)((?:\\x[0-9A-F]{2})+)/) do
|
92
|
+
# We use negative lookbehind and the first capturing group to skip over
|
93
|
+
# properly escaped backslashes
|
94
|
+
prefix = ::Regexp.last_match(1) # Prefix is an even number of backslashes
|
95
|
+
byte_sequence = ::Regexp.last_match(2).scan(/[0-9A-F]{2}/)
|
96
|
+
prefix + byte_sequence.pack('H2' * byte_sequence.length).tap do |sequence|
|
67
97
|
fix_encoding!(sequence, coerce_invalid_chars)
|
68
98
|
end
|
69
99
|
end
|
@@ -29,8 +29,14 @@ class SerializationTest < Minitest::Test
|
|
29
29
|
assert_equal "control 0x01 char \n whoops!", load_yaml(chr_1_yaml)
|
30
30
|
end
|
31
31
|
|
32
|
+
test 'should handle non-binary yaml with escaped things that look like control chars' do
|
33
|
+
# irb> Psych.dump(['\\x01 \\xAF \\\\xAF', "\x01 \\\x01 \x01\\\x01"])
|
34
|
+
escaped_yaml = "---\n- \"\\\\x01 \\\\xAF \\\\\\\\xAF\"\n- \"\\x01 \\\\\\x01 \\x01\\\\\\x01\"\n"
|
35
|
+
assert_equal ['\\x01 \\xAF \\\\xAF', '0x01 \\0x01 0x01\\0x01'], load_yaml(escaped_yaml)
|
36
|
+
end
|
37
|
+
|
32
38
|
test 'should leave non-binary JSON with things that look like control chars unchanged' do
|
33
|
-
hash = { 'report' => ' \
|
39
|
+
hash = { 'report' => ' \x01 ' }
|
34
40
|
assert_equal hash, load_yaml(hash.to_json)
|
35
41
|
end
|
36
42
|
|
@@ -38,26 +44,60 @@ class SerializationTest < Minitest::Test
|
|
38
44
|
assert_yaml_coercion_behaviour
|
39
45
|
end
|
40
46
|
|
41
|
-
test 'dump_yaml should produce encoding-portable YAML' do
|
42
|
-
|
47
|
+
test 'dump_yaml with utf8_storage = false should produce encoding-portable YAML' do
|
48
|
+
self.utf8_storage = false
|
49
|
+
original_object = { basic: 'manana', complex: 'mañana' }
|
43
50
|
yaml_produced = dump_yaml(original_object)
|
44
51
|
reloaded_object = load_yaml(yaml_produced)
|
45
52
|
|
46
|
-
|
53
|
+
assert_match(/basic: manana/, yaml_produced, 'binary-encoded more than was necessary')
|
47
54
|
|
48
55
|
refute yaml_produced.bytes.detect { |byte| byte > 127 }, 'yaml has high-ascii'
|
49
56
|
assert reloaded_object.inspect.bytes.detect { |byte| byte > 127 }
|
50
57
|
assert_equal original_object, reloaded_object
|
51
58
|
end
|
52
59
|
|
53
|
-
test 'encoding-portable YAML should be loadable' do
|
54
|
-
|
60
|
+
test 'encoding-portable YAML with utf8_storage = false should be loadable' do
|
61
|
+
self.utf8_storage = false
|
62
|
+
original_object = { basic: 'manana', complex: 'mañana' }
|
63
|
+
yaml_produced = dump_yaml(original_object)
|
64
|
+
|
65
|
+
assert_equal("---\n:basic: manana\n:complex: !binary |-\n bWHDsWFuYQ==\n", yaml_produced)
|
66
|
+
|
67
|
+
reloaded_object = load_yaml(yaml_produced)
|
68
|
+
assert_equal original_object, reloaded_object
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'non-encoding-portable YAML with utf8_storage = true should be loadable' do
|
72
|
+
self.utf8_storage = true
|
73
|
+
original_object = { basic: 'manana', complex: 'mañana' }
|
55
74
|
yaml_produced = dump_yaml(original_object)
|
75
|
+
assert_equal("---\n:basic: manana\n:complex: mañana\n", yaml_produced)
|
56
76
|
|
57
77
|
reloaded_object = load_yaml(yaml_produced)
|
58
78
|
assert_equal original_object, reloaded_object
|
59
79
|
end
|
60
80
|
|
81
|
+
test 'yaml_safe_classes should filter which classes can be loaded' do
|
82
|
+
original_object = { basic: 'manana', complex: 'mañana' }
|
83
|
+
yaml_produced = dump_yaml(original_object)
|
84
|
+
self.yaml_safe_classes = []
|
85
|
+
assert_raises Psych::DisallowedClass, 'Load should fail without Symbol in yaml_safe_classes' do
|
86
|
+
load_yaml(yaml_produced)
|
87
|
+
end
|
88
|
+
|
89
|
+
self.yaml_safe_classes = [Symbol]
|
90
|
+
reloaded_object = load_yaml(yaml_produced)
|
91
|
+
assert_equal original_object, reloaded_object, 'Safe reload with Symbol class specified'
|
92
|
+
|
93
|
+
if Psych::VERSION.start_with?('3.')
|
94
|
+
# Not supported with Ruby >= 3.1 unless you force psych version < 4
|
95
|
+
self.yaml_safe_classes = :unsafe
|
96
|
+
reloaded_object = load_yaml(yaml_produced)
|
97
|
+
assert_equal original_object, reloaded_object, 'Unsafe reload with Symbol class'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
61
101
|
test 'time-like objects should serialise correctly with psych' do
|
62
102
|
assert_timey_wimey_stuff
|
63
103
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ndr_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- NCRS Development Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|