void mongoc_bulk_operation_replace_one (mongoc_bulk_operation_t *bulk, const bson_t *selector, const bson_t *document, bool upsert) { mongoc_write_command_t command = { 0 }; size_t err_off; bson_return_if_fail (bulk); bson_return_if_fail (selector); bson_return_if_fail (document); ENTRY; if (!bson_validate (document, (BSON_VALIDATE_DOT_KEYS | BSON_VALIDATE_DOLLAR_KEYS), &err_off)) { MONGOC_WARNING ("%s(): replacement document may not contain " "$ or . in keys. Ingoring document.", __FUNCTION__); EXIT; } _mongoc_write_command_init_update (&command, selector, document, upsert, false, bulk->ordered); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
static void test_bson_build_child_deep_no_begin_end (void) { union { bson_t b; bson_impl_alloc_t a; } u; int count = 0; bson_init(&u.b); test_bson_build_child_deep_no_begin_end_1(&u.b, &count); assert(bson_validate(&u.b, BSON_VALIDATE_NONE, NULL)); assert(u.a.alloclen == 1024); assert_bson_equal_file(&u.b, "test39.bson"); bson_destroy(&u.b); }
static void test_bson_utf8_key (void) { bson_uint32_t length; bson_iter_t iter; const char *str; bson_t *b; size_t offset; b = get_bson("eurokey.bson"); assert(bson_validate(b, BSON_VALIDATE_NONE, &offset)); assert(bson_iter_init(&iter, b)); assert(bson_iter_next(&iter)); assert(!strcmp(bson_iter_key(&iter), "€€€€€")); assert((str = bson_iter_utf8(&iter, &length))); assert(length == 15); /* 5 3-byte sequences. */ assert(!strcmp(str, "€€€€€")); bson_destroy(b); }
static void test_bson_build_child_deep (void) { union { bson_t b; bson_impl_alloc_t a; } u; int count = 0; bson_init(&u.b); assert((u.b.flags & BSON_FLAG_INLINE)); test_bson_build_child_deep_1(&u.b, &count); assert(!(u.b.flags & BSON_FLAG_INLINE)); assert((u.b.flags & BSON_FLAG_STATIC)); assert(!(u.b.flags & BSON_FLAG_NO_FREE)); assert(!(u.b.flags & BSON_FLAG_RDONLY)); assert(bson_validate(&u.b, BSON_VALIDATE_NONE, NULL)); assert(((bson_impl_alloc_t *)&u.b)->alloclen == 1024); assert_bson_equal_file(&u.b, "test39.bson"); bson_destroy(&u.b); }
void mongoc_bulk_operation_replace_one (mongoc_bulk_operation_t *bulk, const bson_t *selector, const bson_t *document, bool upsert) { mongoc_write_command_t command = { 0 }; size_t err_off; mongoc_write_command_t *last; int flags = BSON_VALIDATE_DOT_KEYS|BSON_VALIDATE_DOLLAR_KEYS; BSON_ASSERT (bulk); BSON_ASSERT (selector); BSON_ASSERT (document); ENTRY; if (!bson_validate (document, (bson_validate_flags_t)flags, &err_off)) { MONGOC_WARNING ("%s(): replacement document may not contain " "$ or . in keys. Ignoring document.", BSON_FUNC); EXIT; } if (bulk->commands.len) { last = &_mongoc_array_index (&bulk->commands, mongoc_write_command_t, bulk->commands.len - 1); if (last->type == MONGOC_WRITE_COMMAND_UPDATE) { _mongoc_write_command_update_append (last, selector, document, upsert, false); EXIT; } } _mongoc_write_command_init_update (&command, selector, document, upsert, false, bulk->flags, bulk->operation_id); _mongoc_array_append_val (&bulk->commands, command); EXIT; }
static void _mongoc_write_command_update_legacy (mongoc_write_command_t *command, mongoc_client_t *client, mongoc_server_stream_t *server_stream, const char *database, const char *collection, const mongoc_write_concern_t *write_concern, uint32_t offset, mongoc_write_result_t *result, bson_error_t *error) { mongoc_rpc_t rpc; bson_iter_t iter, subiter, subsubiter; bson_t doc; bool has_update, has_selector, is_upsert; bson_t update, selector; bson_t *gle = NULL; const uint8_t *data = NULL; uint32_t len = 0; size_t err_offset; bool val = false; char ns [MONGOC_NAMESPACE_MAX + 1]; int32_t affected = 0; int vflags = (BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL | BSON_VALIDATE_DOLLAR_KEYS | BSON_VALIDATE_DOT_KEYS); ENTRY; BSON_ASSERT (command); BSON_ASSERT (client); BSON_ASSERT (database); BSON_ASSERT (server_stream); BSON_ASSERT (collection); bson_iter_init (&iter, command->documents); while (bson_iter_next (&iter)) { if (bson_iter_recurse (&iter, &subiter) && bson_iter_find (&subiter, "u") && BSON_ITER_HOLDS_DOCUMENT (&subiter)) { bson_iter_document (&subiter, &len, &data); bson_init_static (&doc, data, len); if (bson_iter_init (&subsubiter, &doc) && bson_iter_next (&subsubiter) && (bson_iter_key (&subsubiter) [0] != '$') && !bson_validate (&doc, (bson_validate_flags_t)vflags, &err_offset)) { result->failed = true; bson_set_error (error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "update document is corrupt or contains " "invalid keys including $ or ."); EXIT; } } else { result->failed = true; bson_set_error (error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "updates is malformed."); EXIT; } } bson_snprintf (ns, sizeof ns, "%s.%s", database, collection); bson_iter_init (&iter, command->documents); while (bson_iter_next (&iter)) { rpc.update.msg_len = 0; rpc.update.request_id = 0; rpc.update.response_to = 0; rpc.update.opcode = MONGOC_OPCODE_UPDATE; rpc.update.zero = 0; rpc.update.collection = ns; rpc.update.flags = MONGOC_UPDATE_NONE; has_update = false; has_selector = false; is_upsert = false; bson_iter_recurse (&iter, &subiter); while (bson_iter_next (&subiter)) { if (strcmp (bson_iter_key (&subiter), "u") == 0) { bson_iter_document (&subiter, &len, &data); rpc.update.update = data; bson_init_static (&update, data, len); has_update = true; } else if (strcmp (bson_iter_key (&subiter), "q") == 0) { bson_iter_document (&subiter, &len, &data); rpc.update.selector = data; bson_init_static (&selector, data, len); has_selector = true; } else if (strcmp (bson_iter_key (&subiter), "multi") == 0) { val = bson_iter_bool (&subiter); if (val) { rpc.update.flags = (mongoc_update_flags_t)( rpc.update.flags | MONGOC_UPDATE_MULTI_UPDATE); } } else if (strcmp (bson_iter_key (&subiter), "upsert") == 0) { val = bson_iter_bool (&subiter); if (val) { rpc.update.flags = (mongoc_update_flags_t)( rpc.update.flags | MONGOC_UPDATE_UPSERT); } is_upsert = true; } } if (!mongoc_cluster_sendv_to_server (&client->cluster, &rpc, 1, server_stream, write_concern, error)) { result->failed = true; EXIT; } if (_mongoc_write_concern_needs_gle (write_concern)) { if (!_mongoc_client_recv_gle (client, server_stream, &gle, error)) { result->failed = true; EXIT; } if (bson_iter_init_find (&subiter, gle, "n") && BSON_ITER_HOLDS_INT32 (&subiter)) { affected = bson_iter_int32 (&subiter); } /* * CDRIVER-372: * * Versions of MongoDB before 2.6 don't return the _id for an * upsert if _id is not an ObjectId. */ if (is_upsert && affected && !bson_iter_init_find (&subiter, gle, "upserted") && bson_iter_init_find (&subiter, gle, "updatedExisting") && BSON_ITER_HOLDS_BOOL (&subiter) && !bson_iter_bool (&subiter)) { if (has_update && bson_iter_init_find (&subiter, &update, "_id")) { _ignore_value (bson_append_iter (gle, "upserted", 8, &subiter)); } else if (has_selector && bson_iter_init_find (&subiter, &selector, "_id")) { _ignore_value (bson_append_iter (gle, "upserted", 8, &subiter)); } } _mongoc_write_result_merge_legacy ( result, command, gle, MONGOC_ERROR_COLLECTION_UPDATE_FAILED, offset); offset++; bson_destroy (gle); } } EXIT; }
void _mongoc_write_command_update_legacy (mongoc_write_command_t *command, mongoc_client_t *client, mongoc_server_stream_t *server_stream, const char *database, const char *collection, uint32_t offset, mongoc_write_result_t *result, bson_error_t *error) { int64_t started; int32_t max_bson_obj_size; mongoc_rpc_t rpc; uint32_t request_id = 0; bson_iter_t subiter, subsubiter; bson_t doc; bson_t update, selector; const uint8_t *data = NULL; uint32_t len = 0; size_t err_offset; bool val = false; char ns[MONGOC_NAMESPACE_MAX + 1]; int vflags = (BSON_VALIDATE_UTF8 | BSON_VALIDATE_UTF8_ALLOW_NULL | BSON_VALIDATE_DOLLAR_KEYS | BSON_VALIDATE_DOT_KEYS); bson_reader_t *reader; const bson_t *bson; bool eof; ENTRY; BSON_ASSERT (command); BSON_ASSERT (client); BSON_ASSERT (database); BSON_ASSERT (server_stream); BSON_ASSERT (collection); started = bson_get_monotonic_time (); max_bson_obj_size = mongoc_server_stream_max_bson_obj_size (server_stream); reader = bson_reader_new_from_data (command->payload.data, command->payload.len); while ((bson = bson_reader_read (reader, &eof))) { if (bson_iter_init (&subiter, bson) && bson_iter_find (&subiter, "u") && BSON_ITER_HOLDS_DOCUMENT (&subiter)) { bson_iter_document (&subiter, &len, &data); BSON_ASSERT (bson_init_static (&doc, data, len)); if (bson_iter_init (&subsubiter, &doc) && bson_iter_next (&subsubiter) && (bson_iter_key (&subsubiter)[0] != '$') && !bson_validate ( &doc, (bson_validate_flags_t) vflags, &err_offset)) { result->failed = true; bson_set_error (error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "update document is corrupt or contains " "invalid keys including $ or ."); bson_reader_destroy (reader); EXIT; } } else { result->failed = true; bson_set_error (error, MONGOC_ERROR_BSON, MONGOC_ERROR_BSON_INVALID, "updates is malformed."); bson_reader_destroy (reader); EXIT; } } bson_snprintf (ns, sizeof ns, "%s.%s", database, collection); bson_reader_destroy (reader); reader = bson_reader_new_from_data (command->payload.data, command->payload.len); while ((bson = bson_reader_read (reader, &eof))) { request_id = ++client->cluster.request_id; rpc.header.msg_len = 0; rpc.header.request_id = request_id; rpc.header.response_to = 0; rpc.header.opcode = MONGOC_OPCODE_UPDATE; rpc.update.zero = 0; rpc.update.collection = ns; rpc.update.flags = MONGOC_UPDATE_NONE; BSON_ASSERT (bson_iter_init (&subiter, bson)); while (bson_iter_next (&subiter)) { if (strcmp (bson_iter_key (&subiter), "u") == 0) { bson_iter_document (&subiter, &len, &data); if (len > max_bson_obj_size) { _mongoc_write_command_too_large_error ( error, 0, len, max_bson_obj_size); result->failed = true; bson_reader_destroy (reader); EXIT; } rpc.update.update = data; BSON_ASSERT (bson_init_static (&update, data, len)); } else if (strcmp (bson_iter_key (&subiter), "q") == 0) { bson_iter_document (&subiter, &len, &data); if (len > max_bson_obj_size) { _mongoc_write_command_too_large_error ( error, 0, len, max_bson_obj_size); result->failed = true; bson_reader_destroy (reader); EXIT; } rpc.update.selector = data; BSON_ASSERT (bson_init_static (&selector, data, len)); } else if (strcmp (bson_iter_key (&subiter), "multi") == 0) { val = bson_iter_bool (&subiter); if (val) { rpc.update.flags = (mongoc_update_flags_t) ( rpc.update.flags | MONGOC_UPDATE_MULTI_UPDATE); } } else if (strcmp (bson_iter_key (&subiter), "upsert") == 0) { val = bson_iter_bool (&subiter); if (val) { rpc.update.flags = (mongoc_update_flags_t) ( rpc.update.flags | MONGOC_UPDATE_UPSERT); } } } _mongoc_monitor_legacy_write ( client, command, database, collection, server_stream, request_id); if (!mongoc_cluster_legacy_rpc_sendv_to_server ( &client->cluster, &rpc, server_stream, error)) { result->failed = true; bson_reader_destroy (reader); EXIT; } _mongoc_monitor_legacy_write_succeeded (client, bson_get_monotonic_time () - started, command, server_stream, request_id); started = bson_get_monotonic_time (); } bson_reader_destroy (reader); }
int main (int argc, char *argv[]) { bson_reader_t *reader; const bson_t *b; const char *filename; size_t offset; int docnum; int fd; int i; /* * Print program usage if no arguments are provided. */ if (argc == 1) { fprintf(stderr, "usage: %s FILE...\n", argv[0]); return 1; } /* * Process command line arguments expecting each to be a filename. */ for (i = 1; i < argc; i++) { filename = argv[i]; docnum = 0; /* * Open the filename provided in command line arguments. */ errno = 0; fd = open(filename, O_RDONLY); if (fd == -1) { fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); continue; } /* * Initialize a new reader for this file descriptor. */ reader = bson_reader_new_from_fd(fd, TRUE); /* * Convert each incoming document to JSON and print to stdout. */ while ((b = bson_reader_read(reader, NULL))) { docnum++; if (!bson_validate(b, (BSON_VALIDATE_UTF8 | BSON_VALIDATE_DOLLAR_KEYS | BSON_VALIDATE_DOT_KEYS | BSON_VALIDATE_UTF8_ALLOW_NULL), &offset)) { fprintf(stderr, "Document %u in \"%s\" is invalid at offset %u.\n", docnum, filename, (int)offset); return 1; } } /* * Cleanup after our reader, which closes the file descriptor. */ bson_reader_destroy(reader); } return 0; }
static void test_bson_validate (void) { char filename[64]; size_t offset; bson_t *b; int i; for (i = 1; i <= 38; i++) { snprintf(filename, sizeof filename, "test%u.bson", i); b = get_bson(filename); assert(bson_validate(b, BSON_VALIDATE_NONE, &offset)); bson_destroy(b); } b = get_bson("overflow2.bson"); assert(!bson_validate(b, BSON_VALIDATE_NONE, &offset)); assert(offset == 9); bson_destroy(b); b = get_bson("trailingnull.bson"); assert(!bson_validate(b, BSON_VALIDATE_NONE, &offset)); assert(offset == 14); bson_destroy(b); b = get_bson("dollarquery.bson"); assert(!bson_validate(b, BSON_VALIDATE_DOLLAR_KEYS, &offset)); bson_destroy(b); b = get_bson("dotquery.bson"); assert(!bson_validate(b, BSON_VALIDATE_DOT_KEYS, &offset)); bson_destroy(b); b = get_bson("overflow3.bson"); assert(!bson_validate(b, BSON_VALIDATE_NONE, &offset)); assert(offset == 9); bson_destroy(b); b = get_bson("overflow4.bson"); assert(!bson_validate(b, BSON_VALIDATE_NONE, &offset)); bson_destroy(b); b = get_bson("codewscope.bson"); assert(bson_validate (b, BSON_VALIDATE_NONE, &offset)); bson_destroy(b); #define ENSURE_FAILURE(file) \ b = get_bson(file); \ assert(!bson_validate(b, BSON_VALIDATE_NONE, &offset)); \ bson_destroy(b); ENSURE_FAILURE("test40.bson"); ENSURE_FAILURE("test41.bson"); ENSURE_FAILURE("test42.bson"); ENSURE_FAILURE("test43.bson"); ENSURE_FAILURE("test44.bson"); ENSURE_FAILURE("test45.bson"); ENSURE_FAILURE("test46.bson"); ENSURE_FAILURE("test47.bson"); ENSURE_FAILURE("test48.bson"); ENSURE_FAILURE("test49.bson"); ENSURE_FAILURE("test50.bson"); ENSURE_FAILURE("test51.bson"); ENSURE_FAILURE("test52.bson"); ENSURE_FAILURE("test53.bson"); ENSURE_FAILURE("test54.bson"); #undef ENSURE_FAILURE }