test(fuzz): add config-frame receive and identity parser fuzz targets
Add two libFuzzer harnesses (GLOBbed from tests/fuzz/*.c) and deterministic P8 config-frame receive tests: - fuzz_config_receive.c drives config_receive() from arbitrary bytes. It captures one canonical valid frame with the production sender and feeds the receiver four shapes: raw bytes, valid-version-prefix + fuzz bytes, valid frame minus the P8 tail (super_mode + copy-as) + fuzz bytes, and valid frame minus the usermap count + fuzz bytes. This reaches the --super/--copy-as and huge/negative map-count paths that random bytes cannot get through the preceding wire-bool gate. - fuzz_identity_parse.c fuzzes identity_parse_copy_as/map/chown plus the identity_wire_valid/identity_ownership_requested predicates on a fresh config per input. - test_fuzz_smoke.c gains deterministic malformed-frame cases: out-of-range super_mode, negative/extreme copy-as ids, non-bool copy-as presence, tail truncation, huge/negative usermap counts, version mismatch and a wrong-order field after the version gate. Unit build (STRICT_WARNINGS) and the fuzz build are clean; both targets run 3000+ iterations with no crash. No production code changed.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Fuzz the CLI-time identity parsers (identity.h):
|
||||
* - identity_parse_copy_as
|
||||
* - identity_parse_map (user and group variants)
|
||||
* - identity_parse_chown
|
||||
*
|
||||
* Each parser mutates a Config, so every input gets a fresh config_create()
|
||||
* (freed afterwards). After a successful parse the shared wire validator and
|
||||
* the ownership predicate are also exercised on the mutated config. The input
|
||||
* is NUL-terminated; embedded NULs simply shorten the effective spec, which is
|
||||
* fine for a parser fuzzer.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "identity.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void exercise(Config* c, const char* spec, int which) {
|
||||
if (!c)
|
||||
return;
|
||||
switch (which) {
|
||||
case 0:
|
||||
(void)identity_parse_copy_as(c, spec);
|
||||
break;
|
||||
case 1:
|
||||
(void)identity_parse_map(c, spec, false);
|
||||
break;
|
||||
case 2:
|
||||
(void)identity_parse_map(c, spec, true);
|
||||
break;
|
||||
default:
|
||||
(void)identity_parse_chown(c, spec);
|
||||
break;
|
||||
}
|
||||
(void)identity_wire_valid(c);
|
||||
(void)identity_ownership_requested(c);
|
||||
config_delete(c);
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
char* spec = malloc(size + 1);
|
||||
if (!spec)
|
||||
return 0;
|
||||
memcpy(spec, data, size);
|
||||
spec[size] = '\0';
|
||||
|
||||
exercise(config_create(), spec, 0);
|
||||
exercise(config_create(), spec, 1);
|
||||
exercise(config_create(), spec, 2);
|
||||
exercise(config_create(), spec, 3);
|
||||
|
||||
free(spec);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user