damus-io / nostrdb

The unfairly fast embedded nostr database backed by lmdb
Other
87 stars 15 forks source link

Create simple_fuzzer.c #15

Closed geeknik closed 10 months ago

geeknik commented 11 months ago

simple and inefficient AFL fuzzer for nostrdb responsible for finding 1x global buffer overflow 1x Floating Point Exception (div by zero) 1x Assertion failure

How to use it yourself:

  1. Install Clang 14+
  2. Install LLVM 14+
  3. Install AFL++
  4. Then... AFL_USE_ASAN=1 afl-clang-lto -flto=full -fsanitize=address -Wall -Wno-unused-function -Werror -O2 -g -Ideps/secp256k1/include -Ideps/lmdb -Ideps/flatcc/include fuzzer.c nostrdb.c sha256.c deps/flatcc/src/runtime/json_parser.c deps/flatcc/src/runtime/builder.c deps/flatcc/src/runtime/emitter.c deps/flatcc/src/runtime/refmap.c deps/lmdb/liblmdb.a deps/secp256k1/.libs/libsecp256k1.a -o fuzzer
  5. create an input directory drop some sort of starting corpus. i chose blns.txt because it rocks.
  6. afl-fuzz -i $input -o $output -- ./fuzzer

image

jb55 commented 11 months ago

Hey! Few comments below.

On Fri, Sep 01, 2023 at 11:29:04PM +0000, geeknik wrote:

simple and inefficient AFL fuzzer for nostrdb responsible for finding 1x global buffer overflow 1x Floating Point Exception (div by zero) 1x Assertion failure

Closes: https://github.com/damus-io/nostrdb/pull/15

fuzzer/simple_fuzzer.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 fuzzer/simple_fuzzer.c

diff --git a/fuzzer/simple_fuzzer.c b/fuzzer/simple_fuzzer.c new file mode 100644 index 0000000..f436aa1 --- /dev/null +++ b/fuzzer/simple_fuzzer.c

[..]

+__AFL_FUZZ_INIT(); + +int main(void) {

  • while (__AFL_LOOP(1000000)) {
  • unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
  • size_t len = __AFL_FUZZ_TESTCASE_LEN;
  • struct ndb *db;
  • int init_result = ndb_init(&db, 1024, 1);

This opens and closes the DB 1,000,000 times. is this intended?

  • if (init_result != 1) {
  • fprintf(stderr, "Failed to initialize nostrdb\n");
  • continue;
  • }
  • int result = ndb_process_event(db, (const char *)buf, len);
  • if (result == 0) {
  • if (len >= 32) {
  • struct ndb_note *note = ndb_get_note_by_id(db, buf);
  • if (note != NULL) {
  • }
  • }
  • } else {
  • }

Why only lookup after failure to process the event? Confused by this logic.

  • ndb_destroy(db);
  • }
  • return 0; +}

We should probably have a Makefile entry for building this.