Skip to content

Commit 568a3b1

Browse files
authored
PYTHON-4084 Fix BSON inflation for RawBSONDocument (#1456)
1 parent 8422edf commit 568a3b1

File tree

3 files changed

+20
-34
lines changed

3 files changed

+20
-34
lines changed

bson/_cbsonmodule.c

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,19 +1878,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
18781878
goto invalid;
18791879
}
18801880

1881-
if (options->is_raw_bson) {
1882-
value = PyObject_CallFunction(
1883-
options->document_class, "y#O",
1884-
buffer + *position, (Py_ssize_t)size, options->options_obj);
1885-
if (!value) {
1886-
goto invalid;
1887-
}
1888-
*position += size;
1889-
break;
1890-
}
1891-
1892-
value = elements_to_dict(self, buffer + *position + 4,
1893-
size - 5, options);
1881+
value = elements_to_dict(self, buffer + *position,
1882+
size, options);
18941883
if (!value) {
18951884
goto invalid;
18961885
}
@@ -2456,8 +2445,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
24562445
if (buffer[*position + scope_size - 1]) {
24572446
goto invalid;
24582447
}
2459-
scope = elements_to_dict(self, buffer + *position + 4,
2460-
scope_size - 5, options);
2448+
scope = elements_to_dict(self, buffer + *position,
2449+
scope_size, options);
24612450
if (!scope) {
24622451
Py_DECREF(code);
24632452
goto invalid;
@@ -2809,9 +2798,14 @@ static PyObject* elements_to_dict(PyObject* self, const char* string,
28092798
unsigned max,
28102799
const codec_options_t* options) {
28112800
PyObject* result;
2801+
if (options->is_raw_bson) {
2802+
return PyObject_CallFunction(
2803+
options->document_class, "y#O",
2804+
string, max, options->options_obj);
2805+
}
28122806
if (Py_EnterRecursiveCall(" while decoding a BSON document"))
28132807
return NULL;
2814-
result = _elements_to_dict(self, string, max, options);
2808+
result = _elements_to_dict(self, string + 4, max - 5, options);
28152809
Py_LeaveRecursiveCall();
28162810
return result;
28172811
}
@@ -2902,15 +2896,7 @@ static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) {
29022896
goto done;
29032897
}
29042898

2905-
/* No need to decode fields if using RawBSONDocument */
2906-
if (options.is_raw_bson) {
2907-
result = PyObject_CallFunction(
2908-
options.document_class, "y#O", string, (Py_ssize_t)size,
2909-
options_obj);
2910-
}
2911-
else {
2912-
result = elements_to_dict(self, string + 4, (unsigned)size - 5, &options);
2913-
}
2899+
result = elements_to_dict(self, string, (unsigned)size, &options);
29142900
done:
29152901
PyBuffer_Release(&view);
29162902
destroy_codec_options(&options);
@@ -2988,14 +2974,7 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
29882974
goto fail;
29892975
}
29902976

2991-
/* No need to decode fields if using RawBSONDocument. */
2992-
if (options.is_raw_bson) {
2993-
dict = PyObject_CallFunction(
2994-
options.document_class, "y#O", string, (Py_ssize_t)size,
2995-
options_obj);
2996-
} else {
2997-
dict = elements_to_dict(self, string + 4, (unsigned)size - 5, &options);
2998-
}
2977+
dict = elements_to_dict(self, string, (unsigned)size, &options);
29992978
if (!dict) {
30002979
Py_DECREF(result);
30012980
goto fail;

doc/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ PyMongo 4.7 brings a number of improvements including:
1010
:attr:`pymongo.monitoring.CommandStartedEvent.server_connection_id`,
1111
:attr:`pymongo.monitoring.CommandSucceededEvent.server_connection_id`, and
1212
:attr:`pymongo.monitoring.CommandFailedEvent.server_connection_id` properties.
13+
- Fixed a bug where inflating a :class:`~bson.raw_bson.RawBSONDocument` containing a :class:`~bson.code.Code` would cause an error.
1314

1415
Changes in Version 4.6.1
1516
------------------------

test/test_raw_bson.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from test import client_context, unittest
2323
from test.test_client import IntegrationTest
2424

25-
from bson import decode, encode
25+
from bson import Code, decode, encode
2626
from bson.binary import JAVA_LEGACY, Binary, UuidRepresentation
2727
from bson.codec_options import CodecOptions
2828
from bson.errors import InvalidBSON
@@ -199,6 +199,12 @@ def test_preserve_key_ordering(self):
199199
for rkey, elt in zip(rawdoc, keyvaluepairs):
200200
self.assertEqual(rkey, elt[0])
201201

202+
def test_contains_code_with_scope(self):
203+
doc = RawBSONDocument(encode({"value": Code("x=1", scope={})}))
204+
205+
self.assertEqual(decode(encode(doc)), {"value": Code("x=1", {})})
206+
self.assertEqual(doc["value"].scope, RawBSONDocument(encode({})))
207+
202208

203209
if __name__ == "__main__":
204210
unittest.main()

0 commit comments

Comments
 (0)