aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2012-10-05 19:23:25 +0100
committerJon Leighton <j@jonathanleighton.com>2012-10-12 11:49:13 +0100
commit9e5f7cc62e9ef1e865c6eba28be69e935434f8e6 (patch)
tree3a7ae51ae10359f58854f549d16c08db28c852fd /activerecord
parent36360e9bb959f226380ee7c660651b27b3a53d18 (diff)
downloadrails-9e5f7cc62e9ef1e865c6eba28be69e935434f8e6.tar.gz
rails-9e5f7cc62e9ef1e865c6eba28be69e935434f8e6.tar.bz2
rails-9e5f7cc62e9ef1e865c6eba28be69e935434f8e6.zip
Revert "Key the attributes hash with symbols"
This reverts commit 86c3dfbd47cb96af02daaa655963292b1a1b110e. Conflicts: activerecord/lib/active_record/attribute_methods/read.rb Reason: whilst this increased performance, it also presents a DoS risk via memory exhaustion if users were allowing user input to dictate the arguments of read/write_attribute. I will investigate alternative ways to cut down on string allocations here.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/attribute_methods/read.rb14
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb4
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb4
4 files changed, 10 insertions, 14 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 6213b5dcd5..a26c5e0f5b 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -46,7 +46,7 @@ module ActiveRecord
def define_method_attribute(attr_name)
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
def __temp__
- read_attribute(:'#{attr_name}') { |n| missing_attribute(n, caller) }
+ read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }
end
alias_method '#{attr_name}', :__temp__
undef_method :__temp__
@@ -70,17 +70,13 @@ module ActiveRecord
# it has been typecast (for example, "2004-12-12" in a data column is cast
# to a date object, like Date.new(2004, 12, 12)).
def read_attribute(attr_name)
- return unless attr_name
- name_sym = attr_name.to_sym
-
# If it's cached, just return it
# We use #[] first as a perf optimization for non-nil values. See https://gist.github.com/3552829.
- @attributes_cache[name_sym] || @attributes_cache.fetch(name_sym) {
- name = attr_name.to_s
-
+ name = attr_name.to_s
+ @attributes_cache[name] || @attributes_cache.fetch(name) {
column = @columns_hash.fetch(name) {
return @attributes.fetch(name) {
- if name_sym == :id && self.class.primary_key != name
+ if name == 'id' && self.class.primary_key != name
read_attribute(self.class.primary_key)
end
}
@@ -91,7 +87,7 @@ module ActiveRecord
}
if self.class.cache_attribute?(name)
- @attributes_cache[name_sym] = column.type_cast(value)
+ @attributes_cache[name] = column.type_cast(value)
else
column.type_cast value
end
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 b9a69cdb0a..f36a5806a9 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -50,7 +50,7 @@ module ActiveRecord
if (rounded_value != rounded_time) || (!rounded_value && original_time)
write_attribute("#{attr_name}", original_time)
#{attr_name}_will_change!
- @attributes_cache[:"#{attr_name}"] = zoned_time
+ @attributes_cache["#{attr_name}"] = zoned_time
end
end
EOV
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index 6eb9e25fd9..fa9097db1f 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -26,13 +26,13 @@ module ActiveRecord
def write_attribute(attr_name, value)
attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
- @attributes_cache.delete(attr_name.to_sym)
+ @attributes_cache.delete(attr_name)
column = column_for_attribute(attr_name)
# If we're dealing with a binary column, write the data to the cache
# so we don't attempt to typecast multiple times.
if column && column.binary?
- @attributes_cache[attr_name.to_sym] = value
+ @attributes_cache[attr_name] = value
end
if column || @attributes.has_key?(attr_name)
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index d08b157011..c2b58fd7d1 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -542,10 +542,10 @@ class AttributeMethodsTest < ActiveRecord::TestCase
val = t.send attr_name unless attr_name == "type"
if attribute_gets_cached
assert cached_columns.include?(attr_name)
- assert_equal val, cache[attr_name.to_sym]
+ assert_equal val, cache[attr_name]
else
assert uncached_columns.include?(attr_name)
- assert !cache.include?(attr_name.to_sym)
+ assert !cache.include?(attr_name)
end
end
end