don't allow NULL byte in key names in ruby encoder

This commit is contained in:
Mike Dirolf 2009-12-17 10:05:38 -05:00
parent f9fb823c53
commit 5168692ab9
2 changed files with 27 additions and 12 deletions

View File

@ -72,6 +72,11 @@ class BSON_RUBY
buf.put_array(to_utf8(val.to_s).unpack("C*") << 0) buf.put_array(to_utf8(val.to_s).unpack("C*") << 0)
end end
def self.serialize_key(buf, key)
raise InvalidDocument, "Key names must not contain the NULL byte" if key.include? 0
self.serialize_cstr(buf, key)
end
def to_a def to_a
@buf.to_a @buf.to_a
end end
@ -365,7 +370,7 @@ class BSON_RUBY
def serialize_null_element(buf, key) def serialize_null_element(buf, key)
buf.put(NULL) buf.put(NULL)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
end end
def serialize_dbref_element(buf, key, val) def serialize_dbref_element(buf, key, val)
@ -377,7 +382,7 @@ class BSON_RUBY
def serialize_binary_element(buf, key, val) def serialize_binary_element(buf, key, val)
buf.put(BINARY) buf.put(BINARY)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
bytes = val.to_a bytes = val.to_a
num_bytes = bytes.length num_bytes = bytes.length
@ -396,13 +401,13 @@ class BSON_RUBY
def serialize_boolean_element(buf, key, val) def serialize_boolean_element(buf, key, val)
buf.put(BOOLEAN) buf.put(BOOLEAN)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
buf.put(val ? 1 : 0) buf.put(val ? 1 : 0)
end end
def serialize_date_element(buf, key, val) def serialize_date_element(buf, key, val)
buf.put(DATE) buf.put(DATE)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
millisecs = (val.to_f * 1000).to_i millisecs = (val.to_f * 1000).to_i
buf.put_long(millisecs) buf.put_long(millisecs)
end end
@ -410,7 +415,7 @@ class BSON_RUBY
def serialize_number_element(buf, key, val, type) def serialize_number_element(buf, key, val, type)
if type == NUMBER if type == NUMBER
buf.put(type) buf.put(type)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
buf.put_double(val) buf.put_double(val)
else else
if val > 2**64 / 2 - 1 or val < -2**64 / 2 if val > 2**64 / 2 - 1 or val < -2**64 / 2
@ -418,11 +423,11 @@ class BSON_RUBY
end end
if val > 2**32 / 2 - 1 or val < -2**32 / 2 if val > 2**32 / 2 - 1 or val < -2**32 / 2
buf.put(NUMBER_LONG) buf.put(NUMBER_LONG)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
buf.put_long(val) buf.put_long(val)
else else
buf.put(type) buf.put(type)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
buf.put_int(val) buf.put_int(val)
end end
end end
@ -430,7 +435,7 @@ class BSON_RUBY
def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT) def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT)
buf.put(opcode) buf.put(opcode)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
buf.put_array(BSON.new.serialize(val, check_keys).to_a) buf.put_array(BSON.new.serialize(val, check_keys).to_a)
end end
@ -444,7 +449,7 @@ class BSON_RUBY
def serialize_regex_element(buf, key, val) def serialize_regex_element(buf, key, val)
buf.put(REGEX) buf.put(REGEX)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
str = val.to_s.sub(/.*?:/, '')[0..-2] # Turn "(?xxx:yyy)" into "yyy" str = val.to_s.sub(/.*?:/, '')[0..-2] # Turn "(?xxx:yyy)" into "yyy"
self.class.serialize_cstr(buf, str) self.class.serialize_cstr(buf, str)
@ -461,14 +466,14 @@ class BSON_RUBY
def serialize_oid_element(buf, key, val) def serialize_oid_element(buf, key, val)
buf.put(OID) buf.put(OID)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
buf.put_array(val.to_a) buf.put_array(val.to_a)
end end
def serialize_string_element(buf, key, val, type) def serialize_string_element(buf, key, val, type)
buf.put(type) buf.put(type)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
# Make a hole for the length # Make a hole for the length
len_pos = buf.position len_pos = buf.position
@ -488,7 +493,7 @@ class BSON_RUBY
def serialize_code_w_scope(buf, key, val) def serialize_code_w_scope(buf, key, val)
buf.put(CODE_W_SCOPE) buf.put(CODE_W_SCOPE)
self.class.serialize_cstr(buf, key) self.class.serialize_key(buf, key)
# Make a hole for the length # Make a hole for the length
len_pos = buf.position len_pos = buf.position

View File

@ -321,4 +321,14 @@ class BSONTest < Test::Unit::TestCase
assert_equal BSON.serialize(one).to_a, BSON.serialize(dup).to_a assert_equal BSON.serialize(one).to_a, BSON.serialize(dup).to_a
end end
def test_null_character
doc = {"a" => "\x00"}
assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a)
assert_raise InvalidDocument do
BSON.serialize({"\x00" => "a"})
end
end
end end