Skip to content

Commit a060c15

Browse files
author
A. Jesse Jiryu Davis
committed
Fix null pointer when decoding invalid DBRef PYTHON-532
1 parent a9d1457 commit a060c15

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

bson/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def _get_object(data, position, as_class, tz_aware, uuid_subtype):
150150
object = _elements_to_dict(encoded, as_class, tz_aware, uuid_subtype)
151151
position += obj_size
152152
if "$ref" in object:
153-
return (DBRef(object.pop("$ref"), object.pop("$id"),
153+
return (DBRef(object.pop("$ref"), object.pop("$id", None),
154154
object.pop("$db", None), object), position)
155155
return object, position
156156

bson/_cbsonmodule.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,8 +1202,14 @@ static PyObject* get_value(PyObject* self, const char* buffer, int* position,
12021202

12031203
Py_INCREF(collection);
12041204
PyDict_DelItemString(value, "$ref");
1205-
Py_INCREF(id);
1206-
PyDict_DelItemString(value, "$id");
1205+
1206+
if (id == NULL) {
1207+
id = Py_None;
1208+
Py_INCREF(id);
1209+
} else {
1210+
Py_INCREF(id);
1211+
PyDict_DelItemString(value, "$id");
1212+
}
12071213

12081214
if (database == NULL) {
12091215
database = Py_None;

test/test_collection.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from bson.binary import Binary, UUIDLegacy, OLD_UUID_SUBTYPE, UUID_SUBTYPE
3232
from bson.code import Code
33+
from bson.dbref import DBRef
3334
from bson.objectid import ObjectId
3435
from bson.py3compat import b
3536
from bson.son import SON
@@ -1675,6 +1676,31 @@ def test_bad_encode(self):
16751676
self.assertRaises(InvalidDocument, c.save, {"x": c})
16761677
warnings.simplefilter("default")
16771678

1679+
def test_bad_dbref(self):
1680+
c = self.db.test
1681+
c.drop()
1682+
1683+
# Incomplete DBRefs.
1684+
self.assertRaises(
1685+
InvalidDocument,
1686+
c.insert, {'ref': {'$ref': 'collection'}})
1687+
1688+
self.assertRaises(
1689+
InvalidDocument,
1690+
c.insert, {'ref': {'$id': ObjectId()}})
1691+
1692+
ref_only = {'ref': {'$ref': 'collection'}}
1693+
id_only = {'ref': {'$id': ObjectId()}}
1694+
1695+
# Force insert of ref without $id.
1696+
c.insert(ref_only, check_keys=False)
1697+
self.assertEqual(DBRef('collection', id=None), c.find_one()['ref'])
1698+
c.drop()
1699+
1700+
# DBRef without $ref is decoded as normal subdocument.
1701+
c.insert(id_only, check_keys=False)
1702+
self.assertEqual(id_only, c.find_one())
1703+
16781704
def test_as_class(self):
16791705
c = self.db.test
16801706
c.drop()

0 commit comments

Comments
 (0)