Skip to content

Commit

Permalink
Make sure very large changesets in bootstraps do not crash the sync c…
Browse files Browse the repository at this point in the history
…lient (#6220)
  • Loading branch information
jbreams authored Jan 23, 2023
1 parent f34a371 commit 715e870
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Fix several data races when opening cached frozen Realms. New frozen Realms were added to the cache and the lock released before they were fully initialized, resulting in races if they were immediately read from the cache on another thread ([PR #6211](https://github.com/realm/realm-core/pull/6211), since v6.0.0).
* Properties and types not present in the requested schema would be missing from the reported schema in several scenarios, such as if the Realm was being opened with a different schema version than the persisted one, and if the new tables or columns were added while the Realm instance did not have an active read transaction ([PR #6211](https://github.com/realm/realm-core/pull/6211), since v13.2.0).
* If a client reset w/recovery or discard local is interrupted while the "fresh" realm is being downloaded, the sync client may crash with a MultpleSyncAgents exception ([#6217](https://github.com/realm/realm-core/issues/6217), since v11.13.0)
* Changesets from the server sent during FLX bootstrapping that are larger than 16MB can cause the sync client to crash with a LogicError (PR [#6218](https://github.com/realm/realm-core/pull/6218), since v12.0.0)

### Breaking changes
* `SyncSession::log_out()` has been renamed to `SyncSession::force_close()` to reflect what it actually does ([#6183](https://github.com/realm/realm-core/pull/6183))
Expand Down
13 changes: 12 additions & 1 deletion src/realm/sync/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,18 @@ bool SessionImpl::process_flx_bootstrap_message(const SyncProgress& progress, Do
}

bool new_batch = false;
bootstrap_store->add_batch(query_version, std::move(maybe_progress), received_changesets, &new_batch);
try {
bootstrap_store->add_batch(query_version, std::move(maybe_progress), received_changesets, &new_batch);
}
catch (const LogicError& ex) {
if (ex.kind() == LogicError::binary_too_big) {
IntegrationException ex(ClientError::bad_changeset_size,
"bootstrap changeset too large to store in pending bootstrap store");
on_integration_failure(ex);
return true;
}
throw;
}

// If we've started a new batch and there is more to come, call on_flx_sync_progress to mark the subscription as
// bootstrapping.
Expand Down
41 changes: 41 additions & 0 deletions test/object-store/sync/flx_sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2941,6 +2941,47 @@ TEST_CASE("flx: bootstrap changesets are applied continuously", "[sync][flx][app
CHECK(user_commit_version == bootstrap_version + 1);
}


TEST_CASE("flx: really big bootstraps", "[sync][flx][app]") {
FLXSyncTestHarness harness("harness");

std::vector<ObjectId> expected_obj_ids;
harness.load_initial_data([&](SharedRealm realm) {
realm->cancel_transaction();
for (size_t n = 0; n < 10; ++n) {
realm->begin_transaction();
for (size_t i = 0; i < 100; ++i) {
expected_obj_ids.push_back(ObjectId::gen());
auto& obj_id = expected_obj_ids.back();
CppContext c(realm);
Object::create(c, realm, "TopLevel",
std::any(AnyDict{{"_id", obj_id},
{"queryable_str_field", "foo"s},
{"queryable_int_field", static_cast<int64_t>(5)},
{"non_queryable_field", random_string(1024 * 128)}}));
}
realm->commit_transaction();
}
realm->begin_transaction();
});

SyncTestFile target(harness.app()->current_user(), harness.schema(), SyncConfig::FLXSyncEnabled{});
auto error_pf = util::make_promise_future<SyncError>();
target.sync_config->error_handler = [promise = util::CopyablePromiseHolder(std::move(error_pf.promise))](
std::shared_ptr<SyncSession>, SyncError err) mutable {
promise.get_promise().emplace_value(std::move(err));
};
auto realm = Realm::get_shared_realm(target);
auto mut_subs = realm->get_latest_subscription_set().make_mutable_copy();
mut_subs.insert_or_assign(Query(realm->read_group().get_table("class_TopLevel")));
auto subs = mut_subs.commit();

// TODO when BAAS-19105 is fixed we should be able to just wait for bootstrapping to be complete. For now though,
// check that we get the error code we expect.
auto err = error_pf.future.get();
REQUIRE(err.error_code == sync::ClientError::bad_changeset_size);
}

} // namespace realm::app

#endif // REALM_ENABLE_AUTH_TESTS

0 comments on commit 715e870

Please sign in to comment.