summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.zig48
-rw-r--r--sqlite.zig67
2 files changed, 67 insertions, 48 deletions
diff --git a/build.zig b/build.zig
index b851865..3b990ff 100644
--- a/build.zig
+++ b/build.zig
@@ -242,8 +242,6 @@ pub fn build(b: *std.Build) !void {
242 test_step.dependOn(&run_tests.step); 242 test_step.dependOn(&run_tests.step);
243 } 243 }
244 244
245 // Fuzzing
246
247 const lib = b.addStaticLibrary(.{ 245 const lib = b.addStaticLibrary(.{
248 .name = "sqlite", 246 .name = "sqlite",
249 .target = getTarget(target, true), 247 .target = getTarget(target, true),
@@ -253,52 +251,6 @@ pub fn build(b: *std.Build) !void {
253 lib.addIncludePath(b.path("c")); 251 lib.addIncludePath(b.path("c"));
254 lib.linkLibC(); 252 lib.linkLibC();
255 253
256 // The library
257 const fuzz_lib = b.addStaticLibrary(.{
258 .name = "fuzz-lib",
259 .root_source_file = b.path("fuzz/main.zig"),
260 .target = getTarget(target, true),
261 .optimize = optimize,
262 });
263 fuzz_lib.addIncludePath(b.path("c"));
264 fuzz_lib.linkLibrary(lib);
265 fuzz_lib.want_lto = true;
266 fuzz_lib.bundle_compiler_rt = true;
267 fuzz_lib.root_module.addImport("sqlite", sqlite_mod);
268
269 // Setup the output name
270 const fuzz_executable_name = "fuzz";
271 const fuzz_exe_path = try b.cache_root.join(b.allocator, &.{fuzz_executable_name});
272
273 // We want `afl-clang-lto -o path/to/output path/to/library`
274 const fuzz_compile = b.addSystemCommand(&.{ "afl-clang-lto", "-o", fuzz_exe_path });
275 fuzz_compile.addArtifactArg(lib);
276 fuzz_compile.addArtifactArg(fuzz_lib);
277
278 // Install the cached output to the install 'bin' path
279 const fuzz_install = b.addInstallBinFile(.{ .cwd_relative = fuzz_exe_path }, fuzz_executable_name);
280
281 // Add a top-level step that compiles and installs the fuzz executable
282 const fuzz_compile_run = b.step("fuzz", "Build executable for fuzz testing using afl-clang-lto");
283 // fuzz_compile_run.dependOn(&fuzz_lib.step);
284 fuzz_compile_run.dependOn(&fuzz_compile.step);
285 fuzz_compile_run.dependOn(&fuzz_install.step);
286
287 // Compile a companion exe for debugging crashes
288 const fuzz_debug_exe = b.addExecutable(.{
289 .name = "fuzz-debug",
290 .root_source_file = b.path("fuzz/main.zig"),
291 .target = getTarget(target, true),
292 .optimize = optimize,
293 });
294 fuzz_debug_exe.addIncludePath(b.path("c"));
295 fuzz_debug_exe.linkLibrary(lib);
296 fuzz_debug_exe.root_module.addImport("sqlite", sqlite_mod);
297
298 // Only install fuzz-debug when the fuzz step is run
299 const install_fuzz_debug_exe = b.addInstallArtifact(fuzz_debug_exe, .{});
300 fuzz_compile_run.dependOn(&install_fuzz_debug_exe.step);
301
302 // 254 //
303 // Examples 255 // Examples
304 // 256 //
diff --git a/sqlite.zig b/sqlite.zig
index 6174d1c..6d22d1f 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -4068,3 +4068,70 @@ test "reuse same field twice in query string" {
4068 defer testing.allocator.free(name.?); 4068 defer testing.allocator.free(name.?);
4069 try testing.expectEqualStrings(name.?, update_name); 4069 try testing.expectEqualStrings(name.?, update_name);
4070} 4070}
4071
4072test "fuzzing" {
4073 const global = struct {
4074 fn testOne(input: []const u8) anyerror!void {
4075 var db = try Db.init(.{
4076 .mode = .Memory,
4077 .open_flags = .{
4078 .write = true,
4079 .create = true,
4080 },
4081 });
4082 defer db.deinit();
4083
4084 try db.exec("CREATE TABLE test(id integer primary key, name text, data blob)", .{}, .{});
4085
4086 db.execDynamic(input, .{}, .{}) catch |err| switch (err) {
4087 error.SQLiteError => return,
4088 error.ExecReturnedData => return,
4089 error.EmptyQuery => return,
4090 else => return err,
4091 };
4092
4093 db.execDynamic(
4094 "INSERT INTO test(name, data) VALUES($name, $data)",
4095 .{},
4096 .{
4097 .name = "foo",
4098 .data = input,
4099 },
4100 ) catch |err| switch (err) {
4101 error.SQLiteError => return,
4102 else => return err,
4103 };
4104
4105 var stmt = db.prepareDynamic("SELECT name, data FROM test") catch |err| switch (err) {
4106 error.SQLiteError => return,
4107 else => return err,
4108 };
4109 defer stmt.deinit();
4110
4111 var rows_memory: [4096]u8 = undefined;
4112 var rows_fba = std.heap.FixedBufferAllocator.init(&rows_memory);
4113
4114 const row_opt = stmt.oneAlloc(
4115 struct {
4116 name: Text,
4117 data: Blob,
4118 },
4119 rows_fba.allocator(),
4120 .{},
4121 .{},
4122 ) catch |err| switch (err) {
4123 error.SQLiteError => return,
4124 else => return err,
4125 };
4126
4127 if (row_opt) |row| {
4128 if (!std.mem.eql(u8, row.name.data, "foo")) return error.InvalidNameField;
4129 if (!std.mem.eql(u8, row.data.data, input)) return error.InvalidDataField;
4130 } else {
4131 return error.NoRowsFound;
4132 }
4133 }
4134 };
4135
4136 try testing.fuzz(global.testOne, .{});
4137}