diff --git a/Makefile b/Makefile index 7bbbca4..74eed6b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -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-binascii +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-binascii fuzzer-dbm PYTHON_CONFIG_PATH=$(CPYTHON_INSTALL_PATH)/bin/python3-config CXXFLAGS += $(shell $(PYTHON_CONFIG_PATH) --cflags) @@ -43,3 +43,6 @@ fuzzer-zoneinfo: fuzzer-binascii: clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"binascii.py\"" -ldl $(LDFLAGS) -o fuzzer-binascii + +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 b016889..798a246 100644 --- a/fuzz_targets.txt +++ b/fuzz_targets.txt @@ -2,6 +2,7 @@ ast ast.py binascii binascii.py configparser configparser.py csv csv.py +dbm dbm.py decode decode.py difflib difflib.py email email.py