diff --git a/db/c.cc b/db/c.cc index 4547115710..b7bed5249b 100644 --- a/db/c.cc +++ b/db/c.cc @@ -1759,9 +1759,13 @@ rocksdb_column_family_handle_t* rocksdb_create_column_family( rocksdb_t* db, const rocksdb_options_t* column_family_options, const char* column_family_name, char** errptr) { rocksdb_column_family_handle_t* handle = new rocksdb_column_family_handle_t; - SaveError(errptr, db->rep->CreateColumnFamily( - ColumnFamilyOptions(column_family_options->rep), - std::string(column_family_name), &(handle->rep))); + handle->rep = nullptr; + if (SaveError(errptr, db->rep->CreateColumnFamily( + ColumnFamilyOptions(column_family_options->rep), + std::string(column_family_name), &(handle->rep)))) { + delete handle; + return nullptr; + } handle->immortal = false; return handle; } @@ -7534,9 +7538,13 @@ rocksdb_column_family_handle_t* rocksdb_transactiondb_create_column_family( const rocksdb_options_t* column_family_options, const char* column_family_name, char** errptr) { rocksdb_column_family_handle_t* handle = new rocksdb_column_family_handle_t; - SaveError(errptr, txn_db->rep->CreateColumnFamily( - ColumnFamilyOptions(column_family_options->rep), - std::string(column_family_name), &(handle->rep))); + handle->rep = nullptr; + if (SaveError(errptr, txn_db->rep->CreateColumnFamily( + ColumnFamilyOptions(column_family_options->rep), + std::string(column_family_name), &(handle->rep)))) { + delete handle; + return nullptr; + } handle->immortal = false; return handle; } diff --git a/db/c_test.c b/db/c_test.c index 8c57d0fcf6..fee69c0ff0 100644 --- a/db/c_test.c +++ b/db/c_test.c @@ -4880,6 +4880,21 @@ int main(int argc, char** argv) { rocksdb_sst_file_manager_destroy(sst_file_manager); } + StartPhase("create_column_family_error_returns_null"); + { + // Creating a column family with a name that already exists should fail + // and return NULL. Without the fix, the handle is leaked and a non-NULL + // pointer with an indeterminate rep field is returned. + char* cf_err = NULL; + rocksdb_column_family_handle_t* cf_handle = + rocksdb_create_column_family(db, options, "default", &cf_err); + // Should have an error since "default" already exists + CheckCondition(cf_err != NULL); + // The handle should be NULL on error (this is the bug fix) + CheckCondition(cf_handle == NULL); + free(cf_err); + } + StartPhase("cancel_all_background_work"); rocksdb_cancel_all_background_work(db, 1);