提交 e62fff40 编写于 作者: S Sean Griffin

Treat strings greater than int max value as out of range

Sufficiently large integers cause `find` and `find_by` to raise
`StatementInvalid` instead of `RecordNotFound` or just returning `nil`.
Given that we can't cast to `nil` for `Integer` like we would with junk
data for other types, we raise a `RangeError` instead, and rescue in
places where it would be highly unexpected to get an exception from
casting.

Fixes #17380
上级 9b9f0197
......@@ -155,6 +155,8 @@ def find(*ids)
raise RecordNotFound, "Couldn't find #{name} with '#{primary_key}'=#{id}"
end
record
rescue RangeError
raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
end
def find_by(*args)
......@@ -185,6 +187,8 @@ def find_by(*args)
s.execute(hash.values, self, connection).first
rescue TypeError => e
raise ActiveRecord::StatementInvalid.new(e.message, e)
rescue RangeError
nil
end
end
......
......@@ -433,6 +433,8 @@ def find_with_ids(*ids)
else
find_some(ids)
end
rescue RangeError
raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID"
end
def find_one(id)
......
......@@ -4,6 +4,7 @@
require 'active_record/type/time_value'
require 'active_record/type/value'
require 'active_record/type/big_integer'
require 'active_record/type/binary'
require 'active_record/type/boolean'
require 'active_record/type/date'
......
require 'active_record/type/integer'
module ActiveRecord
module Type
class BigInteger < Integer # :nodoc:
private
def max_value
::Float::INFINITY
end
end
end
end
require 'active_record/type/integer'
require 'active_record/type/big_integer'
module ActiveRecord
module Type
class DecimalWithoutScale < Integer # :nodoc:
class DecimalWithoutScale < BigInteger # :nodoc:
def type
:decimal
end
......
......@@ -15,9 +15,28 @@ def cast_value(value)
case value
when true then 1
when false then 0
else value.to_i rescue nil
else
result = value.to_i rescue nil
ensure_below_max(result) if result
result
end
end
def ensure_below_max(value)
if value > max_value
raise RangeError, "#{value} is too large for #{self.class} with limit #{limit || 4}"
end
end
def max_value
@max_value = determine_max_value unless defined?(@max_value)
@max_value
end
def determine_max_value
limit = self.limit || 4
2 << (limit * 8 - 1) # 8 bits per byte with one bit for sign
end
end
end
end
......@@ -985,7 +985,6 @@ def test_geometric_content
class NumericData < ActiveRecord::Base
self.table_name = 'numeric_data'
attribute :world_population, Type::Integer.new
attribute :my_house_population, Type::Integer.new
attribute :atoms_in_universe, Type::Integer.new
end
......
......@@ -99,21 +99,10 @@ def test_exists_passing_active_record_object_is_deprecated
end
def test_exists_fails_when_parameter_has_invalid_type
if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter)
assert_raises ActiveRecord::StatementInvalid do
Topic.exists?(("9"*53).to_i) # number that's bigger than int
end
else
assert_raises(RangeError) do
assert_equal false, Topic.exists?(("9"*53).to_i) # number that's bigger than int
end
if current_adapter?(:PostgreSQLAdapter)
assert_raises ActiveRecord::StatementInvalid do
Topic.exists?("foo")
end
else
assert_equal false, Topic.exists?("foo")
end
assert_equal false, Topic.exists?("foo")
end
def test_exists_does_not_select_columns_without_alias
......@@ -209,6 +198,18 @@ def test_find_by_ids_with_limit_and_offset
assert_equal 2, last_devs.size
end
def test_find_with_large_number
assert_raises(ActiveRecord::RecordNotFound) { Topic.find('9999999999999999999999999999999') }
end
def test_find_by_with_large_number
assert_nil Topic.find_by(id: '9999999999999999999999999999999')
end
def test_find_by_id_with_large_number
assert_nil Topic.find_by_id('9999999999999999999999999999999')
end
def test_find_an_empty_array
assert_equal [], Topic.find([])
end
......
......@@ -15,7 +15,6 @@ class BigNumber < ActiveRecord::Base
unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
attribute :value_of_e, Type::Integer.new
end
attribute :world_population, Type::Integer.new
attribute :my_house_population, Type::Integer.new
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册