# Basic fuzzing

**URL:** <https://ziggit.dev/t/basic-fuzzing/16246>\
**Category:** Docs\
**Tags:** testing, fuzzing\
**Created:** [June 18, 2026, 8:11pm UTC](https://ziggit.dev/t/basic-fuzzing/16246 "2026-06-18T20:11:37Z")\
**Posts on this page:** 1\
**Showing post:** 19

<div class="post-metadata">

**Author:** ![gooncreeper](https://ziggit.dev/user_avatar/ziggit.dev/gooncreeper/32/7984_2.png) [@gooncreeper](https://ziggit.dev/u/gooncreeper)\
**Post date:** [June 29, 2026, 10:06pm UTC](https://ziggit.dev/t/basic-fuzzing/16246/19 "2026-06-29T22:06:25Z")

</div>

> [@WeeBull](#):
>
> Is it fair to say that a `Smith` is just a source of random values?

In the sense that you are generating unknown values, yes; however, not quite in the sense of how they are generated.

> [@WeeBull](#):
>
> Would you expect to write Smiths for complex data types, and they would build on `std.testing.Smith`? Would I write a `PacketSmith` if I wanted to generate a stream of randomised network packets?

If you are asking if you should break the generation of complex types into smaller reusable functions, that is generally a good idea; and yes, they would use `Smith` as it is the the root source of getting values from the fuzzer. Take as an example the compiler’s own [`AstSmith`](https://codeberg.org/ziglang/zig/src/commit/77a4c4bbcfc412bda8c0e17729a7f10ae7483636/lib/std/zig/AstSmith.zig) which generates Zig ASTs (abstract syntax trees, essentially Zig code). It is currently used to fuzz test AST-parsing and `zig fmt`.

> [@WeeBull](#):
>
> I don’t see how this is true from the current implementation. It looks like values are int generated directly from the hashes right now. Is this description how it might work in the future?

Not quite, `Smith` is not doing any value generation. Most of the time, it calls into the fuzzer ([example](https://codeberg.org/ziglang/zig/src/commit/77a4c4bbcfc412bda8c0e17729a7f10ae7483636/lib/std/testing/Smith.zig#L469)) to generate values, though it is also able to read a pregenerated input (`Smith.in`) for rerunning inputs. Hashes are only used as a way to give the fuzzer context on the source of different values so it can more effectively mutate them. They don’t get included in the inputs, even which the fuzzer stores on disk for if it gets restarted, in any way. The implementation of the fuzzer logic and mutations can be found [here](https://codeberg.org/ziglang/zig/src/commit/aeec09ebb6251ae5ab236a29900344a95f05655d/lib/fuzzer.zig).

> Doesn’t the Smith need to understand higher level constructs to do mutations?

By default, the fuzzer already has several details on the construction of the input, from which value requests are end-of-streams, bytes, etc., from hashes, and from which blocks the input hits. However, the fuzzer expects that you give some effort in guiding it to construct interesting inputs, for example by using weights. The more you guide the fuzzer, the more efficient your fuzzing campaign (test) will be. For example,

> [@WeeBull](#):
>
> A packet will have a header, length, payload and checksum. Weights aren’t enough because the fields have inter-dependencies. If it’s trivially driven by random bytes for all fields, even with weights, the likelihood of getting a valid packet is vanishingly small.

an efficient input generator for such a case would request a `bool` which decides if the checksum will be populated with the correct value for the fuzzer. It would weigh at runtime the values of other fields based off what makes sense for the already generated dependencies.

No matter the fuzzer implementation, a test where more inputs lead to interesting behavior is going to be more efficient than the contrary, which is why Zig fuzzing leans into the smith-based approach.

> [@WeeBull](#):
>
> then I’ll want a quick way to reproduce that failure

When a fuzz test crashes the input gets saved to `.zig-cache/f/crash` (this path is also printed when the test crashes). You can copy the file into the module with you fuzz test and use the `.corpus` option with the input included using `@embedFile` ([more detailed post](https://ziggit.dev/t/saving-fuzzer-crash-files-as-reproductions/15768/2)). The corpus is automatically run with the test even in non-fuzzing mode.

---

_[View the full topic](https://ziggit.dev/t/basic-fuzzing/16246)._
