commit 6aeeb605981c45654adf40c79aaf1327e5709982
Author: Aaron Patterson <aaron.patterson@gmail.com>
Date: Tue Aug 2 16:46:36 2011 -0700
prevent sql injection attacks by escaping quotes in column names
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 6f41f84..c50022b 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -238,7 +238,7 @@ module ActiveRecord
end
def quote_column_name(name) #:nodoc:
- @quoted_column_names[name] ||= "`#{name}`"
+ @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`"
end
def quote_table_name(name) #:nodoc:
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index 1616698..242f3f7 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -162,7 +162,7 @@ module ActiveRecord
end
def quote_column_name(name) #:nodoc:
- %Q("#{name}")
+ %Q("#{name.to_s.gsub('"', '""')}")
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index e9af77c..242be2a 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -79,6 +79,23 @@ end
class BasicsTest < ActiveRecord::TestCase
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts
+ def test_column_names_are_escaped
+ conn = ActiveRecord::Base.connection
+ classname = conn.class.name[/[^:]*$/]
+ badchar = {
+ 'SQLite3Adapter' => '"',
+ 'MysqlAdapter' => '`',
+ 'Mysql2Adapter' => '`',
+ 'PostgreSQLAdapter' => '"',
+ 'OracleAdapter' => '"',
+ }.fetch(classname) {
+ raise "need a bad char for #{classname}"
+ }
+
+ quoted = conn.quote_column_name "foo#{badchar}bar"
+ assert_equal("#{badchar}foo#{badchar * 2}bar#{badchar}", quoted)
+ end
+
def test_table_exists
assert !NonExistentTable.table_exists?
assert Topic.table_exists?