Skip to content

Commit 992baab

Browse files
committed
CDRIVER-2541 leak if encoding bad BSON to JSON
Early exit from _bson_as_json_visit_array / _bson_as_json_visit_document didn't free the JSON string that was under construction.
1 parent 12670df commit 992baab

File tree

2 files changed

+70
-46
lines changed

2 files changed

+70
-46
lines changed

src/libbson/src/bson/bson.c

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,8 +1555,11 @@ bson_append_regex (bson_t *bson,
15551555

15561556

15571557
bool
1558-
bson_append_regex_w_len (bson_t *bson, const char *key, int key_length,
1559-
const char *regex, int regex_length,
1558+
bson_append_regex_w_len (bson_t *bson,
1559+
const char *key,
1560+
int key_length,
1561+
const char *regex,
1562+
int regex_length,
15601563
const char *options)
15611564
{
15621565
static const uint8_t type = BSON_TYPE_REGEX;
@@ -1586,21 +1589,22 @@ bson_append_regex_w_len (bson_t *bson, const char *key, int key_length,
15861589

15871590
_bson_append_regex_options_sorted (options_sorted, options);
15881591

1589-
r = _bson_append (bson,
1590-
6,
1591-
(1 + key_length + 1 + regex_length + 1 + options_sorted->len + 1),
1592-
1,
1593-
&type,
1594-
key_length,
1595-
key,
1596-
1,
1597-
&gZero,
1598-
regex_length,
1599-
regex,
1600-
1,
1601-
&gZero,
1602-
options_sorted->len + 1,
1603-
options_sorted->str);
1592+
r = _bson_append (
1593+
bson,
1594+
6,
1595+
(1 + key_length + 1 + regex_length + 1 + options_sorted->len + 1),
1596+
1,
1597+
&type,
1598+
key_length,
1599+
key,
1600+
1,
1601+
&gZero,
1602+
regex_length,
1603+
regex,
1604+
1,
1605+
&gZero,
1606+
options_sorted->len + 1,
1607+
options_sorted->str);
16041608

16051609
bson_string_free (options_sorted, true);
16061610

@@ -2191,7 +2195,7 @@ bson_copy_to (const bson_t *src, bson_t *dst)
21912195
if ((src->flags & BSON_FLAG_INLINE)) {
21922196
#ifdef BSON_MEMCHECK
21932197
dst->len = src->len;
2194-
dst->canary = malloc(1);
2198+
dst->canary = malloc (1);
21952199
memcpy (dst->padding, src->padding, sizeof dst->padding);
21962200
#else
21972201
memcpy (dst, src, sizeof *dst);
@@ -2963,10 +2967,10 @@ _bson_as_json_visit_code (const bson_iter_t *iter,
29632967

29642968
static bool
29652969
_bson_as_json_visit_symbol (const bson_iter_t *iter,
2966-
const char *key,
2967-
size_t v_symbol_len,
2968-
const char *v_symbol,
2969-
void *data)
2970+
const char *key,
2971+
size_t v_symbol_len,
2972+
const char *v_symbol,
2973+
void *data)
29702974
{
29712975
bson_json_state_t *state = data;
29722976
char *escaped;
@@ -3032,30 +3036,18 @@ _bson_as_json_visit_codewscope (const bson_iter_t *iter,
30323036

30333037

30343038
static const bson_visitor_t bson_as_json_visitors = {
3035-
_bson_as_json_visit_before,
3036-
NULL, /* visit_after */
3037-
_bson_as_json_visit_corrupt,
3038-
_bson_as_json_visit_double,
3039-
_bson_as_json_visit_utf8,
3040-
_bson_as_json_visit_document,
3041-
_bson_as_json_visit_array,
3042-
_bson_as_json_visit_binary,
3043-
_bson_as_json_visit_undefined,
3044-
_bson_as_json_visit_oid,
3045-
_bson_as_json_visit_bool,
3046-
_bson_as_json_visit_date_time,
3047-
_bson_as_json_visit_null,
3048-
_bson_as_json_visit_regex,
3049-
_bson_as_json_visit_dbpointer,
3050-
_bson_as_json_visit_code,
3051-
_bson_as_json_visit_symbol,
3052-
_bson_as_json_visit_codewscope,
3053-
_bson_as_json_visit_int32,
3054-
_bson_as_json_visit_timestamp,
3055-
_bson_as_json_visit_int64,
3056-
_bson_as_json_visit_maxkey,
3057-
_bson_as_json_visit_minkey,
3058-
NULL, /* visit_unsupported_type */
3039+
_bson_as_json_visit_before, NULL, /* visit_after */
3040+
_bson_as_json_visit_corrupt, _bson_as_json_visit_double,
3041+
_bson_as_json_visit_utf8, _bson_as_json_visit_document,
3042+
_bson_as_json_visit_array, _bson_as_json_visit_binary,
3043+
_bson_as_json_visit_undefined, _bson_as_json_visit_oid,
3044+
_bson_as_json_visit_bool, _bson_as_json_visit_date_time,
3045+
_bson_as_json_visit_null, _bson_as_json_visit_regex,
3046+
_bson_as_json_visit_dbpointer, _bson_as_json_visit_code,
3047+
_bson_as_json_visit_symbol, _bson_as_json_visit_codewscope,
3048+
_bson_as_json_visit_int32, _bson_as_json_visit_timestamp,
3049+
_bson_as_json_visit_int64, _bson_as_json_visit_maxkey,
3050+
_bson_as_json_visit_minkey, NULL, /* visit_unsupported_type */
30593051
_bson_as_json_visit_decimal128,
30603052
};
30613053

@@ -3080,6 +3072,7 @@ _bson_as_json_visit_document (const bson_iter_t *iter,
30803072
child_state.depth = state->depth + 1;
30813073
child_state.mode = state->mode;
30823074
if (bson_iter_visit_all (&child, &bson_as_json_visitors, &child_state)) {
3075+
bson_string_free (child_state.str, true);
30833076
return true;
30843077
}
30853078

@@ -3112,6 +3105,7 @@ _bson_as_json_visit_array (const bson_iter_t *iter,
31123105
child_state.depth = state->depth + 1;
31133106
child_state.mode = state->mode;
31143107
if (bson_iter_visit_all (&child, &bson_as_json_visitors, &child_state)) {
3108+
bson_string_free (child_state.str, true);
31153109
return true;
31163110
}
31173111

src/libbson/tests/test-json.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,33 @@ test_bson_json_read_corrupt_utf8 (void)
10451045
}
10461046

10471047

1048+
/* exercise early exit from _bson_as_json_visit_document/array, CDRIVER-2541 */
1049+
static void
1050+
test_bson_json_read_corrupt_document (void)
1051+
{
1052+
/* like {a: {a: "\x80"}}, the value is invalid UTF-8 */
1053+
const char bad_doc[] = "\x16\x00\x00\x00" /* length */
1054+
"\x03\x61\x00" /* subdoc field with key "a" */
1055+
"\x0e\x00\x00\x00" /* length of subdoc in bytes */
1056+
"\x02\x61\x00\x02\x00\x00\x00\x80\x00" /* a: "\x80" */
1057+
"\x00"; /* terminator */
1058+
1059+
/* like {a: ["\x80"]}, the inner value is invalid UTF-8 */
1060+
const char bad_array[] = "\x16\x00\x00\x00" /* length */
1061+
"\x04\x61\x00" /* array field with key "a" */
1062+
"\x0e\x00\x00\x00" /* length of array in bytes */
1063+
"\x02\x30\x00" /* key "0" */
1064+
"\x02\x00\x00\x00\x80\x00" /* string "\x80" */
1065+
"\x00"; /* terminator */
1066+
1067+
bson_t bson;
1068+
bson_init_static (&bson, (uint8_t *) bad_doc, sizeof (bad_doc));
1069+
BSON_ASSERT (!bson_as_json (&bson, NULL));
1070+
bson_init_static (&bson, (uint8_t *) bad_array, sizeof (bad_array));
1071+
BSON_ASSERT (!bson_as_json (&bson, NULL));
1072+
}
1073+
1074+
10481075
static void
10491076
test_bson_json_read_decimal128 (void)
10501077
{
@@ -2917,6 +2944,9 @@ test_json_install (TestSuite *suite)
29172944
suite, "/bson/json/read/raw_utf8", test_bson_json_read_raw_utf8);
29182945
TestSuite_Add (
29192946
suite, "/bson/json/read/corrupt_utf8", test_bson_json_read_corrupt_utf8);
2947+
TestSuite_Add (suite,
2948+
"/bson/json/read/corrupt_document",
2949+
test_bson_json_read_corrupt_document);
29202950
TestSuite_Add (
29212951
suite, "/bson/json/read/decimal128", test_bson_json_read_decimal128);
29222952
TestSuite_Add (

0 commit comments

Comments
 (0)