Ensure SQLite allocation failures cannot authorize history deletion
This commit is contained in:
1 parent
7853fb0fc6
commit
aa97e053cd
2 files changed
+23
-3
No files matched your search
+2
-1
@@ -847,7 +847,8 @@ if OS_LINUX
|
||||
test_db_sync_integrity_SOURCES = test_db_sync_integrity.c
|
||||
test_db_sync_integrity_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
|
||||
test_db_sync_integrity_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
|
||||
test_db_sync_integrity_LDFLAGS = -Wl,--wrap=EVP_DigestVerifyInit -Wl,--wrap=sqlite3_exec -Wl,--wrap=uasync_set_timeout
|
||||
test_db_sync_integrity_LDFLAGS = -Wl,--wrap=EVP_DigestVerifyInit -Wl,--wrap=sqlite3_exec -Wl,--wrap=uasync_set_timeout \
|
||||
-Wl,--wrap=sqlite3_column_blob -Wl,--wrap=sqlite3_errcode
|
||||
endif
|
||||
|
||||
test_merkle_sync_SOURCES = test_merkle_sync.c $(test_clock_sources)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "../src/chat/db_sync.c"
|
||||
#include <assert.h>
|
||||
|
||||
static int fail_verify, fail_commit, fail_timer;
|
||||
static int fail_verify, fail_commit, fail_timer, fail_blob, blob_nomem;
|
||||
static unsigned fault_hits;
|
||||
extern int __real_EVP_DigestVerifyInit(EVP_MD_CTX*, EVP_PKEY_CTX**, const EVP_MD*, ENGINE*, EVP_PKEY*);
|
||||
int __wrap_EVP_DigestVerifyInit(EVP_MD_CTX* ctx, EVP_PKEY_CTX** pctx, const EVP_MD* md, ENGINE* engine, EVP_PKEY* key) {
|
||||
@@ -17,6 +17,17 @@ int __wrap_sqlite3_exec(sqlite3* db, const char* sql, int (*cb)(void*, int, char
|
||||
return __real_sqlite3_exec(db, sql, cb, arg, err);
|
||||
}
|
||||
|
||||
extern const void* __real_sqlite3_column_blob(sqlite3_stmt*, int);
|
||||
const void* __wrap_sqlite3_column_blob(sqlite3_stmt* stmt, int col) {
|
||||
if (fail_blob) { fail_blob = 0; blob_nomem = 1; fault_hits++; return NULL; }
|
||||
return __real_sqlite3_column_blob(stmt, col);
|
||||
}
|
||||
extern int __real_sqlite3_errcode(sqlite3*);
|
||||
int __wrap_sqlite3_errcode(sqlite3* db) {
|
||||
if (blob_nomem) { blob_nomem = 0; return SQLITE_NOMEM; }
|
||||
return __real_sqlite3_errcode(db);
|
||||
}
|
||||
|
||||
extern void* __real_uasync_set_timeout(struct UASYNC*, uint64_t, void*, void (*)(void*), const char*);
|
||||
void* __wrap_uasync_set_timeout(struct UASYNC* ua, uint64_t delay, void* arg, void (*cb)(void*), const char* name) {
|
||||
if (fail_timer && !strcmp(name, "db_recalc")) { fail_timer = 0; fault_hits++; return NULL; }
|
||||
@@ -84,10 +95,16 @@ static void test_preservation(void) {
|
||||
assert(insert(&f, 100, "original", sig) == 0 && insert(&f, 100, "original", sig) == 1);
|
||||
fail_verify = 1; assert(insert(&f, 100, "original", sig) == -1); intact(&f, "original");
|
||||
fail_verify = 2; assert(insert(&f, 100, "original", sig) == -1); intact(&f, "original");
|
||||
fail_blob = 1; assert(insert(&f, 100, "original", sig) == -1); intact(&f, "original");
|
||||
fail_blob = 1;
|
||||
assert(si_send_data_batch(&f.si, 2, 0, 1, 0, DB_WANT_FROM_NONE) == -1); intact(&f, "original");
|
||||
assert(insert(&f, 100, "modified", sig) == -2); intact(&f, "original");
|
||||
sql(&f, "UPDATE history SET node_id=99");
|
||||
assert(insert(&f, 100, "original", sig) == -1); intact(&f, "original");
|
||||
assert(si_send_data_batch(&f.si, 2, 0, 1, 0, DB_WANT_FROM_NONE) == -1); intact(&f, "original");
|
||||
f.inst.topo_sqlite_db = f.db.db; /* Отказ SQL lookup, в отличие от ещё неизвестного ключа. */
|
||||
assert(insert(&f, 100, "original", sig) == -1); intact(&f, "original");
|
||||
f.inst.topo_sqlite_db = NULL;
|
||||
sql(&f, "UPDATE history SET node_id=1");
|
||||
fail_verify = 1;
|
||||
assert(si_send_data_batch(&f.si, 2, 0, 1, 0, DB_WANT_FROM_NONE) == -1); intact(&f, "original");
|
||||
@@ -134,6 +151,8 @@ static void test_recalc(void) {
|
||||
struct fixture f; init(&f); uint8_t sig[64];
|
||||
for (uint64_t ts = 1; ts <= 55; ts++) { sign(&f, ts, "record", sig); assert(insert(&f, ts, "record", sig) == 0); }
|
||||
uint64_t next = f.si.next_id, hash = 0;
|
||||
fail_blob = 1;
|
||||
assert(db_sync_last_chain_hash8(&f.si, &hash) == -1 && db_sync_count(&f.si) == 55 && f.si.recalc.pending);
|
||||
fail_commit = 1;
|
||||
assert(db_sync_last_chain_hash8(&f.si, &hash) == -1 && f.si.recalc.pending && f.si.recalc.pos == 0);
|
||||
assert(sqlite3_get_autocommit(f.db.db));
|
||||
@@ -172,7 +191,7 @@ int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_CHAT_SYNC, DEBUG_LEVEL_DEBUG);
|
||||
size_t baseline = u_get_allocated_count();
|
||||
test_preservation(); test_deletion(); test_recalc(); test_delivery();
|
||||
assert(fault_hits == 10 && u_get_allocated_count() == baseline);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "PASS history integrity; injected failures=%u; tracked allocations restored", fault_hits);
|
||||
assert(fault_hits == 7 && u_get_allocated_count() == baseline);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user