Skip to content

Commit 6ab44be

Browse files
authored
Merge commit from fork
* PYTHON-5996 Harden bson buffer size guard against signed integer overflow * PYTHON-5996 Add changelog entry * remove changelog entry for now * Update doc/changelog.rst * Update doc/changelog.rst * Update doc/changelog.rst * Update doc/changelog.rst
1 parent 44119d0 commit 6ab44be

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

‎bson/buffer.c‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define PY_SSIZE_T_CLEAN
1919
#include "Python.h"
2020

21+
#include <limits.h>
2122
#include <stdlib.h>
2223
#include <string.h>
2324

@@ -105,18 +106,25 @@ static int buffer_grow(buffer_t buffer, int min_length) {
105106
* Return non-zero and sets MemoryError on allocation failure.
106107
* Return non-zero and sets ValueError if `size` would exceed 2GiB. */
107108
static int buffer_assure_space(buffer_t buffer, int size) {
108-
int new_size = buffer->position + size;
109-
/* Check for overflow. */
110-
if (new_size < buffer->position) {
109+
long long new_size;
110+
if (size < 0) {
111111
PyErr_SetString(PyExc_ValueError,
112112
"Document would overflow BSON size limit");
113113
return 1;
114114
}
115115

116-
if (new_size <= buffer->size) {
116+
/* Compute in a wider type so the addition cannot overflow `int`. */
117+
new_size = (long long)buffer->position + (long long)size;
118+
if (new_size > INT_MAX) {
119+
PyErr_SetString(PyExc_ValueError,
120+
"Document would overflow BSON size limit");
121+
return 1;
122+
}
123+
124+
if ((int)new_size <= buffer->size) {
117125
return 0;
118126
}
119-
return buffer_grow(buffer, new_size);
127+
return buffer_grow(buffer, (int)new_size);
120128
}
121129

122130
/* Save `size` bytes from the current position in `buffer` (and grow if needed).

‎test/test_bson.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,14 @@ def test_overflow(self):
691691
self.assertTrue(encode({"x": -9223372036854775808}))
692692
self.assertRaises(OverflowError, encode, {"x": -9223372036854775809})
693693

694+
@unittest.skipUnless(bson.has_c(), "This test requires the C extension")
695+
def test_encode_size_limit(self):
696+
# PYTHON-5996: encoding must raise when a document's encoded size
697+
# exceeds the BSON size limit.
698+
big_value = "a" * (1 << 30)
699+
with self.assertRaises(ValueError):
700+
encode({"a": big_value, "b": big_value, "c": big_value})
701+
694702
def test_small_long_encode_decode(self):
695703
encoded1 = encode({"x": 256})
696704
decoded1 = decode(encoded1)["x"]

0 commit comments

Comments
 (0)