# Fuzzing SQLite
"[ClusterFuzz](https://google.github.io/clusterfuzz/) is a scalable fuzzing
infrastructure which finds security and stabilty issues in software". Chromium
uses ClusterFuzz to find bugs in SQLite, among others. One can view SQLite
Fuzzing coverage [here](https://chromium-coverage.appspot.com/reports/709707_fuzzers_only/linux/chromium/src/third_party/sqlite/amalgamation/report.html),
with more detailed data [here](https://clusterfuzz.com/fuzzer-stats?fuzzer=libFuzzer_sqlite3_lpm_fuzzer).
Given access to a ClusterFuzz test case, this README will describe how one can
reproduce and help diagnose SQLite bugs found by ClusterFuzz.
Example bug: https://crbug.com/956851
# Simple automated repro
To verify that the bug still repros on the current main branch:
1. Open the relevant bug (ex. https://crbug.com/956851).
2. Open the ClusterFuzz "Detailed report" (ex. https://clusterfuzz.com/testcase?key=5756437473656832).
3. Click on the "REDO TASK" button.
4. Check on "Check if bug still reproduces", and click "Commit".
5. The bottom of the ClusterFuzz "Detailed report" from (2) should reflect that
the "Redo task(s): progression" task has started.
6. Wait for a few hours to a day, and this link should update to reflect that
the "Progression task finished.". If the bug has been fixed in main, then it
will automatically be closed. Otherwise, the bug still repro's, and the updated
stack trace will be displayed in the "Detailed report".
# Local repro setup
1. Run from your Chromium source directory.
# Local repro using ClusterFuzz testcase
SQLite authors and non-Chromium contributors may need more data in order to
reproduce SQLite bugs originating from Chromium fuzzers if:
* The fuzzer is not public (ex. LPM-based fuzzers, including fts_lpm), or
* The fuzzer's content is serialized in a custom manner, like via protobuf
(ex. LPM-based fuzzers as well).
In these cases, you may need to reproduce the testcase manually on your local
environment, and also provide a SQL query that can reproduce the issue, by
deserializing the fuzzer reproduce testcase.
To reproduce the testcase:
1. `export FUZZER_NAME=sqlite3_fts3_lpm_fuzzer # FUZZER_NAME is listed in the bug as the "Fuzz Target"`
2. Download the ClusterFuzz minimized testcase.
3. `export CLUSTERFUZZ_TESTCASE=./clusterfuzz-testcase-minimized-sqlite3_fts3_lpm_fuzzer-5756437473656832 # Set the ClusterFuzz testcase path to CLUSTERFUZZ_TESTCASE`
3. `gn args out/Fuzzer # Set arguments to match those in the ClusterFuzz "Detailed report"'s "GN CONFIG (ARGS.GN)" section`
4. `autoninja -C out/Fuzzer/ ${FUZZER_NAME} # Build the fuzzer target`
5. `./out/Fuzzer/${FUZZER_NAME} ${CLUSTERFUZZ_TESTCASE} # Verify repro by running fuzzer (for memory leaks, try setting "ASAN_OPTIONS=detect_leaks=1")`
After this, to obtain a shareable SQLite query testcase:
1. `LPM_DUMP_NATIVE_INPUT=1 SQL_SKIP_QUERIES=AlterTable ./out/Fuzzer/${FUZZER_NAME} ${CLUSTERFUZZ_TESTCASE} # Try using different args to get SQL statements that will repro the bug`
SQL_SKIP_QUERIES can help minimize the repro, LPM_DUMP_NATIVE_INPUT can dump a
SQLite query as output from a LPM fuzzer testcase, and DUMP_NATIVE_INPUT can
dump a SQLite query as output from a
[shadow_table_fuzzer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/sqlite/fuzz/shadow_table_fuzzer.cc)
testcase.
2. Optionally, minimize the testcase further using the `-minimize_crash`
[flag](https://chromium.googlesource.com/chromium/src/+/main/testing/libfuzzer/reproducing.md#minimizing-a-crash-input-optional).
3. Optionally, take output from (2) into a repro.sql file for further testing.
To do so, either copy the SQL query in the output from (1) into a .sql file, or
run the final command in (2) with a `> repro.sql` at the end, and filter out
non-SQL content afterwards. Either way, ensure the testcase continues to repro
given filters placed in (2).
# Local repro using SQL commands
Please have a .sql file with SQL queries ready. We'll refer to this file as
repro.sql. This may optionally be generated in the previous section, when
getting a `DUMP_NATIVE_INPUT` from `./out/Fuzzer/${FUZZER_NAME}`.
1. `autoninja -C out/Fuzzer/ sqlite_shell # Build the sqlite_shell`
2. `out/Fuzzer/sqlite_shell < repro.sql # Try running this sql query in SQLite`
Optionally, test cases may be further minimized by deleting lines/sections in
repro.sql, until the crash no longer reproduces.