test and fix for BSON w/ negative integers. raise RangeError for out of range ints
This commit is contained in:
parent
a9aa5e5271
commit
37d6e16fe7
@ -151,6 +151,10 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
|
|||||||
switch(TYPE(value)) {
|
switch(TYPE(value)) {
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
{
|
{
|
||||||
|
if (rb_funcall(value, rb_intern(">"), 1, INT2NUM(2147483647)) == Qtrue ||
|
||||||
|
rb_funcall(value, rb_intern("<"), 1, INT2NUM(-2147483648)) == Qtrue) {
|
||||||
|
rb_raise(rb_eRangeError, "MongoDB can only handle 4-byte ints - try converting to a double before saving");
|
||||||
|
}
|
||||||
write_name_and_type(buffer, key, 0x10);
|
write_name_and_type(buffer, key, 0x10);
|
||||||
VALUE as_f = rb_funcall(value, rb_intern("to_f"), 0);
|
VALUE as_f = rb_funcall(value, rb_intern("to_f"), 0);
|
||||||
int int_value = NUM2LL(as_f);
|
int int_value = NUM2LL(as_f);
|
||||||
|
@ -248,7 +248,10 @@ class BSON
|
|||||||
end
|
end
|
||||||
|
|
||||||
def deserialize_number_int_data(buf)
|
def deserialize_number_int_data(buf)
|
||||||
buf.get_int
|
# sometimes ruby makes me angry... why would the same code pack as signed
|
||||||
|
# but unpack as unsigned
|
||||||
|
unsigned = buf.get_int
|
||||||
|
unsigned >= 2**32 / 2 ? unsigned - 2**32 : unsigned
|
||||||
end
|
end
|
||||||
|
|
||||||
def deserialize_object_data(buf)
|
def deserialize_object_data(buf)
|
||||||
@ -387,6 +390,9 @@ class BSON
|
|||||||
if type == NUMBER
|
if type == NUMBER
|
||||||
buf.put_double(val)
|
buf.put_double(val)
|
||||||
else
|
else
|
||||||
|
if val > 2**32 / 2 - 1 or val < -2**32 / 2
|
||||||
|
raise RangeError.new "MongoDB can only handle 4-byte ints - try converting to a double before saving"
|
||||||
|
end
|
||||||
buf.put_int(val)
|
buf.put_int(val)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -36,6 +36,18 @@ class BSONTest < Test::Unit::TestCase
|
|||||||
doc = {'doc' => 42}
|
doc = {'doc' => 42}
|
||||||
@b.serialize(doc)
|
@b.serialize(doc)
|
||||||
assert_equal doc, @b.deserialize
|
assert_equal doc, @b.deserialize
|
||||||
|
|
||||||
|
doc = {"doc" => -5600}
|
||||||
|
@b.serialize(doc)
|
||||||
|
assert_equal doc, @b.deserialize
|
||||||
|
|
||||||
|
doc = {"doc" => 2147483647}
|
||||||
|
@b.serialize(doc)
|
||||||
|
assert_equal doc, @b.deserialize
|
||||||
|
|
||||||
|
doc = {"doc" => -2147483648}
|
||||||
|
@b.serialize(doc)
|
||||||
|
assert_equal doc, @b.deserialize
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ordered_hash
|
def test_ordered_hash
|
||||||
@ -195,6 +207,21 @@ class BSONTest < Test::Unit::TestCase
|
|||||||
0x00, 0x00, 0x00])
|
0x00, 0x00, 0x00])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_overflow
|
||||||
|
doc = {"x" => 2**45}
|
||||||
|
assert_raise RangeError do
|
||||||
|
@b.serialize(doc)
|
||||||
|
end
|
||||||
|
|
||||||
|
doc = {"x" => 2147483647}
|
||||||
|
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
||||||
|
|
||||||
|
doc["x"] = doc["x"] + 1
|
||||||
|
assert_raise RangeError do
|
||||||
|
@b.serialize(doc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_do_not_change_original_object
|
def test_do_not_change_original_object
|
||||||
val = OrderedHash.new
|
val = OrderedHash.new
|
||||||
val['not_id'] = 1
|
val['not_id'] = 1
|
||||||
|
Loading…
Reference in New Issue
Block a user