- Scheme 50.1%
- Shell 26.2%
- Makefile 12.6%
- C 10.8%
- Common Lisp 0.3%
| .builds | ||
| .jerboa | ||
| docs | ||
| scripts | ||
| src | ||
| support | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| jerboa_sqlite_shim.c | ||
| jpkg.sexp | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| SECURITY.md | ||
jerboa-sqlite-ffi
SQLite3 bindings for Jerboa.
Status: experimental. Treat this repository as a native FFI/storage component
until the release gates in SECURITY.md and docs/ffi-boundary.md are complete.
Requirements
- Jerboa
jerbuild - C compiler
- SQLite development headers and library
pkg-configrecommended
On Debian/Ubuntu:
sudo apt-get install build-essential pkg-config sqlite3 libsqlite3-dev
Build And Test
make test
make loader-policy-test
make native-sanitizer-test
make corrupt-db-corpus
make audit
make sqlite-advisory-check
make reproducibility-report
make target-evidence
make release-evidence
make test builds jerboa_sqlite_shim.so, transpiles the Jerboa library, and
runs the SQLite regression tests, including deterministic concurrent
step/bind/reset/finalize and query/close races. If jerbuild is not installed,
the Makefile bootstraps the pinned Jerboa release into .jerboa/bin.
Production binaries should statically link the shim and pre-register
jerboa_sqlite_open_bv and the remaining ABI symbols. Dynamic loading is a
development-only path: set JERBOA_SQLITE_DEV_NATIVE=1 and set
JERBOA_SQLITE_LIB to the exact canonical absolute path of the shim file.
The shim and every ancestor must have an expected root/current-user owner and
must not be world-writable; privileged processes ignore both variables.
Directories, relative paths, symlinks, non-canonical paths, CWD lookup, and bare
loader names are rejected. make loader-policy-test exercises those cases in
fresh processes.
make native-sanitizer-test runs the deterministic lifecycle races with a
UBSan-instrumented shim. It also builds ASan and TSan shims; they run on Linux,
while Darwin records compile evidence because injecting those runtimes into the
non-sanitized Scheme host is not a supported local configuration.
make corrupt-db-corpus runs a deterministic 512-case storage corpus through
the public wrapper API. It records valid database acceptance plus fail-closed
behavior for bad magic, truncated headers, invalid page/header metadata, and
generated random-byte database images.
make audit records the SQLite version and native linkage for release notes.
On Darwin, the Makefile prefers Homebrew SQLite because the Apple /usr/lib
SQLite can lag the reviewed production minimum.
make release-evidence writes the local release artifact bundle under
dist/release-evidence/, including toolchain identity, native linkage, SQLite
compile options, a minimal SBOM manifest, SQLite advisory status, source inputs,
hashes, corrupt-database corpus output, and a two-clean-build reproducibility
report that also compares repeated corpus output.
Production support is blocked until make target-evidence records a
marker-complete proof through JSQLITE_TARGET_PROOF_FILE; production release
hosts should set JSQLITE_REQUIRE_TARGET_PROOF=1. The proof covers target
SQLite advisory/linkage review, platform CVE/backport review, external storage
fuzzing, downstream consumer integration, backup/WAL/SHM artifact handling, and
cross-platform smoke. It must not contain database dumps, WAL/SHM contents,
secrets, private paths, hostnames, customer data, or raw command output.
Usage
(import (jerboa-sqlite)) ; compatibility module name
(define db (sqlite-open "my.db"))
(sqlite-exec db "CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)")
(sqlite-eval db "INSERT INTO items (name) VALUES (?)" "hello")
(for-each
(lambda (row)
(printf "~a ~a~%" (vector-ref row 0) (vector-ref row 1)))
(sqlite-query db "SELECT id, name FROM items ORDER BY id"))
(sqlite-close db)
Use parameter binding for untrusted values. Plaintext SQLite database files are sensitive local artifacts if they contain credentials, tokens, user data, or private operational records.
API
| Function | Description |
|---|---|
(sqlite-open path) |
Open database and return an opaque synchronized handle |
(sqlite-close db) |
Reject new calls, drain active calls, finalize statements, and close exactly once |
(sqlite-exec db sql) |
Execute trusted SQL without result rows |
(sqlite-eval db sql args...) |
Execute with bound parameters |
(sqlite-query db sql args...) |
Query with bound parameters; returns list of vectors |
(sqlite-prepare db sql) |
Prepare statement |
(sqlite-bind! stmt idx val) |
Bind parameter |
(sqlite-bind-null! stmt idx) |
Bind SQL NULL |
(sqlite-step stmt) |
Step statement |
(sqlite-reset stmt) |
Reset statement |
(sqlite-clear-bindings stmt) |
Clear statement bindings |
(sqlite-column-value stmt col) |
Read typed column value |
(sqlite-columns stmt) |
Return column names |
(sqlite-finalize stmt) |
Drain active statement calls and finalize exactly once |
(sqlite-last-insert-rowid db) |
Last inserted row ID |
(sqlite-changes db) |
Rows changed by last statement |
(sqlite-errmsg db) |
Last SQLite error message |
Security
See SECURITY.md, docs/ffi-boundary.md,
docs/sqlite-advisory-review.md, and docs/release-evidence.md.