Commit 1da92bd
authored
Fix 35 bugs and bump version to 0.9.111 (#9)
* Fix 35 bugs across CloudSync SQLite/PostgreSQL sync extension
Comprehensive audit identified and fixed 35 bugs (1 CRITICAL, 7 HIGH,
18 MEDIUM, 9 LOW) across the entire codebase. All 84 SQLite tests and
26 PostgreSQL tests pass with 0 failures and 0 memory leaks.
## src/cloudsync.c (13 fixes)
- [HIGH] Guard NULL db_version_stmt in cloudsync_dbversion_rerun —
set db_version = CLOUDSYNC_MIN_DB_VERSION and return 0 when stmt
is NULL, preventing NULL dereference after schema rebuild failure
- [MEDIUM] Add early return for NULL stmt in dbvm_execute to prevent
crash when called with uninitialized statement pointer
- [MEDIUM] Change (bool)dbvm_count() to (dbvm_count() > 0) in
table_pk_exists — prevents negative return values being cast to
true, giving false positive "pk exists" results
- [MEDIUM] Add NULL check on database_column_text result in
cloudsync_refill_metatable before calling strlen — prevents crash
on corrupted or empty column data
- [MEDIUM] Route early returns in cloudsync_payload_apply through
goto cleanup so CLEANUP callback and vm finalize always run —
prevents resource leaks and callback contract violation
- [MEDIUM] Change return false to goto abort_add_table when
ROWIDONLY rejected — ensures table_free runs on the partially
allocated table, preventing memory leak
- [MEDIUM] Initialize *persistent = false at top of
cloudsync_colvalue_stmt — prevents use of uninitialized value
when table_lookup returns NULL
- [LOW] Add NULL check on database_column_blob in merge_did_cid_win
— prevents memcmp with NULL pointer on corrupted cloudsync table
- [LOW] Handle partial failure in table_add_to_context_cb — clean
up col_name, col_merge_stmt, col_value_stmt at index on error
instead of leaving dangling pointers
- [LOW] Remove unused pragma_checked field from cloudsync_context
- [LOW] Change pointer comparison to strcmp in cloudsync_set_schema
— pointer equality missed cases where different string pointers
had identical content
- [LOW] Fix cloudsync_payload_get NULL check: blob == NULL (always
false for char** arg) changed to *blob == NULL
- [LOW] Pass extra meta_ref args to SQL_CLOUDSYNC_UPSERT_COL_INIT_OR_BUMP_VERSION
mprintf call to match updated PostgreSQL format string
## src/sqlite/cloudsync_sqlite.c (5 fixes)
- [HIGH] Split DEFAULT_FLAGS into FLAGS_PURE (SQLITE_UTF8 |
SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC) and FLAGS_VOLATILE
(SQLITE_UTF8). Pure functions: cloudsync_version, cloudsync_pk_encode,
cloudsync_pk_decode. All others volatile — fixes cloudsync_uuid()
returning identical values within the same query when SQLite cached
deterministic results
- [HIGH] Fix realloc inconsistency in dbsync_update_payload_append:
on second realloc failure, state was inconsistent (new_values
resized, old_values not, capacity not updated). Both reallocs now
checked before updating pointers and capacity
- [MEDIUM] Move payload->count++ after all database_value_dup NULL
checks in dbsync_update_payload_append — prevents count increment
when allocation failed, which would cause use-after-free on cleanup
- [MEDIUM] Add dbsync_update_payload_free(payload) before 3 early
returns in dbsync_update_final — prevents memory leak of entire
aggregate payload on error paths
- [MEDIUM] Clean up partial database_value_dup allocations on OOM in
dbsync_update_payload_append — free dup'd values at current index
when count is not incremented to prevent leak
## src/sqlite/database_sqlite.c (6 fixes)
- [MEDIUM] Replace fixed 4096-byte trigger WHEN clause buffers with
dynamic cloudsync_memory_mprintf — prevents silent truncation for
tables with long filter expressions
- [MEDIUM] Check cloudsync_memory_mprintf return for NULL before
storing in col_names[] in database_build_trigger_when — prevents
strlen(NULL) crash in filter_is_column under OOM
- [LOW] Use consistent PRId64 format with (int64_t) cast for schema
hash in database_check_schema_hash and database_update_schema_hash
— prevents format string mismatch on platforms where uint64_t and
int64_t have different printf specifiers
- [LOW] Fix DEBUG_DBFUNCTION using undeclared variable 'table'
instead of 'table_name' in database_create_metatable (line 568)
and database_create_triggers (line 782) — compile error when
debug macros enabled
- [LOW] Remove dead else branch in database_pk_rowid — unreachable
code after sqlite3_prepare_v2 success check
## src/sqlite/sql_sqlite.c (1 fix)
- [MEDIUM] Change %s to %q in SQL_INSERT_SETTINGS_STR_FORMAT —
prevents SQL injection via malformed setting key/value strings
## src/dbutils.c (1 fix)
- [MEDIUM] Change snprintf to cloudsync_memory_mprintf for settings
insert using the new %q format — ensures proper SQL escaping
## src/utils.c (1 fix)
- [MEDIUM] Fix integer overflow in cloudsync_blob_compare:
(int)(size1 - size2) overflows for large size_t values, changed
to (size1 > size2) ? 1 : -1
## src/network.c (1 fix)
- [MEDIUM] Remove trailing semicolon from savepoint name
"cloudsync_logout_savepoint;" — semicolon in name caused
savepoint/release mismatch
## src/postgresql/sql_postgresql.c (1 fix)
- [CRITICAL] Replace EXCLUDED.col_version with %s.col_version
(table reference) in SQL_CLOUDSYNC_UPSERT_COL_INIT_OR_BUMP_VERSION
— PostgreSQL EXCLUDED refers to the proposed INSERT row (always
col_version=1), not the existing row. This caused col_version to
never increment correctly on conflict, breaking CRDT merge logic
## src/postgresql/cloudsync_postgresql.c (4 fixes)
- [HIGH] Change PG_RETURN_INT32(rc) to PG_RETURN_BOOL(rc == DBRES_OK)
in pg_cloudsync_terminate — SQL declaration returns BOOLEAN but code
returned raw integer, causing protocol mismatch
- [HIGH] Copy blob data with palloc+memcpy before databasevm_reset in
cloudsync_col_value, and fix PG_RETURN_CSTRING to PG_RETURN_BYTEA_P
— reset invalidates SPI tuple memory, causing use-after-free; wrong
return type caused type mismatch with SQL declaration
- [MEDIUM] Use palloc0 instead of cloudsync_memory_alloc+memset in
aggregate context — palloc0 is lifetime-safe in PG aggregate memory
context; cloudsync_memory_alloc uses wrong allocator
- [MEDIUM] Free SPI_tuptable in all paths of get_column_oid — prevents
SPI tuple table leak on early return
## src/postgresql/database_postgresql.c (3 fixes)
- [MEDIUM] Use sql_escape_identifier for table_name/schema in CREATE
INDEX — prevents SQL injection via specially crafted table names
- [MEDIUM] Use sql_escape_literal for table_name in trigger WHEN
clause — prevents SQL injection in trigger condition
- [LOW] Use SPI_getvalue instead of DatumGetName for type safety in
database_pk_names — DatumGetName assumes Name type which may not
match the actual column type from information_schema
## test/unit.c (3 new tests)
- do_test_blob_compare_large_sizes: verifies overflow fix for large
size_t values in cloudsync_blob_compare
- do_test_deterministic_flags: verifies cloudsync_uuid() returns
different values in same query (non-deterministic flag working)
- do_test_schema_hash_consistency: verifies int64 hash format
roundtrip through cloudsync_schema_versions table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Bump version to 0.9.111
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update .gitignore1 parent 5ba27a7 commit 1da92bd
File tree
13 files changed
+317
-124
lines changed- src
- postgresql
- sqlite
- test
13 files changed
+317
-124
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
119 | 118 | | |
120 | 119 | | |
121 | 120 | | |
| |||
255 | 254 | | |
256 | 255 | | |
257 | 256 | | |
| 257 | + | |
| 258 | + | |
258 | 259 | | |
259 | 260 | | |
260 | 261 | | |
261 | 262 | | |
262 | 263 | | |
263 | 264 | | |
264 | | - | |
| 265 | + | |
265 | 266 | | |
266 | 267 | | |
267 | 268 | | |
| |||
365 | 366 | | |
366 | 367 | | |
367 | 368 | | |
368 | | - | |
| 369 | + | |
369 | 370 | | |
370 | 371 | | |
371 | 372 | | |
372 | 373 | | |
373 | | - | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
374 | 380 | | |
375 | 381 | | |
376 | 382 | | |
| |||
559 | 565 | | |
560 | 566 | | |
561 | 567 | | |
562 | | - | |
| 568 | + | |
563 | 569 | | |
564 | 570 | | |
565 | 571 | | |
| |||
748 | 754 | | |
749 | 755 | | |
750 | 756 | | |
751 | | - | |
| 757 | + | |
752 | 758 | | |
753 | 759 | | |
754 | 760 | | |
| |||
920 | 926 | | |
921 | 927 | | |
922 | 928 | | |
923 | | - | |
| 929 | + | |
924 | 930 | | |
925 | 931 | | |
926 | 932 | | |
927 | 933 | | |
928 | | - | |
| 934 | + | |
929 | 935 | | |
930 | 936 | | |
931 | | - | |
932 | | - | |
| 937 | + | |
| 938 | + | |
933 | 939 | | |
934 | | - | |
| 940 | + | |
935 | 941 | | |
936 | | - | |
| 942 | + | |
937 | 943 | | |
938 | 944 | | |
939 | | - | |
940 | | - | |
941 | | - | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
942 | 948 | | |
943 | | - | |
| 949 | + | |
944 | 950 | | |
945 | | - | |
| 951 | + | |
946 | 952 | | |
947 | 953 | | |
948 | | - | |
949 | | - | |
| 954 | + | |
| 955 | + | |
950 | 956 | | |
951 | 957 | | |
952 | | - | |
| 958 | + | |
953 | 959 | | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
954 | 967 | | |
955 | 968 | | |
956 | 969 | | |
| |||
992 | 1005 | | |
993 | 1006 | | |
994 | 1007 | | |
995 | | - | |
| 1008 | + | |
996 | 1009 | | |
997 | 1010 | | |
998 | 1011 | | |
| |||
1039 | 1052 | | |
1040 | 1053 | | |
1041 | 1054 | | |
1042 | | - | |
| 1055 | + | |
| 1056 | + | |
1043 | 1057 | | |
1044 | 1058 | | |
1045 | 1059 | | |
| |||
1082 | 1096 | | |
1083 | 1097 | | |
1084 | 1098 | | |
1085 | | - | |
| 1099 | + | |
1086 | 1100 | | |
1087 | 1101 | | |
1088 | 1102 | | |
| |||
1373 | 1387 | | |
1374 | 1388 | | |
1375 | 1389 | | |
| 1390 | + | |
| 1391 | + | |
| 1392 | + | |
| 1393 | + | |
1376 | 1394 | | |
1377 | 1395 | | |
1378 | 1396 | | |
| |||
1929 | 1947 | | |
1930 | 1948 | | |
1931 | 1949 | | |
| 1950 | + | |
1932 | 1951 | | |
1933 | 1952 | | |
1934 | 1953 | | |
| |||
2448 | 2467 | | |
2449 | 2468 | | |
2450 | 2469 | | |
2451 | | - | |
2452 | | - | |
| 2470 | + | |
| 2471 | + | |
2453 | 2472 | | |
2454 | 2473 | | |
2455 | 2474 | | |
| |||
2459 | 2478 | | |
2460 | 2479 | | |
2461 | 2480 | | |
2462 | | - | |
2463 | | - | |
| 2481 | + | |
| 2482 | + | |
2464 | 2483 | | |
2465 | 2484 | | |
2466 | 2485 | | |
| |||
2548 | 2567 | | |
2549 | 2568 | | |
2550 | 2569 | | |
2551 | | - | |
| 2570 | + | |
2552 | 2571 | | |
2553 | 2572 | | |
2554 | 2573 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
411 | 411 | | |
412 | 412 | | |
413 | 413 | | |
414 | | - | |
415 | | - | |
| 414 | + | |
| 415 | + | |
416 | 416 | | |
| 417 | + | |
417 | 418 | | |
418 | | - | |
| 419 | + | |
419 | 420 | | |
420 | | - | |
421 | | - | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
422 | 424 | | |
423 | 425 | | |
424 | 426 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
942 | 942 | | |
943 | 943 | | |
944 | 944 | | |
945 | | - | |
| 945 | + | |
946 | 946 | | |
947 | 947 | | |
948 | 948 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
473 | 473 | | |
474 | 474 | | |
475 | 475 | | |
476 | | - | |
| 476 | + | |
477 | 477 | | |
478 | 478 | | |
479 | 479 | | |
| |||
820 | 820 | | |
821 | 821 | | |
822 | 822 | | |
823 | | - | |
824 | | - | |
| 823 | + | |
825 | 824 | | |
826 | 825 | | |
827 | 826 | | |
| |||
1819 | 1818 | | |
1820 | 1819 | | |
1821 | 1820 | | |
1822 | | - | |
| 1821 | + | |
| 1822 | + | |
| 1823 | + | |
| 1824 | + | |
1823 | 1825 | | |
1824 | 1826 | | |
1825 | 1827 | | |
1826 | | - | |
1827 | | - | |
1828 | | - | |
| 1828 | + | |
| 1829 | + | |
| 1830 | + | |
1829 | 1831 | | |
1830 | 1832 | | |
1831 | 1833 | | |
| |||
1958 | 1960 | | |
1959 | 1961 | | |
1960 | 1962 | | |
1961 | | - | |
1962 | 1963 | | |
1963 | 1964 | | |
1964 | | - | |
1965 | | - | |
| 1965 | + | |
| 1966 | + | |
| 1967 | + | |
| 1968 | + | |
| 1969 | + | |
| 1970 | + | |
| 1971 | + | |
| 1972 | + | |
1966 | 1973 | | |
1967 | | - | |
1968 | | - | |
1969 | | - | |
1970 | | - | |
1971 | | - | |
1972 | | - | |
| 1974 | + | |
| 1975 | + | |
| 1976 | + | |
| 1977 | + | |
| 1978 | + | |
| 1979 | + | |
| 1980 | + | |
| 1981 | + | |
| 1982 | + | |
1973 | 1983 | | |
1974 | | - | |
| 1984 | + | |
| 1985 | + | |
1975 | 1986 | | |
| 1987 | + | |
1976 | 1988 | | |
1977 | | - | |
| 1989 | + | |
| 1990 | + | |
1978 | 1991 | | |
1979 | 1992 | | |
1980 | 1993 | | |
| |||
0 commit comments