aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test
diff options
context:
space:
mode:
authorAaron Lipman <alipman88@gmail.com>2019-07-08 13:55:28 -0400
committerAaron Lipman <alipman88@gmail.com>2019-07-17 23:22:39 -0400
commit722c45f64110be876d83e7f9a22592aa954886c1 (patch)
tree2d571f742c934e2a4ca1e08aacca1ed8443f93af /activesupport/test
parentc5a24c8ebba543687c11f893584618a20316fe34 (diff)
downloadrails-722c45f64110be876d83e7f9a22592aa954886c1.tar.gz
rails-722c45f64110be876d83e7f9a22592aa954886c1.tar.bz2
rails-722c45f64110be876d83e7f9a22592aa954886c1.zip
Omit marshal_dump & _dump from delegate_missing_to
Exclude missing marshal_dump and _dump methods from being delegated to an object's delegation target via the delegate_missing_to extension. This avoids unintentionally adding instance variables to an object during marshallization, should the delegation target be a method which would otherwise add them. In current versions of Ruby, a bug exists in the way objects are marshalled, allowing for instance variables to be added or removed during marshallization (see https://bugs.ruby-lang.org/issues/15968). This results in a corrupted serialized byte stream, causing an object's instance variables to "leak" into subsequent serialized objects during demarshallization. In Rails, this behavior may be triggered when marshalling an object that uses the delegate_missing_to extension, if the delegation target is a method which adds or removes instance variables to an object being marshalled - when calling Marshal.dump(object), Ruby's built in behavior will check whether the object responds to :marshal_dump or :_dump, which in turn triggers the delegation target method in the responds_to_missing? function defined in activesupport/lib/active_support/core_ext/module/delegation.rb While future versions of Ruby will resolve this bug by raising a RuntimeError, the underlying cause of this error may not be readily apparent when encountered by Rails developers. By excluding marshal_dump and _dump from being delegated to an object's target, this commit eliminates a potential cause of unexpected behavior and/or RuntimeErrors. Fixes #36522
Diffstat (limited to 'activesupport/test')
-rw-r--r--activesupport/test/core_ext/module_test.rb29
1 files changed, 29 insertions, 0 deletions
diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb
index ec9ecd06ee..dd36a9373a 100644
--- a/activesupport/test/core_ext/module_test.rb
+++ b/activesupport/test/core_ext/module_test.rb
@@ -111,6 +111,24 @@ class DecoratedReserved
end
end
+class Maze
+ attr_accessor :cavern, :passages
+end
+
+class Cavern
+ delegate_missing_to :target
+
+ attr_reader :maze
+
+ def initialize(maze)
+ @maze = maze
+ end
+
+ def target
+ @maze.passages = :twisty
+ end
+end
+
class Block
def hello?
true
@@ -411,6 +429,17 @@ class ModuleTest < ActiveSupport::TestCase
assert_respond_to DecoratedTester.new(@david), :extra_missing
end
+ def test_delegate_missing_to_does_not_interfere_with_marshallization
+ maze = Maze.new
+ maze.cavern = Cavern.new(maze)
+
+ array = [maze, nil]
+ serialized_array = Marshal.dump(array)
+ deserialized_array = Marshal.load(serialized_array)
+
+ assert_nil deserialized_array[1]
+ end
+
def test_delegate_with_case
event = Event.new(Tester.new)
assert_equal 1, event.foo