Skip to content

Commit f2a46a7

Browse files
authored
Serializer: reraise all .load errors as UnmarshalError (petergoldstein#1011)
* Serializer: for Marshal, catch all .load errors In order to avoid missing an error message to filter out, treat any Marshal.load error as a failed serialization, and trust Ruby's e.cause system to provide a lineage of the error's true beginning. * Treat all deserialization errors as UnmarshalError
1 parent 718cacb commit f2a46a7

File tree

2 files changed

+17
-90
lines changed

2 files changed

+17
-90
lines changed

lib/dalli/protocol/value_serializer.rb

+9-34
Original file line numberDiff line numberDiff line change
@@ -33,42 +33,17 @@ def store(value, req_options, bitflags)
3333
[store_value, bitflags]
3434
end
3535

36-
# TODO: Some of these error messages need to be validated. It's not obvious
37-
# that all of them are actually generated by the invoked code
38-
# in current systems
39-
# rubocop:disable Layout/LineLength
40-
TYPE_ERR_REGEXP = %r{needs to have method `_load'|exception class/object expected|instance of IO needed|incompatible marshal file format}.freeze
41-
ARGUMENT_ERR_REGEXP = /undefined class|marshal data too short/.freeze
42-
NAME_ERR_STR = 'uninitialized constant'
43-
# rubocop:enable Layout/LineLength
44-
4536
def retrieve(value, bitflags)
4637
serialized = (bitflags & FLAG_SERIALIZED) != 0
47-
serialized ? serializer.load(value) : value
48-
rescue TypeError => e
49-
filter_type_error(e)
50-
rescue ArgumentError => e
51-
filter_argument_error(e)
52-
rescue NameError => e
53-
filter_name_error(e)
54-
end
55-
56-
def filter_type_error(err)
57-
raise err unless TYPE_ERR_REGEXP.match?(err.message)
58-
59-
raise UnmarshalError, "Unable to unmarshal value: #{err.message}"
60-
end
61-
62-
def filter_argument_error(err)
63-
raise err unless ARGUMENT_ERR_REGEXP.match?(err.message)
64-
65-
raise UnmarshalError, "Unable to unmarshal value: #{err.message}"
66-
end
67-
68-
def filter_name_error(err)
69-
raise err unless err.message.include?(NAME_ERR_STR)
70-
71-
raise UnmarshalError, "Unable to unmarshal value: #{err.message}"
38+
if serialized
39+
begin
40+
serializer.load(value)
41+
rescue StandardError
42+
raise UnmarshalError, 'Unable to unmarshal value'
43+
end
44+
else
45+
value
46+
end
7247
end
7348

7449
def serializer

test/protocol/test_value_serializer.rb

+8-56
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@
181181
end
182182
end
183183

184-
assert_equal exception.message, "Unable to unmarshal value: #{error_message}"
184+
assert_equal exception.cause.message, error_message
185185
end
186186
end
187187

@@ -198,7 +198,7 @@
198198
end
199199
end
200200

201-
assert_equal exception.message, "Unable to unmarshal value: #{error_message}"
201+
assert_equal exception.cause.message, error_message
202202
end
203203
end
204204

@@ -212,7 +212,7 @@
212212
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
213213
end
214214

215-
assert_equal exception.message, "Unable to unmarshal value: #{error_message}"
215+
assert_equal exception.cause.message, error_message
216216
end
217217
end
218218

@@ -226,23 +226,7 @@
226226
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
227227
end
228228

229-
assert exception.message.start_with?("Unable to unmarshal value: #{error_message}")
230-
end
231-
end
232-
233-
describe 'when deserialization raises a TypeError with a non-matching message' do
234-
let(:error_message) { SecureRandom.hex(10) }
235-
let(:serializer) { Marshal }
236-
237-
it 're-raises TypeError' do
238-
error = ->(_arg) { raise TypeError, error_message }
239-
exception = serializer.stub :load, error do
240-
assert_raises TypeError do
241-
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
242-
end
243-
end
244-
245-
assert_equal error_message, exception.message
229+
assert exception.cause.message.start_with?(error_message)
246230
end
247231
end
248232

@@ -259,23 +243,7 @@
259243
end
260244
end
261245

262-
assert exception.message.start_with?("Unable to unmarshal value: #{error_message}")
263-
end
264-
end
265-
266-
describe 'when deserialization raises a NameError with a non-matching message' do
267-
let(:error_message) { SecureRandom.hex(10) }
268-
let(:serializer) { Marshal }
269-
270-
it 're-raises NameError' do
271-
error = ->(_arg) { raise NameError, error_message }
272-
exception = serializer.stub :load, error do
273-
assert_raises NameError do
274-
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
275-
end
276-
end
277-
278-
assert exception.message.start_with?(error_message)
246+
assert exception.cause.message.start_with?(error_message)
279247
end
280248
end
281249

@@ -289,7 +257,7 @@
289257
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
290258
end
291259

292-
assert_equal exception.message, "Unable to unmarshal value: #{error_message}"
260+
assert_equal exception.cause.message, error_message
293261
end
294262
end
295263

@@ -303,23 +271,7 @@
303271
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
304272
end
305273

306-
assert_equal exception.message, "Unable to unmarshal value: #{error_message}"
307-
end
308-
end
309-
310-
describe 'when deserialization raises an ArgumentError with a non-matching message' do
311-
let(:error_message) { SecureRandom.hex(10) }
312-
let(:serializer) { Marshal }
313-
314-
it 're-raises ArgumentError' do
315-
error = ->(_arg) { raise ArgumentError, error_message }
316-
exception = serializer.stub :load, error do
317-
assert_raises ArgumentError do
318-
vs.retrieve(raw_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
319-
end
320-
end
321-
322-
assert_equal exception.message, error_message
274+
assert_equal exception.cause.message, error_message
323275
end
324276
end
325277

@@ -334,7 +286,7 @@
334286
deserialized_value
335287
end
336288

337-
it 'raises UnmarshalError for non-seriaized data' do
289+
it 'raises UnmarshalError for non-serialized data' do
338290
assert_raises Dalli::UnmarshalError do
339291
vs.retrieve(:not_serialized_value, Dalli::Protocol::ValueSerializer::FLAG_SERIALIZED)
340292
end

0 commit comments

Comments
 (0)