diff options
Diffstat (limited to 'fuzz')
-rw-r--r-- | fuzz/simple_ops.c | 162 |
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; +} |