Bug fixes: composite PK, nl_to_sql sandbox, FK check, SQL injection, storage correctness
Critical fixes: - Composite PK: execInsert + validateConstraints use all PK columns - nl_to_sql: non-SELECT SQL no longer executed directly during validation - FK check: removed O(N) scanMemTable fallback, uses db.get() with SSTables - exprToSql: nkIdent wrapped in quotes to prevent SQL injection - restoreSchema: try/except around tokenize/parse for crash resilience - recovery.nim: lastTxnId tracking + putUnsafe/deleteUnsafe without WAL - SCRAM: verifyClientProof length check + DefaultIterationCount restored Storage fixes: - lsm.nim: SSTable sort order fixed (ascending), close() flushes all memtables - compaction.nim: tombstones preserved during compaction - wal.nim: header written for empty existing files, readEntries checks magic - btree.nim: B+ tree leaf split keeps boundary key - bloom.nim: deserialize raises on short data - mmap.nim: bounds checks for adviseWillNeed/DontNeed + posix.close() Protocol fixes: - zerocopy.nim: readString bounds check - wire.nim: deserializeValue 32-bit underflow check - auth.nim: JWT JSON escaping for claims - server.nim: readUint32BE bounds check + specific exception handling - raft.nim: readData checks + specific exception handling Tests: - Added Composite Primary Key test suite (4 tests) Build: 0 warnings, 0 errors
This commit is contained in:
@@ -181,8 +181,8 @@ proc parsePrimary(p: var Parser): Node =
|
||||
Node(kind: nkCase, caseExpr: caseExpr, caseWhens: whens, caseElse: elseExpr,
|
||||
line: tok.line, col: tok.col)
|
||||
else:
|
||||
discard p.advance()
|
||||
Node(kind: nkNullLit, line: tok.line, col: tok.col)
|
||||
raise newException(ValueError,
|
||||
"Unexpected token " & $tok.kind & " at line " & $tok.line & ", col " & $tok.col)
|
||||
|
||||
proc parseOverClause(p: var Parser): Node =
|
||||
## Parse OVER ( [PARTITION BY expr, ...] [ORDER BY expr [ASC|DESC], ...] [frame] )
|
||||
@@ -324,7 +324,10 @@ proc parseComparison(p: var Parser): Node =
|
||||
if p.peek().kind == tkNot:
|
||||
discard p.advance()
|
||||
negated = true
|
||||
discard p.advance() # consume NULL token (assumed)
|
||||
if p.peek().kind != tkNull:
|
||||
raise newException(ValueError,
|
||||
"Expected NULL after IS " & (if negated: "NOT " else: "") & "at line " & $tok.line)
|
||||
discard p.advance() # consume NULL token
|
||||
return Node(kind: nkIsExpr, isExpr: result, isNegated: negated,
|
||||
line: tok.line, col: tok.col)
|
||||
while p.peek().kind in {tkEq, tkNotEq, tkLt, tkLtEq, tkGt, tkGtEq, tkFtsMatch, tkDistanceOp, tkJsonContains, tkJsonContainedBy, tkJsonHasAny, tkJsonHasAll}:
|
||||
|
||||
Reference in New Issue
Block a user