aboutsummaryrefslogtreecommitdiff
path: root/fuzz
diff options
context:
space:
mode:
Diffstat (limited to 'fuzz')
-rw-r--r--fuzz/simple_ops.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/fuzz/simple_ops.c b/fuzz/simple_ops.c
new file mode 100644
index 0000000..a7f501e
--- /dev/null
+++ b/fuzz/simple_ops.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+#include <hkvs.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+inline static int rdlen(size_t *pr, const uint8_t **pd, size_t *pn) {
+ const uint8_t *d = *pd;
+ size_t n = *pn;
+ if(n == 0) return -1;
+ *pd = d + 1;
+ *pn = n - 1;
+ *pr = d[0];
+ return 0;
+}
+
+static const char zeroes[256];
+
+static void no_io_destroy(hkvs_io *io) {
+ (void)io;
+}
+
+inline static void check_error(int r) {
+ if(r < 0) {
+ fprintf(stderr, "Error: %s\n", strerror(-r));
+ abort();
+ }
+}
+
+extern int LLVMFuzzerTestOneInput(const uint8_t *fz_data, size_t fz_n);
+int LLVMFuzzerTestOneInput(const uint8_t *fz_data, size_t fz_n) {
+ bool log = false;
+
+ if(fz_n < 8) return 0;
+ hkvs_io *io;
+ {
+ uint64_t seed;
+ memcpy(&seed, fz_data, 8);
+ fz_data += 8;
+ fz_n -= 8;
+ io = hkvs_io_new_mem(seed);
+ }
+
+ size_t sizes[256];
+ for(size_t i = 0; i < 256; i++) {
+ sizes[i] = (size_t)-1;
+ }
+
+ hkvs *db;
+ int r = hkvs_new(&db, io);
+ if(r == -E2BIG) return 0;
+ check_error(r);
+
+ hkvs_table *t;
+ r = hkvs_table_create(db, &t, 42, 1, 16);
+ check_error(r);
+ assert(r == 1);
+
+ hkvs_rid id = HKVS_INVALID_RID;
+ uint8_t id_k = 0;
+
+ if(log) puts("begin");
+
+ while(fz_n) {
+ uint8_t op = *fz_data++;
+ fz_n--;
+
+ switch(op) {
+ case 0:
+ {
+ if(log) puts("reopen");
+
+ void (*old_destroy)(hkvs_io*) = io->destroy;
+ io->destroy = no_io_destroy;
+ hkvs_free(db);
+ io->destroy = old_destroy;
+
+ r = hkvs_new(&db, io);
+ check_error(r);
+
+ r = hkvs_table_create(db, &t, 42, 1, 16);
+ check_error(r);
+ assert(r == 0);
+ id = HKVS_INVALID_RID;
+ break;
+ }
+ case 3:
+ {
+ if(fz_n < 1) goto end;
+ uint8_t k = *fz_data;
+ fz_data++;
+ fz_n--;
+ if(log) printf("find %02x ", k);
+ id = hkvs_record_find(db, t, (const char *)&k);
+ if(hkvs_rid_ok(id)) {
+ id_k = k;
+ assert(!memcmp(hkvs_record_key(db, t, id), &k, 1));
+ size_t len;
+ char *val;
+ r = hkvs_record_value(db, t, id, &val, &len);
+ check_error(r);
+ if(log) printf("[%zu]\n", len);
+ assert(len == sizes[k]);
+ } else {
+ if(log) puts("not found");
+ assert(sizes[k] == (size_t)-1);
+ }
+ break;
+ }
+ case 4:
+ {
+ if(!hkvs_rid_ok(id)) break;
+ if(log) printf("delete %02x\n", id_k);
+ hkvs_record_delete(db, t, id);
+ sizes[id_k] = (size_t)-1;
+ id = HKVS_INVALID_RID;
+ break;
+ }
+ case 5:
+ {
+ if(!hkvs_rid_ok(id)) break;
+ size_t n;
+ r = rdlen(&n, &fz_data, &fz_n);
+ if(r < 0) goto end;
+ if(log) printf("set %02x [%zu]\n", id_k, n);
+ r = hkvs_record_set(db, t, id, zeroes, n);
+ check_error(r);
+ sizes[id_k] = n;
+ break;
+ }
+ case 6:
+ {
+ if(fz_n < 1) goto end;
+ uint8_t k = *fz_data;
+ fz_data++;
+ fz_n--;
+ size_t n;
+ r = rdlen(&n, &fz_data, &fz_n);
+ if(r < 0) goto end;
+ if(log) printf("update %02x [%zu]\n", k, n);
+ r = hkvs_record_update(db, t, &id, (const char*)&k, zeroes, n);
+ check_error(r);
+ if(r) {
+ assert(sizes[k] == (size_t)-1);
+ } else {
+ assert(sizes[k] != (size_t)-1);
+ }
+ id_k = k;
+ sizes[k] = n;
+ break;
+ }
+ }
+ }
+
+end:
+ hkvs_free(db);
+
+ return 0;
+}