Fix segfault if storage sync open_backend returns bad code

This commit is contained in:
Tim Wojtulewicz 2025-05-29 14:43:43 -07:00
parent d570486f36
commit 0d18ce4e13
2 changed files with 21 additions and 30 deletions

View file

@ -246,6 +246,10 @@ OperationResult Redis::DoOpen(OpenResultCallback* cb, RecordValPtr options) {
StringValPtr host = backend_options->GetField<StringVal>("server_host");
if ( host ) {
PortValPtr port = backend_options->GetField<PortVal>("server_port");
if ( ! port )
return {ReturnCode::CONNECTION_FAILED,
"server_port must be set if server_host is set in Redis options record"};
server_addr = util::fmt("%s:%d", host->ToStdString().c_str(), port->Port());
REDIS_OPTIONS_SET_TCP(&opt, host->ToStdStringView().data(), port->Port());
}

View file

@ -7,6 +7,13 @@
using namespace zeek;
using namespace zeek::storage;
static void wait_for_result(OperationResult& op_result, BackendPtr& backend, ResultCallback* cb) {
if ( op_result.code == ReturnCode::IN_PROGRESS && ! backend->SupportsSync() ) {
backend->Poll();
op_result = cb->Result();
}
}
%%}
module Storage::Sync;
@ -31,12 +38,8 @@ function Storage::Sync::__open_backend%(btype: Storage::Backend, options: any, k
auto options_val = IntrusivePtr<RecordVal>{NewRef{}, options->AsRecordVal()};
auto op_result = storage_mgr->OpenBackend(b.value(), cb, options_val, kt, vt);
// If the backend only supports async, block until it's ready and then pull the result out of
// the callback.
if ( ! b.value()->SupportsSync() ) {
b.value()->Poll();
op_result = cb->Result();
}
// Potentially wait for a result if the backend only supports async.
wait_for_result(op_result, b.value(), cb);
delete cb;
@ -54,12 +57,8 @@ function Storage::Sync::__close_backend%(backend: opaque of Storage::BackendHand
auto cb = new ResultCallback();
op_result = storage_mgr->CloseBackend((*b)->backend, cb);
// If the backend only supports async, block until it's ready and then pull the result out of
// the callback.
if ( ! (*b)->backend->SupportsSync() ) {
(*b)->backend->Poll();
op_result = cb->Result();
}
// Potentially wait for a result if the backend only supports async.
wait_for_result(op_result, (*b)->backend, cb);
delete cb;
}
@ -84,12 +83,8 @@ function Storage::Sync::__put%(backend: opaque of Storage::BackendHandle, key: a
auto val_v = IntrusivePtr<Val>{NewRef{}, value};
op_result = (*b)->backend->Put(cb, key_v, val_v, overwrite, expire_time);
// If the backend only supports async, block until it's ready and then pull the result out of
// the callback.
if ( ! (*b)->backend->SupportsSync() ) {
(*b)->backend->Poll();
op_result = cb->Result();
}
// Potentially wait for a result if the backend only supports async.
wait_for_result(op_result, (*b)->backend, cb);
delete cb;
}
@ -109,12 +104,8 @@ function Storage::Sync::__get%(backend: opaque of Storage::BackendHandle, key: a
auto key_v = IntrusivePtr<Val>{NewRef{}, key};
op_result = (*b)->backend->Get(cb, key_v);
// If the backend only supports async, block until it's ready and then pull the result out of
// the callback.
if ( ! (*b)->backend->SupportsSync() ) {
(*b)->backend->Poll();
op_result = cb->Result();
}
// Potentially wait for a result if the backend only supports async.
wait_for_result(op_result, (*b)->backend, cb);
delete cb;
}
@ -134,12 +125,8 @@ function Storage::Sync::__erase%(backend: opaque of Storage::BackendHandle, key:
auto key_v = IntrusivePtr<Val>{NewRef{}, key};
op_result = (*b)->backend->Erase(cb, key_v);
// If the backend only supports async, block until it's ready and then pull the result out of
// the callback.
if ( ! (*b)->backend->SupportsSync() ) {
(*b)->backend->Poll();
op_result = cb->Result();
}
// Potentially wait for a result if the backend only supports async.
wait_for_result(op_result, (*b)->backend, cb);
delete cb;
}