Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Check for errors on bson_finish, mongo_remove, and mongo_cursor_next

  • Loading branch information...
commit 45ecd6608d24d48689bec4df81b2fbb4cc641ab4 1 parent ec4efcb
@banker banker authored
View
23 src/bson.c
@@ -46,6 +46,8 @@ static int ( *oid_inc_func )( void ) = NULL;
bson *bson_empty( bson *obj ) {
static char *data = "\005\0\0\0\0";
bson_init_data( obj, data );
+ obj->finished = 1;
+ obj->err = 0;
return obj;
}
@@ -64,9 +66,9 @@ void bson_copy( bson *out, const bson *in ) {
out->dataSize = in->dataSize;
out->finished = in->finished;
out->stackPos = in->stackPos;
+ out->err = in->err;
for( i=0; i<out->stackPos; i++ )
out->stack[i] = in->stack[i];
- out->err = in->err;
}
int bson_init_data( bson *b, char *data ) {
@@ -596,11 +598,6 @@ int bson_ensure_space( bson *b, const int bytesNeeded ) {
char *orig = b->data;
int new_size;
- if ( b->finished ) {
- b->err = BSON_OBJECT_FINISHED;
- return BSON_ERROR;
- }
-
if ( pos + bytesNeeded <= b->dataSize )
return BSON_OK;
@@ -627,6 +624,10 @@ int bson_ensure_space( bson *b, const int bytesNeeded ) {
int bson_finish( bson *b ) {
int i;
+
+ if( b->err & BSON_NOT_UTF8 )
+ return BSON_ERROR;
+
if ( ! b->finished ) {
if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR;
bson_append_byte( b, 0 );
@@ -648,6 +649,12 @@ void bson_destroy( bson *b ) {
static int bson_append_estart( bson *b, int type, const char *name, const int dataSize ) {
const int len = strlen( name ) + 1;
+
+ if ( b->finished ) {
+ b->err |= BSON_ALREADY_FINISHED;
+ return BSON_ERROR;
+ }
+
if ( bson_ensure_space( b, 1 + len + dataSize ) == BSON_ERROR ) {
return BSON_ERROR;
}
@@ -880,6 +887,10 @@ int bson_append_finish_object( bson *b ) {
return BSON_OK;
}
+int bson_append_finish_array( bson *b ) {
+ return bson_append_finish_object( b );
+}
+
static bson_err_handler err_handler = NULL;
bson_err_handler set_bson_err_handler( bson_err_handler func ) {
View
16 src/bson.h
@@ -34,15 +34,15 @@ MONGO_EXTERN_C_START
#define BSON_ERROR -1
enum bson_error_t {
- BSON_OBJECT_FINISHED = 1, /**< Trying to modify a finished BSON object. */
- BSON_SIZE_OVERFLOW = 2 /**< Trying to create a BSON object larger than INT_MAX. */
+ BSON_SIZE_OVERFLOW = 1 /**< Trying to create a BSON object larger than INT_MAX. */
};
enum bson_validity_t {
BSON_VALID = 0, /**< BSON is valid and UTF-8 compliant. */
BSON_NOT_UTF8 = ( 1<<1 ), /**< A key or a string is not valid UTF-8. */
BSON_FIELD_HAS_DOT = ( 1<<2 ), /**< Warning: key contains '.' character. */
- BSON_FIELD_INIT_DOLLAR = ( 1<<3 ) /**< Warning: key starts with '$' character. */
+ BSON_FIELD_INIT_DOLLAR = ( 1<<3 ), /**< Warning: key starts with '$' character. */
+ BSON_ALREADY_FINISHED = ( 1<<4 ) /**< Trying to modify a finished BSON object. */
};
enum bson_binary_subtype_t {
@@ -881,6 +881,16 @@ int bson_append_start_array( bson *b, const char *name );
*/
int bson_append_finish_object( bson *b );
+/**
+ * Finish appending a new object or array to a bson. This
+ * is simply an alias for bson_append_finish_object.
+ *
+ * @param b the bson to append to.
+ *
+ * @return BSON_OK or BSON_ERROR.
+ */
+int bson_append_finish_array( bson *b );
+
void bson_numstr( char *str, int i );
void bson_incnumstr( char *str );
View
28 src/mongo.c
@@ -451,6 +451,21 @@ static int mongo_bson_valid( mongo *conn, bson *bson, int write ) {
return MONGO_OK;
}
+/* Determine whether this BSON object is valid for the given operation. */
+static int mongo_cursor_bson_valid( mongo_cursor *cursor, bson *bson ) {
+ if( ! bson->finished ) {
+ cursor->err = MONGO_BSON_NOT_FINISHED;
+ return MONGO_ERROR;
+ }
+
+ if( bson->err & BSON_NOT_UTF8 ) {
+ cursor->err = MONGO_BSON_INVALID;
+ return MONGO_ERROR;
+ }
+
+ return MONGO_OK;
+}
+
/* MongoDB CRUD API */
int mongo_insert_batch( mongo *conn, const char *ns,
@@ -537,6 +552,14 @@ int mongo_update( mongo *conn, const char *ns, const bson *cond,
int mongo_remove( mongo *conn, const char *ns, const bson *cond ) {
char *data;
+
+ /* Make sure that the BSON is valid UTF-8.
+ * TODO: decide whether to check cond as well.
+ * */
+ if( mongo_bson_valid( conn, ( bson * )cond, 0 ) != MONGO_OK ) {
+ return MONGO_ERROR;
+ }
+
mongo_message *mm = mongo_message_create( 16 /* header */
+ 4 /* ZERO */
+ strlen( ns ) + 1
@@ -563,8 +586,13 @@ static int mongo_cursor_op_query( mongo_cursor *cursor ) {
/* Set up default values for query and fields, if necessary. */
if( ! cursor->query )
cursor->query = bson_empty( &empty );
+ else if( mongo_cursor_bson_valid( cursor, cursor->query ) != MONGO_OK )
+ return MONGO_ERROR;
+
if( ! cursor->fields )
cursor->fields = bson_empty( &empty );
+ else if( mongo_cursor_bson_valid( cursor, cursor->fields ) != MONGO_OK )
+ return MONGO_ERROR;
mm = mongo_message_create( 16 + /* header */
4 + /* options */
View
6 test/bson.c
@@ -58,6 +58,12 @@ int main() {
bson_append_long( b, "l", 0x1122334455667788 );
bson_finish( b );
+ ASSERT( b->err == BSON_VALID );
+
+ /* Test append after finish. */
+ ASSERT( bson_append_string( b, "foo", "bar" ) == BSON_ERROR );
+ ASSERT( b->err & BSON_ALREADY_FINISHED );
+
/* Set stackPos to test stack copy. */
b->stackPos = 1;
bson_copy( copy, b );
View
13 test/validate.c
@@ -19,6 +19,7 @@ static void make_small_invalid( bson *out, int i ) {
int main() {
mongo conn[1];
bson b, empty;
+ mongo_cursor cursor[1];
unsigned char not_utf8[3];
int result = 0;
const char *ns = "test.c.validate";
@@ -63,18 +64,24 @@ int main() {
ASSERT( result == BSON_ERROR );
ASSERT( b.err & BSON_NOT_UTF8 );
- bson_finish( &b );
+ ASSERT( bson_finish( &b ) == BSON_ERROR );
ASSERT( b.err & BSON_FIELD_HAS_DOT );
ASSERT( b.err & BSON_FIELD_INIT_DOLLAR );
ASSERT( b.err & BSON_NOT_UTF8 );
result = mongo_insert( conn, ns, &b );
ASSERT( result == MONGO_ERROR );
- ASSERT( conn->err == MONGO_BSON_INVALID );
+ ASSERT( conn->err & MONGO_BSON_NOT_FINISHED );
result = mongo_update( conn, ns, bson_empty( &empty ), &b, 0 );
ASSERT( result == MONGO_ERROR );
- ASSERT( conn->err == MONGO_BSON_INVALID );
+ ASSERT( conn->err & MONGO_BSON_NOT_FINISHED );
+
+ mongo_cursor_init( cursor, conn, "test.cursors" );
+ mongo_cursor_set_query( cursor, &b );
+ result = mongo_cursor_next( cursor );
+ ASSERT( result == MONGO_ERROR );
+ ASSERT( cursor->err & MONGO_BSON_NOT_FINISHED );
bson_destroy( &b );
Please sign in to comment.
Something went wrong with that request. Please try again.