diff --git a/Makefile b/Makefile index 9103a1c..02fdbc9 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -all : fuzzer-html fuzzer-email fuzzer-httpclient fuzzer-json fuzzer-difflib fuzzer-csv fuzzer-decode fuzzer-ast fuzzer-tarfile fuzzer-tarfile-hypothesis fuzzer-zipfile fuzzer-zipfile-hypothesis fuzzer-re fuzzer-configparser fuzzer-tomllib fuzzer-plistlib fuzzer-xml fuzzer-zoneinfo +all : fuzzer-html fuzzer-email fuzzer-httpclient fuzzer-json fuzzer-difflib fuzzer-csv fuzzer-decode fuzzer-ast fuzzer-tarfile fuzzer-tarfile-hypothesis fuzzer-zipfile fuzzer-zipfile-hypothesis fuzzer-re fuzzer-configparser fuzzer-tomllib fuzzer-plistlib fuzzer-xml fuzzer-zoneinfo fuzzer-dbm PYTHON_CONFIG_PATH=$(CPYTHON_INSTALL_PATH)/bin/python3-config CXXFLAGS += $(shell $(PYTHON_CONFIG_PATH) --cflags) -LDFLAGS += -rdynamic $(shell $(PYTHON_CONFIG_PATH) --ldflags --embed) +LDFLAGS += -rdynamic $(shell $(PYTHON_CONFIG_PATH) --ldflags --embed) $(CPYTHON_MODLIBS) -Wl,--allow-multiple-definition fuzzer-html: clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"html.py\"" -ldl $(LDFLAGS) -o fuzzer-html @@ -40,3 +40,6 @@ fuzzer-xml: clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"xml.py\"" -ldl $(LDFLAGS) -o fuzzer-xml fuzzer-zoneinfo: clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"zoneinfo.py\"" -ldl $(LDFLAGS) -o fuzzer-zoneinfo + +fuzzer-dbm: + clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"dbm.py\"" -ldl $(LDFLAGS) -o fuzzer-dbm diff --git a/dbm.py b/dbm.py new file mode 100644 index 0000000..afff832 --- /dev/null +++ b/dbm.py @@ -0,0 +1,56 @@ +from fuzzeddataprovider import FuzzedDataProvider +import os +import dbm +import tempfile + +OP_STORE = 0 +OP_GET = 1 +OP_LIST_KEYS = 2 +OP_DELETE = 3 +OP_ITERATE = 4 + + +# Fuzzes the _gdbm C module (Modules/_gdbmmodule.c). +# Exercises key-value store operations on a temporary GDBM database: +# store, get, key listing, deletion, and iteration with fuzzed +# keys and values. +def FuzzerRunOne(FuzzerInput): + if len(FuzzerInput) < 1 or len(FuzzerInput) > 0x10000: + return + fdp = FuzzedDataProvider(FuzzerInput) + try: + with tempfile.TemporaryDirectory() as tmpdir: + dbpath = os.path.join(tmpdir, "fuzzdb") + with dbm.open(dbpath, "c") as db: + num_ops = fdp.ConsumeIntInRange(1, 20) + for _ in range(num_ops): + if fdp.remaining_bytes() == 0: + break + op = fdp.ConsumeIntInRange(OP_STORE, OP_ITERATE) + if op == OP_STORE: + n = fdp.ConsumeIntInRange(1, min(fdp.remaining_bytes(), 100)) + key = fdp.ConsumeBytes(n) + n2 = ( + fdp.ConsumeIntInRange(1, min(fdp.remaining_bytes(), 1000)) + if fdp.remaining_bytes() > 0 + else 0 + ) + val = fdp.ConsumeBytes(n2) if n2 > 0 else b"" + db[key] = val + elif op == OP_GET: + n = fdp.ConsumeIntInRange(1, min(fdp.remaining_bytes(), 100)) + key = fdp.ConsumeBytes(n) + _ = db.get(key) + elif op == OP_LIST_KEYS: + _ = list(db.keys()) + elif op == OP_DELETE: + n = fdp.ConsumeIntInRange(1, min(fdp.remaining_bytes(), 100)) + key = fdp.ConsumeBytes(n) + if key in db: + del db[key] + elif op == OP_ITERATE: + for k in db: + _ = db[k] + break + except Exception: + pass diff --git a/fuzz_targets.txt b/fuzz_targets.txt index 8710a5f..b4eb476 100644 --- a/fuzz_targets.txt +++ b/fuzz_targets.txt @@ -1,6 +1,7 @@ ast ast.py configparser configparser.py csv csv.py +dbm dbm.py decode decode.py difflib difflib.py email email.py