#!/usr/bin/env bash # CWE-407 scan — SQLite query planner and optimizer # SQLite uses array-backed list types: ExprList, SrcList, IdList # Membership via linear loops: for(i=0; in; i++) + equality # Strategy: lead with known O(n) scan patterns, check ±20 lines for outer loop. set -euo pipefail echo "# scan=sqlite host=$(hostname) date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" cd /tmp && git clone --depth 1 https://github.com/sqlite/sqlite sqlite 2>&1 | tail -1 # O(n) membership patterns: linear scans over SQLite list types # - sqlite3ExprListFind: linear scan returning index # - loops over nExpr/nSrc/nId with equality/comparison inside SQ_MEM='sqlite3ExprListFind\b|sqlite3IdListIndex\b|for\s*\(.*->nExpr\b|for\s*\(.*->nSrc\b|for\s*\(.*->nId\b|while\s*\(.*->nExpr\b' # Outer loop constructs that would make the above O(n²) # Include both for-loop over list fields and recursive traversal SQ_LOOP='for\s*\(.*pList\|for\s*\(.*pExpr\|for\s*\(.*pSrc\|for\s*\(.*->a\[|while\s*\(.*->a\[|sqlite3WalkExprList\b|sqlite3WalkSelectExpr\b' for dir in \ src \ tool; do [ -d /tmp/sqlite/$dir ] || continue echo "# roots: /tmp/sqlite/$dir" find /tmp/sqlite/$dir -name "*.c" -o -name "*.h" 2>/dev/null | sort | while IFS= read -r f; do ml=$(grep -nE "$SQ_MEM" "$f" 2>/dev/null | cut -d: -f1 || true) [ -z "$ml" ] && continue while IFS= read -r ln; do s=$(( ln > 20 ? ln - 20 : 1 )); e=$(( ln + 20 )) ctx=$(sed -n "${s},${e}p" "$f" 2>/dev/null || true) loop_hit=$(echo "$ctx" | grep -iE "$SQ_LOOP" | head -1 | sed 's/^\s*//' || true) [ -n "$loop_hit" ] && { mem_line=$(sed -n "${ln}p" "$f" | sed 's/^\s*//') echo "CANDIDATE\t${f}:${ln}\t${mem_line} [loop: ${loop_hit}]" } done <<< "$ml" done done # Also scan the amalgamation for patterns missed in src/ # (some logic only exists in sqlite3.c after preprocessing) echo "# roots: /tmp/sqlite/sqlite3.c (amalgamation)" f=/tmp/sqlite/sqlite3.c if [ -f "$f" ]; then ml=$(grep -nE "$SQ_MEM" "$f" 2>/dev/null | cut -d: -f1 || true) while IFS= read -r ln; do [ -z "$ln" ] && continue s=$(( ln > 20 ? ln - 20 : 1 )); e=$(( ln + 20 )) ctx=$(sed -n "${s},${e}p" "$f" 2>/dev/null || true) loop_hit=$(echo "$ctx" | grep -iE "$SQ_LOOP" | head -1 | sed 's/^\s*//' || true) [ -n "$loop_hit" ] && { mem_line=$(sed -n "${ln}p" "$f" | sed 's/^\s*//') echo "CANDIDATE\t${f}:${ln}\t${mem_line} [loop: ${loop_hit}]" } done <<< "$ml" fi echo "# scan complete"