CVE-2020-12135 (C, published 2020-04-24T01:15Z)
Description: value: bson before 0.8 incorrectly uses int rather than size_t for many variables, parameters, and return values. In particular, the bson_ensure_space() parameter bytesNeeded could have an integer overflow via properly constructed bson input.
Severity: MEDIUM (CVSS v3 base score: 5.5)
Weakness: CWE-190 \u2014 Integer Overflow or Wraparound
The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
Repository: https://github.com/10gen-archive/mongo-c-driver-legacy
Files changed:
src/bcon.c
src/bson.c
src/bson.h
src/encoding.c
src/encoding.h
src/env.c
src/env.h
src/gridfs.c
src/gridfs.h
src/mongo.c
Commit message: don't mix up int and size_t (first pass to fix that)


Vulnerable code:
    unsigned int array_index_stack[ARRAY_INDEX_STACK_SIZE];
MONGO_EXPORT int bson_buffer_size( const bson *b ) {
    int ds;
        return bson_iterator_long_raw( i );
static void bson_append( bson *b, const void *data, int len ) {
int bson_ensure_space( bson *b, const int bytesNeeded ) {
        i = b->cur - b->data;
static int bson_append_estart( bson *b, int type, const char *name, const int dataSize ) {
                                    const char *value, int len, bson_type type ) {
    int sl = len + 1;
    bson_append32( b , &sl );
MONGO_EXPORT int bson_append_string_n( bson *b, const char *name, const char *value, int len ) {
MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *value, int len ) {
MONGO_EXPORT int bson_append_code_n( bson *b, const char *name, const char *value, int len ) {
        const char *code, int len, const bson *scope ) {
    int sl, size;
    bson_append32( b, &size );
MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, int len ) {
        bson_append32( b, &subtwolen );
        bson_append32( b, &len );
        bson_append32( b, &len );
    const int plen = strlen( pattern )+1;
    const int olen = strlen( opts )+1;
    int size;
        int data_size = size - 2 - strlen( bson_iterator_key( elem ) );
    i = b->cur - start;
MONGO_EXPORT void *bson_malloc( int size ) {
void *bson_realloc( void *ptr, int size ) {
    int stack[32];        /**< A stack used to keep track of nested BSON elements. */
MONGO_EXPORT int bson_buffer_size( const bson *b );
int bson_ensure_space( bson *b, const int bytesNeeded );
MONGO_EXPORT int bson_append_string_n( bson *b, const char *name, const char *str, int len );
MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *str, int len );
MONGO_EXPORT int bson_append_code_n( bson *b, const char *name, const char *str, int len );
MONGO_EXPORT int bson_append_code_w_scope_n( bson *b, const char *name, const char *code, int size, const bson *scope );
MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, int len );
MONGO_EXPORT void *bson_malloc( int size );
void *bson_realloc( void *ptr, int size );
static int bson_string_is_db_ref( const unsigned char *string, const int length ) {
                                 const int length, const char check_utf8, const char check_dot,
    int position = 0;
                       const int length ) {
                           const int length ) {
                           const int length );
                               const int length );
int mongo_env_write_socket( mongo *conn, const void *buf, int len ) {
        int sent = send( conn->sock, cbuf, len, flags );
int mongo_env_read_socket( mongo *conn, void *buf, int len ) {
        int sent = recv( conn->sock, cbuf, len, 0 );
int mongo_env_write_socket( mongo *conn, const void *buf, int len ) {
        int sent = send( conn->sock, cbuf, len, flags );
int mongo_env_read_socket( mongo *conn, void *buf, int len ) {
        int sent = recv( conn->sock, cbuf, len, 0 );
int mongo_env_write_socket( mongo *conn, const void *buf, int len ) {
        int sent = send( conn->sock, cbuf, len, flags );
int mongo_env_read_socket( mongo *conn, void *buf, int len ) {
        int sent = recv( conn->sock, cbuf, len, 0 );
int mongo_env_read_socket( mongo *conn, void *buf, int len );
int mongo_env_write_socket( mongo *conn, const void *buf, int len );
    int bytes_left = 0;
    int data_partial_len = 0;
    int chunks_to_write = 0;
MONGO_EXPORT mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, int size ) {
        bson_append_int( &query, "n", start );
        bson_append_int( &gte, "$gte", start );
                         &command, NULL, size, 0, 0 );
    int first_chunk;
    int last_chunk;
    int total_chunks;
    int pending_len;    /**> Length of pending_data buffer */
MONGO_EXPORT mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, int size );
    int errstr_size, str_size;
static mongo_message *mongo_message_create( int len , int id , int responseTo , int op ) {
    mm->head.len = len;
static char *mongo_data_append( char *start , const void *data , int len ) {
    int overhead =  16 + 4 + strlen( ns ) + 1;
    int size = overhead;
        int sl = strlen( cursor->ns )+1;
    int sl = strlen( db );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )user, strlen( user ) );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )pass, strlen( pass ) );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )nonce, strlen( nonce ) );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )user, strlen( user ) );

Fixed code:
    size_t array_index_stack[ARRAY_INDEX_STACK_SIZE];
MONGO_EXPORT size_t bson_buffer_size( const bson *b ) {
    size_t ds;
        return ( int )bson_iterator_long_raw( i );
static void bson_append( bson *b, const void *data, size_t len ) {
static void bson_append32_as_int( bson *b, int data ) {
    bson_little_endian32( b->cur, &data );
    b->cur += 4;
}

int bson_ensure_space( bson *b, const size_t bytesNeeded ) {
        i = ( int )( b->cur - b->data );
static int bson_append_estart( bson *b, int type, const char *name, const size_t dataSize ) {
                                    const char *value, size_t len, bson_type type ) {
    size_t sl = len + 1;
    bson_append32_as_int( b , ( int )sl );
MONGO_EXPORT int bson_append_string_n( bson *b, const char *name, const char *value, size_t len ) {
MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *value, size_t len ) {
MONGO_EXPORT int bson_append_code_n( bson *b, const char *name, const char *value, size_t len ) {
        const char *code, size_t len, const bson *scope ) {
    size_t sl, size;
    bson_append32_as_int( b, ( int )size );
MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, size_t len ) {
        bson_append32_as_int( b, ( int )subtwolen );
        bson_append32_as_int( b, ( int )len );
        bson_append32_as_int( b, ( int )len );
    const size_t plen = strlen( pattern )+1;
    const size_t olen = strlen( opts )+1;
    size_t size;
        size_t data_size = size - 2 - strlen( bson_iterator_key( elem ) );
    i = ( int )( b->cur - start );
MONGO_EXPORT void *bson_malloc( size_t size ) {
void *bson_realloc( void *ptr, size_t size ) {
    size_t stack[32];        /**< A stack used to keep track of nested BSON elements. */
MONGO_EXPORT size_t bson_buffer_size( const bson *b );
int bson_ensure_space( bson *b, const size_t bytesNeeded );
MONGO_EXPORT int bson_append_string_n( bson *b, const char *name, const char *str, size_t len );
MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *str, size_t len );
MONGO_EXPORT int bson_append_code_n( bson *b, const char *name, const char *str, size_t len );
MONGO_EXPORT int bson_append_code_w_scope_n( bson *b, const char *name, const char *code, size_t size, const bson *scope );
MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, size_t len );
MONGO_EXPORT void *bson_malloc( size_t size );
void *bson_realloc( void *ptr, size_t size );
static int bson_string_is_db_ref( const unsigned char *string, const size_t length ) {
                                 const size_t length, const char check_utf8, const char check_dot,
    size_t position = 0;
                       const size_t length ) {
                           const size_t length ) {
                           const size_t length );
                               const size_t length );
int mongo_env_write_socket( mongo *conn, const void *buf, size_t len ) {
        size_t sent = send( conn->sock, cbuf, len, flags );
int mongo_env_read_socket( mongo *conn, void *buf, size_t len ) {
        size_t sent = recv( conn->sock, cbuf, len, 0 );
int mongo_env_write_socket( mongo *conn, const void *buf, size_t len ) {
        size_t sent = send( conn->sock, cbuf, len, flags );
int mongo_env_read_socket( mongo *conn, void *buf, size_t len ) {
        size_t sent = recv( conn->sock, cbuf, len, 0 );
int mongo_env_write_socket( mongo *conn, const void *buf, size_t len ) {
        size_t sent = send( conn->sock, cbuf, len, flags );
int mongo_env_read_socket( mongo *conn, void *buf, size_t len ) {
        size_t sent = recv( conn->sock, cbuf, len, 0 );
int mongo_env_read_socket( mongo *conn, void *buf, size_t len );
int mongo_env_write_socket( mongo *conn, const void *buf, size_t len );
    size_t bytes_left = 0;
    size_t data_partial_len = 0;
    size_t chunks_to_write = 0;
MONGO_EXPORT mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, size_t size ) {
        bson_append_int( &query, "n", (int)start );
        bson_append_int( &gte, "$gte", (int)start );
                         &command, NULL, (int)size, 0, 0 );
    size_t first_chunk;
    size_t last_chunk;
    size_t total_chunks;
    size_t pending_len;    /**> Length of pending_data buffer */
MONGO_EXPORT mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, size_t size );
    size_t errstr_size, str_size;
static mongo_message *mongo_message_create( size_t len , int id , int responseTo , int op ) {
    mm->head.len = ( int )len;
static char *mongo_data_append( char *start , const void *data , size_t len ) {
    size_t overhead =  16 + 4 + strlen( ns ) + 1;
    size_t size = overhead;
        size_t sl = strlen( cursor->ns )+1;
    size_t sl = strlen( db );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )user, ( int )strlen( user ) );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )pass, ( int )strlen( pass ) );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )nonce, ( int )strlen( nonce ) );
    mongo_md5_append( &st, ( const mongo_md5_byte_t * )user, ( int )strlen( user ) );