aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/attribute_methods
diff options
context:
space:
mode:
authorSean Griffin <sean@seantheprogrammer.com>2016-02-02 09:15:47 -0700
committerSean Griffin <sean@seantheprogrammer.com>2016-02-02 09:17:45 -0700
commit5bb26008ce7c979a87f0d8aef0dd10514838787f (patch)
tree20f719bc4ce22cd30e252b37280780b500157303 /activerecord/lib/active_record/attribute_methods
parentf7775c74d0a9462e89325b145f1aafd029646ba6 (diff)
downloadrails-5bb26008ce7c979a87f0d8aef0dd10514838787f.tar.gz
rails-5bb26008ce7c979a87f0d8aef0dd10514838787f.tar.bz2
rails-5bb26008ce7c979a87f0d8aef0dd10514838787f.zip
Avoid infinite recursion when bad values are passed to tz aware fields
We had previously updated this to attempt to map over whatever was passed in, so that additional types like range and array could benefit from this behavior without the time zone converter having to deal with every known type. However, the default behavior of a type is to just yield the given value to `map`, which means that if we don't actually know how to handle a value, we'll just recurse infinitely. Since both uses of `map` in this case occur in cases where we know receiving the same object will recurse, we can just break on reference equality. Fixes #23241.
Diffstat (limited to 'activerecord/lib/active_record/attribute_methods')
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb14
1 files changed, 12 insertions, 2 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index 061628725d..6d345689fa 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -20,7 +20,7 @@ module ActiveRecord
nil
end
else
- map(super) { |t| cast(t) }
+ map_avoiding_infinite_recursion(super) { |v| cast(v) }
end
end
@@ -34,13 +34,23 @@ module ActiveRecord
elsif value.is_a?(::Float)
value
else
- map(value) { |v| convert_time_to_time_zone(v) }
+ map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
end
end
def set_time_zone_without_conversion(value)
::Time.zone.local_to_utc(value).in_time_zone
end
+
+ def map_avoiding_infinite_recursion(value)
+ map(value) do |v|
+ if value.equal?(v)
+ nil
+ else
+ yield(value)
+ end
+ end
+ end
end
extend ActiveSupport::Concern