#!/usr/bin/env python3 """Regenerate the committed seed corpora for alkstore's fuzz targets. Writes into fuzz/corpus//. Deterministic: fixed inputs only, no randomness. Run from the repo root: python3 fuzz/gen_fuzz_seeds.py Target seed functions and the main() registry land here with the target tasks; the shared seed_name()/write_seed() plumbing is stable. """ import os def seed_name(target, i): return os.path.join("fuzz", "corpus", target, f"seed-{i:03d}") def write_seed(target, i, data): path = seed_name(target, i) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "wb") as f: f.write(data) def payload_codec_seeds(): i = 0 # Valid JSON of every Value variant (numbers incl. bounds/floats, # strings incl. escapes/unicode, arrays, objects), plus whitespace # padding. valid_docs = [ b"null", b"true", b"false", b"0", b"-1", b"-9223372036854775808", b"9223372036854775807", b"18446744073709551615", b"18446744073709551616", b"3.5", b"-2.25", b"1e10", b"1e309", b"-0", b'""', b'"hello world"', b'"unicode \\u00e9"', b'"emoji \\ud83d\\ude00"', b'"tab\\tnewline\\nquote\\"slash"', b'"null"', b"[]", b'[1, "two", null, true, {"three": 3}, []]', b"{}", b'{"a": 1}', b'{"a": 1, "nested": {"deep": [true, null, 3.5]}}', b'{"\\u00e9": "value"}', b' \t\r\n{"spaced": true}\t\n ', ] for doc in valid_docs: write_seed("payload_codec", i, doc) i += 1 # Truncations at every prefix length of two representative docs. for doc in [b'{"a": 1, "b": [2, 3]}', b"[true, null, 1.5]"]: for n in range(1, len(doc)): write_seed("payload_codec", i, doc[:n]) i += 1 # Deep nesting: shallow, at/near serde_json's 128 recursion limit, # and well past it. Arrays and objects both. for depth in [8, 127, 128, 129, 256, 1024]: write_seed("payload_codec", i, ("[" * depth + "0" + "]" * depth).encode()) i += 1 for depth in [8, 200]: write_seed("payload_codec", i, ('{"a":' * depth + "1" + "}" * depth).encode()) i += 1 # Non-UTF-8 bytes inside and outside string positions. for raw in [b"\xff\xfe\xfd", b'{"a": "\xff"}', b"[1, 2\xff]"]: write_seed("payload_codec", i, raw) i += 1 # Trailing garbage after a valid document. for raw in [ b"{} trailing", b"[1]x", b"1 2", b"null null", b'"first""second"', ]: write_seed("payload_codec", i, raw) i += 1 # Duplicate keys (canonicalization is serde_json's). for raw in [b'{"a": 1, "a": 2}', b'{"o": {"k": 1, "k": 2}, "o": 3}']: write_seed("payload_codec", i, raw) i += 1 # The Null-decode shape: an empty byte store must never decode to # a silent Null (ADR-023 §1). for raw in [b"", b" ", b"null", b"nullx"]: write_seed("payload_codec", i, raw) i += 1 # Other loud-fail shapes (typed `Codec` partition coverage). for raw in [ b"NaN", b"Infinity", b"+1", b"01", b".5", b"1.", b"--1", b"{,}", b"[1,]", b'{"a"}', b'{"missing": }', b"\x80\x81\x82", ]: write_seed("payload_codec", i, raw) i += 1 def every_parse_seeds(): i = 0 # Every grammar-valid unit form (s|m|h|d), single and multi-digit. for spec in [ "@every 1s", "@every 5s", "@every 9s", "@every 17s", "@every 42m", "@every 1m", "@every 90m", "@every 2h", "@every 24h", "@every 1d", "@every 7d", "@every 365d", ]: write_seed("every_parse", i, spec.encode()) i += 1 # Leading-zero forms (parsed through, value = the digits). for spec in ["@every 007s", "@every 007m", "@every 000000042h", "@every 007d"]: write_seed("every_parse", i, spec.encode()) i += 1 # The n <= 0 arms: positive zero (with and without leading zeros) # and the negative shapes (digits == 0 inside the grammar). for spec in ["@every 0s", "@every 00m", "@every 0000d", "@every -5s", "@every -0s"]: write_seed("every_parse", i, spec.encode()) i += 1 # The i64::MAX neighborhood: giant-n accept at scale-1, digit # overflow past i64, and unit-multiplier overflow above it. for spec in [ "@every 9223372036854775807s", "@every 9223372036854775806s", "@every 9223372036854775808s", "@every 9223372036854775807m", "@every 9223372036854775807h", "@every 9223372036854775807d", "@every 18446744073709551616s", "@every 18446744073709551616000000m", ]: write_seed("every_parse", i, spec.encode()) i += 1 # The digit-overflow boundary at exactly i64::MAX/86400 (and ±1). for spec in [ "@every 106751991167300d", "@every 106751991167301d", "@every 106751991167299d", ]: write_seed("every_parse", i, spec.encode()) i += 1 # d-unit multiplier blowups. for spec in ["@every 2147483647d", "@every 4294967295d", "@every 100000000000d"]: write_seed("every_parse", i, spec.encode()) i += 1 # Whitespace / garbage / truncation shapes. for raw in [ b"@every", b"@every ", b"@every 5s", b"@every 5s ", b"@every\t5s", b"@every 5 s", b"@every 5sx", b"@every 5S", b"@every +5s", b"@every .5s", b"@every 3.5s", b"@every 5.0s", b"@every 5\ts", b"@every \xc3\xa9s", b"\xff @every \xff 5s \xfe", b"@every 5s\xff", ]: write_seed("every_parse", i, raw) i += 1 # Non-grammar prefixes and shapes (cron / @once adjacency). for raw in [ b"@once", b"@hourly", b"@daily", b"@weekly", b"*/5 * * * *", b"0 0 * * *", b"every 5s", b"5s", b"@every 5", b"@every s", ]: write_seed("every_parse", i, raw) i += 1 # Byte payloads ≥ 24 bytes: the boundary-arithmetic leg folds # adversarial (next_fire_at, now, interval) triples straight out of # the bytes — the i64::MAX neighborhood, negative shapes, d-blowups. for raw in [ b"@every 9223372036854775807s skip-forward-triple payload XXXXX", b"\x00" * 24, b"\xff" * 24, bytes([ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, # next = i64::MAX 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, # now = 2^62 0x80, 0xC8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, # interval = 250000 ]), bytes([ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, # next = i64::MIN + 1 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, # now = i64::MAX 0x80, 0x92, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, # interval = negative ]), ]: write_seed("every_parse", i, raw) i += 1 def name_validation_seeds(): i = 0 # Plain-content names at the probed lengths: the empty↔one-char # boundary, the pg-identifier (±1) and target-max_len (±1/±2) # neighborhoods. No length cap is pinned; the seeds pin # length-independence of the verdict class. for length in [1, 2, 4, 62, 63, 64, 65, 4095, 4096]: write_seed("name_validation", i, b"a" * length) i += 1 # Empty and whitespace-only shapes (spaces, tab, newline, mixed, # unicode whitespace) — InvalidName on both kinds. for raw in [b"", b" ", b" ", b"\t", b"\n", b" \t\n ", b"\xc2\xa0", b"\xe2\x80\x83"]: write_seed("name_validation", i, raw) i += 1 # The reserved prefix: the boundary form (alone), suffixed, at a # boundary length, and the one v1-reserved string. for raw in [ b"__alkstore_", b"__alkstore_x", b"__alkstore_" + b"a" * 63, b"__alkstore_listener_reconnected__", ]: write_seed("name_validation", i, raw) i += 1 # Prefix near-misses: casing deviations, the missing trailing # underscore, embedded and whitespace-led forms — the pinned rule # is byte-exact and leading-only, so these must accept. for raw in [ b"__ALKSTORE_x", b"__Alkstore_x", b"__alkStore_x", b"__alkstore", b"x__alkstore_y", b" __alkstore_x", b"__alkstore_ ", ]: write_seed("name_validation", i, raw) i += 1 # Whitespace-only and reserved-prefixed at the pg-identifier # neighborhood lengths (±1, ±2). for length in [62, 63, 64, 65]: write_seed("name_validation", i, b" " * length) i += 1 write_seed("name_validation", i, b"__alkstore_" + b"a" * (length - len(b"__alkstore_"))) i += 1 # Unicode and control-char shapes, including invalid UTF-8 (lossy # decode) and embedded NUL. for raw in [ "é-😀-名前".encode(), "\u00e9\u0301".encode(), b"\x00\x01\x02", b"a\x00b", b"tab\tname", b"\x7f", b"\xc3\x28", b"\xff\xfe", ]: write_seed("name_validation", i, raw) i += 1 def main(): payload_codec_seeds() every_parse_seeds() name_validation_seeds() if __name__ == "__main__": main()