Skip to content

Commit

Permalink
Backport offset/limit SQL injection fix to 2-0-stable
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information
jonleighton authored and NZKoz committed Sep 23, 2008
1 parent 760d525 commit 213f315
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 3 deletions.
Expand Up @@ -106,11 +106,16 @@ def add_limit!(sql, options)
# SELECT * FROM suppliers LIMIT 10 OFFSET 50
def add_limit_offset!(sql, options)
if limit = options[:limit]
sql << " LIMIT #{limit}"
sql << " LIMIT #{sanitize_limit(limit)}"
if offset = options[:offset]
sql << " OFFSET #{offset}"
sql << " OFFSET #{offset.to_i}"
end
end
sql
end

def sanitize_limit(limit)
limit.to_s[/,/] ? limit.split(',').map{ |i| i.to_i }.join(',') : limit.to_i
end

# Appends a locking clause to an SQL statement.
Expand Down
Expand Up @@ -318,10 +318,11 @@ def rollback_db_transaction #:nodoc:

def add_limit_offset!(sql, options) #:nodoc:
if limit = options[:limit]
limit = sanitize_limit(limit)
unless offset = options[:offset]
sql << " LIMIT #{limit}"
else
sql << " LIMIT #{offset}, #{limit}"
sql << " LIMIT #{offset.to_i}, #{limit}"
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions activerecord/test/adapter_test.rb
Expand Up @@ -103,4 +103,24 @@ def test_reset_table_with_non_integer_pk
end
end

def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
sql_inject = "1 select * from schema"
assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit=>sql_inject)
if current_adapter?(:MysqlAdapter)
assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
else
assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
end
end

def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
sql_inject = "1, 7 procedure help()"
if current_adapter?(:MysqlAdapter)
assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=> '1 ; DROP TABLE USERS', :offset=>7)
else
assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
end
end
end

0 comments on commit 213f315

Please sign in to comment.