Skip to content

Commit e59a21f

Browse files
Add remaining-buffer bound check in _array_of_documents_to_buffer
In `_cbson_array_of_documents_to_buffer`, the per-element embedded-document length `value_length` (read from server-controlled raw-batch BSON bytes) was checked only for a lower bound (`value_length < BSON_MIN_SIZE`) before being passed to `pymongo_buffer_write(buffer, string + position, value_length)`, which calls `memcpy` from the source buffer. There was no upper-bound check that `value_length` fits within the remaining array bytes, so a crafted reply (firstBatch/nextBatch) with an oversized inner `value_length` causes an out-of-bounds read from the heap. The pure-Python twin `_get_object_size` in `bson/__init__.py` already validates this invariant; the C fast-path dropped it. This commit adds the missing guard immediately before the `pymongo_buffer_write` call, mirroring the adjacent error-handling style and the existing lower-bound block. The loop already guarantees `position < size` and `(size - position) >= BSON_MIN_SIZE` via the prior check, so the subtraction `size - position` is safe (no uint32 underflow). The bug is reachable from `Collection.find_raw_batches()` and `aggregate_raw_batches()` when the driver connects to a malicious or compromised server. It belongs to the same bug class as CVE-2024-5629 (OOB read in the bson C extension, fixed in 4.6.3) but affects a different function. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3405791 commit e59a21f

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

‎bson/_cbsonmodule.c‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,6 +3238,15 @@ static PyObject* _cbson_array_of_documents_to_buffer(PyObject* self, PyObject* a
32383238
goto fail;
32393239
}
32403240

3241+
if (value_length > (uint32_t)(size - position)) {
3242+
PyObject* InvalidBSON = _error("InvalidBSON");
3243+
if (InvalidBSON) {
3244+
PyErr_SetString(InvalidBSON, "invalid array content");
3245+
Py_DECREF(InvalidBSON);
3246+
}
3247+
goto fail;
3248+
}
3249+
32413250
if (pymongo_buffer_write(buffer, string + position, value_length) == 1) {
32423251
goto fail;
32433252
}

0 commit comments

Comments
 (0)