summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.gitignore1
-rw-r--r--build.zig50
-rw-r--r--fuzz/inputs/schema.sql1
-rw-r--r--fuzz/main.zig45
-rw-r--r--fuzz/sql.dict283
5 files changed, 379 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 9dd2249..19e3881 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ zig-*
3.zigmod 3.zigmod
4deps.zig 4deps.zig
5core.* 5core.*
6/fuzz/outputs
diff --git a/build.zig b/build.zig
index 66bd314..5837e88 100644
--- a/build.zig
+++ b/build.zig
@@ -146,7 +146,7 @@ const all_test_targets = switch (builtin.target.cpu.arch) {
146 }, 146 },
147}; 147};
148 148
149pub fn build(b: *std.build.Builder) void { 149pub fn build(b: *std.build.Builder) !void {
150 const in_memory = b.option(bool, "in_memory", "Should the tests run with sqlite in memory (default true)") orelse true; 150 const in_memory = b.option(bool, "in_memory", "Should the tests run with sqlite in memory (default true)") orelse true;
151 const dbfile = b.option([]const u8, "dbfile", "Always use this database file instead of a temporary one"); 151 const dbfile = b.option([]const u8, "dbfile", "Always use this database file instead of a temporary one");
152 const use_bundled = b.option(bool, "use_bundled", "Use the bundled sqlite3 source instead of linking the system library (default false)"); 152 const use_bundled = b.option(bool, "use_bundled", "Use the bundled sqlite3 source instead of linking the system library (default false)");
@@ -203,4 +203,52 @@ pub fn build(b: *std.build.Builder) void {
203 203
204 test_step.dependOn(&tests.step); 204 test_step.dependOn(&tests.step);
205 } 205 }
206
207 // Fuzzing
208
209 const lib = b.addStaticLibrary("sqlite", null);
210 lib.addCSourceFile("c/sqlite3.c", &[_][]const u8{"-std=c99"});
211 lib.linkLibC();
212 lib.setBuildMode(.Debug);
213 lib.setTarget(getTarget(target, true));
214
215 // The library
216 const fuzz_lib = b.addStaticLibrary("fuzz-lib", "fuzz/main.zig");
217 fuzz_lib.addIncludeDir("c");
218 fuzz_lib.setBuildMode(.Debug);
219 fuzz_lib.setTarget(getTarget(target, true));
220 fuzz_lib.linkLibrary(lib);
221 fuzz_lib.want_lto = true;
222 fuzz_lib.bundle_compiler_rt = true;
223 fuzz_lib.addPackagePath("sqlite", "sqlite.zig");
224
225 // Setup the output name
226 const fuzz_executable_name = "fuzz";
227 const fuzz_exe_path = try std.fs.path.join(b.allocator, &.{ b.cache_root, fuzz_executable_name });
228
229 // We want `afl-clang-lto -o path/to/output path/to/library`
230 const fuzz_compile = b.addSystemCommand(&.{ "afl-clang-lto", "-o", fuzz_exe_path });
231 fuzz_compile.addArtifactArg(lib);
232 fuzz_compile.addArtifactArg(fuzz_lib);
233
234 // Install the cached output to the install 'bin' path
235 const fuzz_install = b.addInstallBinFile(.{ .path = fuzz_exe_path }, fuzz_executable_name);
236
237 // Add a top-level step that compiles and installs the fuzz executable
238 const fuzz_compile_run = b.step("fuzz", "Build executable for fuzz testing using afl-clang-lto");
239 // fuzz_compile_run.dependOn(&fuzz_lib.step);
240 fuzz_compile_run.dependOn(&fuzz_compile.step);
241 fuzz_compile_run.dependOn(&fuzz_install.step);
242
243 // Compile a companion exe for debugging crashes
244 const fuzz_debug_exe = b.addExecutable("fuzz-debug", "fuzz/main.zig");
245 fuzz_debug_exe.addIncludeDir("c");
246 fuzz_debug_exe.setBuildMode(.Debug);
247 fuzz_debug_exe.setTarget(getTarget(target, true));
248 fuzz_debug_exe.linkLibrary(lib);
249 fuzz_debug_exe.addPackagePath("sqlite", "sqlite.zig");
250
251 // Only install fuzz-debug when the fuzz step is run
252 const install_fuzz_debug_exe = b.addInstallArtifact(fuzz_debug_exe);
253 fuzz_compile_run.dependOn(&install_fuzz_debug_exe.step);
206} 254}
diff --git a/fuzz/inputs/schema.sql b/fuzz/inputs/schema.sql
new file mode 100644
index 0000000..85a5643
--- /dev/null
+++ b/fuzz/inputs/schema.sql
@@ -0,0 +1 @@
CREATE TABLE foobar(user integer primary key, name text, data blob);
diff --git a/fuzz/main.zig b/fuzz/main.zig
new file mode 100644
index 0000000..482cbe0
--- /dev/null
+++ b/fuzz/main.zig
@@ -0,0 +1,45 @@
1const std = @import("std");
2const sqlite = @import("sqlite");
3
4pub export fn main() callconv(.C) void {
5 zigMain() catch unreachable;
6}
7
8pub fn zigMain() !void {
9 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
10 defer std.debug.assert(gpa.deinit() == false);
11 const allocator = gpa.allocator();
12
13 // Read the data from stdin
14 const stdin = std.io.getStdIn();
15 const data = try stdin.readToEndAlloc(allocator, std.math.maxInt(usize));
16 defer allocator.free(data);
17
18 var db = try sqlite.Db.init(.{
19 .mode = .Memory,
20 .open_flags = .{
21 .write = true,
22 .create = true,
23 },
24 });
25 defer db.deinit();
26
27 try db.exec("CREATE TABLE test(id integer primary key, name text, data blob)", .{}, .{});
28
29 db.execDynamic(data, .{}, .{}) catch |err| switch (err) {
30 error.SQLiteError => return,
31 else => return err,
32 };
33
34 db.execDynamic(
35 "INSERT INTO test(name, data) VALUES($name, $data)",
36 .{},
37 .{
38 .name = data,
39 .data = data,
40 },
41 ) catch |err| switch (err) {
42 error.SQLiteError => return,
43 else => return err,
44 };
45}
diff --git a/fuzz/sql.dict b/fuzz/sql.dict
new file mode 100644
index 0000000..92ec3ca
--- /dev/null
+++ b/fuzz/sql.dict
@@ -0,0 +1,283 @@
1# Taken from https://github.com/google/oss-fuzz/blob/f64134b0b3c2b27a4283e55581d41d83d3c3a64f/projects/sqlite3/sql.dict
2#
3# AFL dictionary for SQL
4# ----------------------
5#
6# Modeled based on SQLite documentation, contains some number of SQLite
7# extensions. Other dialects of SQL may benefit from customized dictionaries.
8#
9# If you append @1 to the file name when loading this dictionary, afl-fuzz
10# will also additionally load a selection of pragma keywords that are very
11# specific to SQLite (and are probably less interesting from the security
12# standpoint, because they are usually not allowed in non-privileged
13# contexts).
14#
15# Created by Michal Zalewski <lcamtuf@google.com>
16#
17
18function_abs=" abs(1)"
19function_avg=" avg(1)"
20function_changes=" changes()"
21function_char=" char(1)"
22function_coalesce=" coalesce(1,1)"
23function_count=" count(1)"
24function_date=" date(1,1,1)"
25function_datetime=" datetime(1,1,1)"
26function_decimal=" decimal(1,1)"
27function_glob=" glob(1,1)"
28function_group_concat=" group_concat(1,1)"
29function_hex=" hex(1)"
30function_ifnull=" ifnull(1,1)"
31function_instr=" instr(1,1)"
32function_julianday=" julianday(1,1,1)"
33function_last_insert_rowid=" last_insert_rowid()"
34function_length=" length(1)"
35function_like=" like(1,1)"
36function_likelihood=" likelihood(1,1)"
37function_likely=" likely(1)"
38function_load_extension=" load_extension(1,1)"
39function_lower=" lower(1)"
40function_ltrim=" ltrim(1,1)"
41function_max=" max(1,1)"
42function_min=" min(1,1)"
43function_nullif=" nullif(1,1)"
44function_printf=" printf(1,1)"
45function_quote=" quote(1)"
46function_random=" random()"
47function_randomblob=" randomblob(1)"
48function_replace=" replace(1,1,1)"
49function_round=" round(1,1)"
50function_rtrim=" rtrim(1,1)"
51function_soundex=" soundex(1)"
52function_sqlite_compileoption_get=" sqlite_compileoption_get(1)"
53function_sqlite_compileoption_used=" sqlite_compileoption_used(1)"
54function_sqlite_source_id=" sqlite_source_id()"
55function_sqlite_version=" sqlite_version()"
56function_strftime=" strftime(1,1,1,1)"
57function_substr=" substr(1,1,1)"
58function_sum=" sum(1)"
59function_time=" time(1,1,1)"
60function_total=" total(1)"
61function_total_changes=" total_changes()"
62function_trim=" trim(1,1)"
63function_typeof=" typeof(1)"
64function_unicode=" unicode(1)"
65function_unlikely=" unlikely(1)"
66function_upper=" upper(1)"
67function_varchar=" varchar(1)"
68function_zeroblob=" zeroblob(1)"
69
70keyword_ABORT="ABORT"
71keyword_ACTION="ACTION"
72keyword_ADD="ADD"
73keyword_AFTER="AFTER"
74keyword_ALL="ALL"
75keyword_ALTER="ALTER"
76keyword_ANALYZE="ANALYZE"
77keyword_AND="AND"
78keyword_AS="AS"
79keyword_ASC="ASC"
80keyword_ATTACH="ATTACH"
81keyword_AUTOINCREMENT="AUTOINCREMENT"
82keyword_BEFORE="BEFORE"
83keyword_BEGIN="BEGIN"
84keyword_BETWEEN="BETWEEN"
85keyword_BY="BY"
86keyword_CASCADE="CASCADE"
87keyword_CASE="CASE"
88keyword_CAST="CAST"
89keyword_CHECK="CHECK"
90keyword_COLLATE="COLLATE"
91keyword_COLUMN="COLUMN"
92keyword_COMMIT="COMMIT"
93keyword_CONFLICT="CONFLICT"
94keyword_CONSTRAINT="CONSTRAINT"
95keyword_CREATE="CREATE"
96keyword_CROSS="CROSS"
97keyword_CURRENT_DATE="CURRENT_DATE"
98keyword_CURRENT_TIME="CURRENT_TIME"
99keyword_CURRENT_TIMESTAMP="CURRENT_TIMESTAMP"
100keyword_DATABASE="DATABASE"
101keyword_DEFAULT="DEFAULT"
102keyword_DEFERRABLE="DEFERRABLE"
103keyword_DEFERRED="DEFERRED"
104keyword_DELETE="DELETE"
105keyword_DESC="DESC"
106keyword_DETACH="DETACH"
107keyword_DISTINCT="DISTINCT"
108keyword_DROP="DROP"
109keyword_EACH="EACH"
110keyword_ELSE="ELSE"
111keyword_END="END"
112keyword_ESCAPE="ESCAPE"
113keyword_EXCEPT="EXCEPT"
114keyword_EXCLUSIVE="EXCLUSIVE"
115keyword_EXISTS="EXISTS"
116keyword_EXPLAIN="EXPLAIN"
117keyword_FAIL="FAIL"
118keyword_FOR="FOR"
119keyword_FOREIGN="FOREIGN"
120keyword_FROM="FROM"
121keyword_FULL="FULL"
122keyword_GLOB="GLOB"
123keyword_GROUP="GROUP"
124keyword_HAVING="HAVING"
125keyword_IF="IF"
126keyword_IGNORE="IGNORE"
127keyword_IMMEDIATE="IMMEDIATE"
128keyword_IN="IN"
129keyword_INDEX="INDEX"
130keyword_INDEXED="INDEXED"
131keyword_INITIALLY="INITIALLY"
132keyword_INNER="INNER"
133keyword_INSERT="INSERT"
134keyword_INSTEAD="INSTEAD"
135keyword_INTERSECT="INTERSECT"
136keyword_INTO="INTO"
137keyword_IS="IS"
138keyword_ISNULL="ISNULL"
139keyword_JOIN="JOIN"
140keyword_KEY="KEY"
141keyword_LEFT="LEFT"
142keyword_LIKE="LIKE"
143keyword_LIMIT="LIMIT"
144keyword_MATCH="MATCH"
145keyword_NATURAL="NATURAL"
146keyword_NO="NO"
147keyword_NOT="NOT"
148keyword_NOTNULL="NOTNULL"
149keyword_NULL="NULL"
150keyword_OF="OF"
151keyword_OFFSET="OFFSET"
152keyword_ON="ON"
153keyword_OR="OR"
154keyword_ORDER="ORDER"
155keyword_OUTER="OUTER"
156keyword_PLAN="PLAN"
157keyword_PRAGMA="PRAGMA"
158keyword_PRIMARY="PRIMARY"
159keyword_QUERY="QUERY"
160keyword_RAISE="RAISE"
161keyword_RECURSIVE="RECURSIVE"
162keyword_REFERENCES="REFERENCES"
163#keyword_REGEXP="REGEXP"
164keyword_REINDEX="REINDEX"
165keyword_RELEASE="RELEASE"
166keyword_RENAME="RENAME"
167keyword_REPLACE="REPLACE"
168keyword_RESTRICT="RESTRICT"
169keyword_RIGHT="RIGHT"
170keyword_ROLLBACK="ROLLBACK"
171keyword_ROW="ROW"
172keyword_SAVEPOINT="SAVEPOINT"
173keyword_SELECT="SELECT"
174keyword_SET="SET"
175keyword_TABLE="TABLE"
176keyword_TEMP="TEMP"
177keyword_TEMPORARY="TEMPORARY"
178keyword_THEN="THEN"
179keyword_TO="TO"
180keyword_TRANSACTION="TRANSACTION"
181keyword_TRIGGER="TRIGGER"
182keyword_UNION="UNION"
183keyword_UNIQUE="UNIQUE"
184keyword_UPDATE="UPDATE"
185keyword_USING="USING"
186keyword_VACUUM="VACUUM"
187keyword_VALUES="VALUES"
188keyword_VIEW="VIEW"
189keyword_VIRTUAL="VIRTUAL"
190keyword_WHEN="WHEN"
191keyword_WHERE="WHERE"
192keyword_WITH="WITH"
193keyword_WITHOUT="WITHOUT"
194
195operator_concat=" || "
196operator_ebove_eq=" >="
197
198snippet_1eq1=" 1=1"
199snippet_at=" @1"
200snippet_backticks=" `a`"
201snippet_blob=" blob"
202snippet_brackets=" [a]"
203snippet_colon=" :1"
204snippet_comment=" /* */"
205snippet_date="2001-01-01"
206snippet_dollar=" $1"
207snippet_dotref=" a.b"
208snippet_fmtY="%Y"
209snippet_int=" int"
210snippet_neg1=" -1"
211snippet_pair=" a,b"
212snippet_parentheses=" (1)"
213snippet_plus2days="+2 days"
214snippet_qmark=" ?1"
215snippet_semicolon=" ;"
216snippet_star=" *"
217snippet_string_pair=" \"a\",\"b\""
218
219string_dbl_q=" \"a\""
220string_escaped_q=" 'a''b'"
221string_single_q=" 'a'"
222
223pragma_application_id@1=" application_id"
224pragma_auto_vacuum@1=" auto_vacuum"
225pragma_automatic_index@1=" automatic_index"
226pragma_busy_timeout@1=" busy_timeout"
227pragma_cache_size@1=" cache_size"
228pragma_cache_spill@1=" cache_spill"
229pragma_case_sensitive_like@1=" case_sensitive_like"
230pragma_checkpoint_fullfsync@1=" checkpoint_fullfsync"
231pragma_collation_list@1=" collation_list"
232pragma_compile_options@1=" compile_options"
233pragma_count_changes@1=" count_changes"
234pragma_data_store_directory@1=" data_store_directory"
235pragma_database_list@1=" database_list"
236pragma_default_cache_size@1=" default_cache_size"
237pragma_defer_foreign_keys@1=" defer_foreign_keys"
238pragma_empty_result_callbacks@1=" empty_result_callbacks"
239pragma_encoding@1=" encoding"
240pragma_foreign_key_check@1=" foreign_key_check"
241pragma_foreign_key_list@1=" foreign_key_list"
242pragma_foreign_keys@1=" foreign_keys"
243pragma_freelist_count@1=" freelist_count"
244pragma_full_column_names@1=" full_column_names"
245pragma_fullfsync@1=" fullfsync"
246pragma_ignore_check_constraints@1=" ignore_check_constraints"
247pragma_incremental_vacuum@1=" incremental_vacuum"
248pragma_index_info@1=" index_info"
249pragma_index_list@1=" index_list"
250pragma_integrity_check@1=" integrity_check"
251pragma_journal_mode@1=" journal_mode"
252pragma_journal_size_limit@1=" journal_size_limit"
253pragma_legacy_file_format@1=" legacy_file_format"
254pragma_locking_mode@1=" locking_mode"
255pragma_max_page_count@1=" max_page_count"
256pragma_mmap_size@1=" mmap_size"
257pragma_page_count@1=" page_count"
258pragma_page_size@1=" page_size"
259pragma_parser_trace@1=" parser_trace"
260pragma_query_only@1=" query_only"
261pragma_quick_check@1=" quick_check"
262pragma_read_uncommitted@1=" read_uncommitted"
263pragma_recursive_triggers@1=" recursive_triggers"
264pragma_reverse_unordered_selects@1=" reverse_unordered_selects"
265pragma_schema_version@1=" schema_version"
266pragma_secure_delete@1=" secure_delete"
267pragma_short_column_names@1=" short_column_names"
268pragma_shrink_memory@1=" shrink_memory"
269pragma_soft_heap_limit@1=" soft_heap_limit"
270pragma_stats@1=" stats"
271pragma_synchronous@1=" synchronous"
272pragma_table_info@1=" table_info"
273pragma_temp_store@1=" temp_store"
274pragma_temp_store_directory@1=" temp_store_directory"
275pragma_threads@1=" threads"
276pragma_user_version@1=" user_version"
277pragma_vdbe_addoptrace@1=" vdbe_addoptrace"
278pragma_vdbe_debug@1=" vdbe_debug"
279pragma_vdbe_listing@1=" vdbe_listing"
280pragma_vdbe_trace@1=" vdbe_trace"
281pragma_wal_autocheckpoint@1=" wal_autocheckpoint"
282pragma_wal_checkpoint@1=" wal_checkpoint"
283pragma_writable_schema@1=" writable_schema"