21
21
#include <bson/bson-json-private.h>
22
22
#include <common-string-private.h>
23
23
#include <common-json-private.h>
24
+ #include <common-macros-private.h>
24
25
#include <bson/bson-iso8601-private.h>
25
26
26
27
#include <string.h>
@@ -60,6 +61,31 @@ typedef struct {
60
61
*/
61
62
static const uint8_t gZero ;
62
63
64
+ /*
65
+ *--------------------------------------------------------------------------
66
+ *
67
+ * _bson_next_power_of_two_for_alloc --
68
+ *
69
+ * Given a potential allocation length no greater than BSON_MAX_SIZE,
70
+ * round it up to the next power of two without exceeding BSON_MAX_SIZE.
71
+ *
72
+ * Returns:
73
+ * A value >= the input size and <= BSON_MAX_SIZE.
74
+ *
75
+ * Side effects:
76
+ * None.
77
+ *
78
+ *--------------------------------------------------------------------------
79
+ */
80
+
81
+ static BSON_INLINE size_t
82
+ _bson_next_power_of_two_for_alloc (size_t size )
83
+ {
84
+ MONGOC_DEBUG_ASSERT (size <= BSON_MAX_SIZE );
85
+ size_t power_of_two = bson_next_power_of_two (size );
86
+ return BSON_MIN (power_of_two , BSON_MAX_SIZE );
87
+ }
88
+
63
89
/*
64
90
*--------------------------------------------------------------------------
65
91
*
@@ -90,7 +116,7 @@ _bson_impl_inline_grow (bson_impl_inline_t *impl, /* IN */
90
116
return true;
91
117
}
92
118
93
- req = bson_next_power_of_two (impl -> len + size );
119
+ req = _bson_next_power_of_two_for_alloc (impl -> len + size );
94
120
95
121
if (req <= BSON_MAX_SIZE ) {
96
122
data = bson_malloc (req );
@@ -150,7 +176,7 @@ _bson_impl_alloc_grow (bson_impl_alloc_t *impl, /* IN */
150
176
return true;
151
177
}
152
178
153
- req = bson_next_power_of_two (req );
179
+ req = _bson_next_power_of_two_for_alloc (req );
154
180
155
181
if ((req <= BSON_MAX_SIZE ) && impl -> realloc ) {
156
182
* impl -> buf = impl -> realloc (* impl -> buf , req , impl -> realloc_func_ctx );
@@ -168,7 +194,8 @@ _bson_impl_alloc_grow (bson_impl_alloc_t *impl, /* IN */
168
194
* _bson_grow --
169
195
*
170
196
* Grows the bson_t structure to be large enough to contain @size
171
- * bytes.
197
+ * bytes in addition to its current content. The caller is responsible
198
+ * for ensuring the new summed size is <= BSON_MAX_SIZE.
172
199
*
173
200
* Returns:
174
201
* true if successful, false if the size would overflow.
@@ -183,6 +210,9 @@ static bool
183
210
_bson_grow (bson_t * bson , /* IN */
184
211
uint32_t size ) /* IN */
185
212
{
213
+ // Already checked by caller in all build types
214
+ MONGOC_DEBUG_ASSERT ((size_t ) bson -> len <= BSON_MAX_SIZE && (size_t ) size <= BSON_MAX_SIZE - (size_t ) bson -> len );
215
+
186
216
if ((bson -> flags & BSON_FLAG_INLINE )) {
187
217
return _bson_impl_inline_grow ((bson_impl_inline_t * ) bson , size );
188
218
}
@@ -2097,7 +2127,7 @@ bson_copy_to (const bson_t *src, bson_t *dst)
2097
2127
}
2098
2128
2099
2129
data = _bson_data (src );
2100
- len = bson_next_power_of_two ((size_t ) src -> len );
2130
+ len = _bson_next_power_of_two_for_alloc ((size_t ) src -> len );
2101
2131
2102
2132
adst = (bson_impl_alloc_t * ) dst ;
2103
2133
adst -> flags = BSON_FLAG_STATIC ;
@@ -2219,6 +2249,10 @@ bson_reserve_buffer (bson_t *bson, uint32_t size)
2219
2249
return NULL ;
2220
2250
}
2221
2251
2252
+ MONGOC_DEBUG_ASSERT ((size_t ) bson -> len <= BSON_MAX_SIZE );
2253
+ if ((size_t ) size > BSON_MAX_SIZE - (size_t ) bson -> len ) {
2254
+ return NULL ;
2255
+ }
2222
2256
if (!_bson_grow (bson , size )) {
2223
2257
return NULL ;
2224
2258
}
0 commit comments