diff --git a/src/client/client_cli.c b/src/client/client_cli.c index 27eb93f..43136af 100644 --- a/src/client/client_cli.c +++ b/src/client/client_cli.c @@ -2113,7 +2113,8 @@ int main(int argc, char* argv[]) { to nor transfers to a server. --write-batch runs the normal live transfer AND then emits the batch FILE from a separate deterministic scan pass. It drives the single-threaded transfer so the config outlives the run for that - second pass (the -m path takes ownership of the config). */ + second pass (main retains ownership of the config; every send path + borrows it). */ if (config->read_batch) { exit_code = apply_batch_to_dest(config, config->read_batch, config->receive_root_directory); goto cleanup; diff --git a/src/shared/config.h b/src/shared/config.h index c7bdb70..b0ae890 100644 --- a/src/shared/config.h +++ b/src/shared/config.h @@ -758,8 +758,9 @@ bool config_has_valid_delete_timing(const Config* config); /* Single source of truth for the cross-field ("combination") invariants a * Config must satisfy. Returns NULL when `config` is consistent, or a static, * human-readable error string (no trailing period) describing the FIRST - * violation found. Pure: performs no I/O, no allocation, no logging and no - * printing, so it is safe to call from every trust boundary. The client calls + * violation found. No I/O, no logging and no printing, so it is safe to call + * from every trust boundary; the iconv rule does invoke charset_spec_valid + * (which parses via str_dup/iconv_open), so it is not allocation-free. The client calls * it from validate_config() for up-front UX and the server calls it from * validate_received_config() so the receiver enforces exactly the same * invariants it relies on (the server is the trust boundary). */ diff --git a/tests/fuzz/fuzz_chunk_deserialize.c b/tests/fuzz/fuzz_chunk_deserialize.c index 444a297..f1c7d2a 100644 --- a/tests/fuzz/fuzz_chunk_deserialize.c +++ b/tests/fuzz/fuzz_chunk_deserialize.c @@ -17,7 +17,11 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (!d) return 0; - Chunk* chunk = chunk_deserialize(d, false); + /* Exercise both the metadata and non-metadata chunk layouts: the + metadata branch (present flag + 4-vs-72 advance) is only reachable with + use_metadata=true, so base the choice on the input rather than hardcoding + false. */ + Chunk* chunk = chunk_deserialize(d, (data[0] & 1) != 0); if (chunk) chunk_destroy(chunk);