fix: comprehensive bug audit — 15 critical/high/medium fixes
Critical fixes: - B-Tree splitChild: fixed out-of-bounds on child.children.len (mid+1..len → mid+1..<len) - Wire protocol: all deserializeValue cases now properly assign to result - Wire protocol: fkBool/fkInt8 now increment pos after reading - MVCC: write-write conflict now detected for completed transactions - MVCC: commit only marks visible versions as deleted (not concurrent uncommitted) - Lexer: buffer overrun on backslash escape at end of input — added bounds check - Bulgarian/Russian stemmers: fixed UTF-8 byte offsets for Cyrillic suffixes (2 bytes per char) High fixes: - WebSocket: added missing std/tables import - Raft: added randomize() call for election timeouts - MemTable.get: binary search O(log n) instead of linear scan O(n) Medium fixes: - Zerocopy: string length now written as 4-byte int32 (was single byte) - Raft appendEntries: guard against nextIdx underflow - Columnar: null tracking with nulls seq on ColumnPtr - Removed dead code in lexer readIdent (redundant true/false checks) - Updated Bulgarian stemming test to match corrected byte offsets All 214 tests pass across 48 suites with 0 failures.
This commit is contained in:
@@ -170,9 +170,12 @@ proc write*(tm: TxnManager, txn: Transaction, key: string, value: seq[byte]): bo
|
||||
if tm.activeTxns[creator].state == tsCommitted:
|
||||
release(tm.lock)
|
||||
return false # write-write conflict
|
||||
elif creator notin tm.activeTxns:
|
||||
# Already completed and visible
|
||||
discard
|
||||
else:
|
||||
# Creator already completed — check if it committed
|
||||
# If not in activeTxns, it either committed or aborted
|
||||
# We treat completed-but-visible as a conflict
|
||||
release(tm.lock)
|
||||
return false # write-write conflict with completed txn
|
||||
|
||||
let lsn = tm.allocLsn()
|
||||
let version = VersionedRecord(
|
||||
@@ -201,9 +204,15 @@ proc commit*(tm: TxnManager, txn: Transaction): bool =
|
||||
tm.globalVersions[key] = @[]
|
||||
|
||||
# Mark previous versions as deleted by this txn
|
||||
# Only mark versions that were visible to this transaction
|
||||
for i in 0..<tm.globalVersions[key].len:
|
||||
if tm.globalVersions[key][i].xmax == TxnId(0):
|
||||
tm.globalVersions[key][i].xmax = txn.id
|
||||
let creator = tm.globalVersions[key][i].xmin
|
||||
# Only mark as deleted if the version was visible (committed before our snapshot)
|
||||
if creator != txn.id:
|
||||
if uint64(creator) <= uint64(txn.snapshotMaxTxn) and
|
||||
creator notin txn.snapshotTxns:
|
||||
tm.globalVersions[key][i].xmax = txn.id
|
||||
|
||||
tm.globalVersions[key].add(version)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user