Skip to content

Commit 7fc3903

Browse files
committed
CDRIVER-2693 segfault in bson_b64_pton
The function relies on data that is initialized by mongoc_init, but a libbson-only application never calls mongoc_init. Use pthread_once to initialize the data on demand instead.
1 parent 084c879 commit 7fc3903

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

NEWS

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Next Release
2+
============
3+
4+
Fix a crash when parsing binary data from JSON if mongoc_init isn't called.
5+
16
mongo-c-driver 1.10.2
27
=====================
38

src/common/common-b64-private.h

-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ bson_b64_ntop (uint8_t const *src,
3030
char *target,
3131
size_t targsize);
3232

33-
void
34-
bson_b64_initialize_rmap (void);
35-
3633
int
3734
bson_b64_pton (char const *src, uint8_t *target, size_t targsize);
3835

src/common/common-b64.c

+27-5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
4141
*/
4242

43+
#include "bson.h"
4344
#include "common-b64-private.h"
4445

4546
#define Assert(Cond) \
@@ -258,11 +259,26 @@ static const uint8_t mongoc_b64rmap_end = 0xfd;
258259
static const uint8_t mongoc_b64rmap_space = 0xfe;
259260
static const uint8_t mongoc_b64rmap_invalid = 0xff;
260261

261-
/**
262-
* Initializing the reverse map is not thread safe, do it at startup.
263-
**/
264-
void
265-
bson_b64_initialize_rmap (void)
262+
/* initializing the reverse map isn't thread safe, do it in pthread_once. here
263+
* in a common source file we don't have access to bson or mongoc defines like
264+
* BSON_ONCE_FUN. */
265+
#if defined(BSON_OS_UNIX)
266+
#include <pthread.h>
267+
#define mongoc_common_once_t pthread_once_t
268+
#define mongoc_common_once pthread_once
269+
#define MONGOC_COMMON_ONCE_FUN(n) void n (void)
270+
#define MONGOC_COMMON_ONCE_RETURN return
271+
#define MONGOC_COMMON_ONCE_INIT PTHREAD_ONCE_INIT
272+
#else
273+
#define mongoc_common_once_t INIT_ONCE
274+
#define MONGOC_COMMON_ONCE_INIT INIT_ONCE_STATIC_INIT
275+
#define mongoc_common_once(o, c) InitOnceExecuteOnce (o, c, NULL, NULL)
276+
#define MONGOC_COMMON_ONCE_FUN(n) \
277+
BOOL CALLBACK n (PINIT_ONCE _ignored_a, PVOID _ignored_b, PVOID *_ignored_c)
278+
#define MONGOC_COMMON_ONCE_RETURN return true
279+
#endif
280+
281+
static MONGOC_COMMON_ONCE_FUN (bson_b64_initialize_rmap)
266282
{
267283
int i;
268284
unsigned char ch;
@@ -286,6 +302,8 @@ bson_b64_initialize_rmap (void)
286302
/* Fill reverse mapping for base64 chars */
287303
for (i = 0; Base64[i] != '\0'; ++i)
288304
mongoc_b64rmap[(uint8_t) Base64[i]] = i;
305+
306+
MONGOC_COMMON_ONCE_RETURN;
289307
}
290308

291309
static int
@@ -501,6 +519,10 @@ mongoc_b64_pton_len (char const *src)
501519
int
502520
bson_b64_pton (char const *src, uint8_t *target, size_t targsize)
503521
{
522+
static mongoc_common_once_t once = MONGOC_COMMON_ONCE_INIT;
523+
524+
mongoc_common_once (&once, bson_b64_initialize_rmap);
525+
504526
if (target)
505527
return mongoc_b64_pton_do (src, target, targsize);
506528
else

src/libmongoc/src/mongoc/mongoc-init.c

-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ static MONGOC_ONCE_FUN (_mongoc_do_init)
9191
tls_init ();
9292
#endif
9393

94-
bson_b64_initialize_rmap ();
95-
9694
#ifdef MONGOC_ENABLE_SASL_CYRUS
9795
/* The following functions should not use tracing, as they may be invoked
9896
* before mongoc_log_set_handler() can complete. */

0 commit comments

Comments
 (0)