<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix" -->

---
title: Tips for more effective fuzz testing with AFL++ | daily.dev
description: Fuzz testing with AFL++ finds bugs in C and C++ code, based on fuzzing roughly 1,000 projects over six years. Key tips: enable both ASan and UBSan together,...
canonical: https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Tips for more effective fuzz testing with AFL++ | daily.dev
og:description: Fuzz testing with AFL++ finds bugs in C and C++ code, based on fuzzing roughly 1,000 projects over six years. Key tips: enable both ASan and UBSan together,...
og:url: https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix
og:image: https://api.daily.dev/og/posts/MBoIxgDix.png
og:image:alt: Tips for more effective fuzz testing with AFL++
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Tips for more effective fuzz testing with AFL++

**[Hacker News](https://daily.dev/sources/hn)** · 11 min read · 0 upvotes · 0 comments

## Summary

Fuzz testing with AFL++ finds bugs in C and C++ code, based on fuzzing roughly 1,000 projects over six years. Key tips: enable both ASan and UBSan together, set ASAN_OPTIONS with abort_on_error=1, halt_on_error=1 and detect_stack_use_after_return=1, and raise max_malloc_fill_size to fill allocations with a pattern past the default 4KiB, which helps detect use-after-free bugs. Prefer AFL++'s persistent mode (afl-gcc-fast, afl-clang-fast) for roughly 10x speed. Never fuzz directly on AFL++'s buffer since ASan won't catch read overflows on it; copy into a correctly sized buffer instead. Shrinking oversized fixed buffers (e.g. from 65536 to 16 bytes) helps fuzzing reach crash conditions faster.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://nullprogram.com/blog/2025/02/05>

## Questions this post answers

### why doesn't AddressSanitizer catch buffer overflows when I pass AFL++'s fuzz buffer directly into my target function

The buffer AFL++ allocates for __AFL_FUZZ_TESTCASE_BUF is larger than the reported length, so ASan cannot detect read overflows past that length when you pass it directly. The fix is to copy the data into a buffer sized exactly to the test case length (realloc and memcpy) before calling the target function, rather than passing the raw buffer and length.

_daily.dev surfaces fuzzing and sanitizer guidance for developers hardening C/C++ code against memory bugs._

### should I use AFL++ persistent mode or the normal fork mode for fuzzing a C program

Persistent mode, enabled via afl-gcc-fast or afl-clang-fast with __AFL_LOOP, is typically an order of magnitude faster than fuzzing a program in-place with afl-gcc or afl-clang. It does introduce pitfalls around state isolation between test iterations, such as leftover heap memory and global variables, which need to be reset or filled with a pattern each run.

_developers tuning fuzzing performance can track practical AFL++ configuration tips on daily.dev._

### how do I fuzz test a C function that only accepts a file path instead of a buffer

Create an in-memory file descriptor with memfd_create, then write the fuzz input to it with ftruncate and pwrite, and pass the path /proc/self/fd/3 (assuming fd 3) to the target function instead of a real file path. This avoids disk writes, works safely under parallel fuzzing since /proc paths are per-process, and needs no cleanup.

_engineers fuzzing legacy file-path-only APIs can reference concrete AFL++ patterns like this via daily.dev._

## Community take

How the wider developer community reacted, aggregated from 5 discussions and 27 comments across hackernews, lobsters (as of 2026-11-02).

**TL;DR:** The technical tips themselves got little direct critique; discussion instead drifted into a broader debate about whether memory-safety bugs in C/C++ stem from developer skill, incentives, or inherent language/tooling limitations, while a smaller thread praised specific tips like the custom buffer sizing and memfd trick.

**Sentiment:** 30% positive · 55% mixed · 15% skeptical

**The case for**

- Several people affirmed fuzzing (and AFL specifically) reliably finds real, reproducible bugs even in code written by highly experienced engineers.
- The tip about building a correctly-sized buffer for ASan was called subtle but valuable, and the memfd-for-path-arguments trick was seen as a useful discovery.
- One commenter noted fuzzing is cheap to run overnight compared to continuously burning tokens on AI-based bug hunting.

**The pushback**

- Some felt the tips are oriented toward manually building fuzzers rather than integrating fuzzing into CI pipelines.
- Several argued that writing fully memory-safe C/C++ may be practically impossible regardless of skill, since no large codebase has ever been free of such issues.
- One commenter questioned how to distinguish a genuine crash/bug from a fluke.

**By community**

- hackernews (mixed): Little direct discussion of the fuzzing tips themselves; most of the thread debates whether C/C++ bugs reflect developer skill, incentives, or language/tooling limits, with general respect for fuzzing as a technique.
- lobsters (positive): Small thread praising specific tips (custom buffer sizing, memfd trick) while noting the advice seems geared more toward manual fuzzer-building than CI integration.

**Hottest debate:** Whether memory-safety bugs in C/C++ are fundamentally a matter of developer skill/care versus inherent limitations of the language and tooling.

**Open questions**

- How can one be confident that a crash found by a fuzzer represents a real, reproducible bug rather than a fluke?
- Are these tips primarily useful for one-off manual fuzzer construction, or can they be adapted for ongoing CI-integrated fuzzing?

**Highlights**

> Has there ever existed a C or C++ codebase of significant size that hasn't had exploitable memory corruption issues? I don't think we can keep saying it's a question of the dev's passion or skill or whatever, if no dev has ever managed to do it. That's not to say memory corruption issues are the only kind of issues, and rewriting a mature C/C++ codebase into a memory safe language may well introduce more issues than it fixes...
> — [sczi on hackernews · 2 comments](https://news.ycombinator.com/item?id=50331612)

> An example that comes to mind is postfix (the SMTP daemon). It hasn't had zero memory safety issues, but nearly so. Certainly an abnormally low amount given the size/complexity of the project and the number of eyes on it. It's also had a pretty 'normal' (read: higher) amount of non-memory related bugs such as SMTP smuggling of filesystem permission TOCTOU, so it's not like its devs are somehow really good at just not writing bugs. Maybe they have chosen a software architecture that allows them to avoid complicated memory-related logic? I genuinely don't know, would love to hear from a postfix developer.
> — [muvlon on hackernews](https://news.ycombinator.com/item?id=50334412)

> > Everything is broken and low-hanging fruit is everywhere. Harsh but true, at least in my experience. And ironically, bugs may resurface with new features being introduced. Their approach to include the source files directly, redefining function names using #defines as necessary truly fits the "hacksaw" comparison! Their point (5) regarding creating a made-to-fit buffer for testing so ASan can do its work properly sounds pretty subtle to me, and like something that should be changed upstream. And using memfd file descriptors for functions that require a path name as argument (their point (7)) is also pretty cool. TIL! Overall, I get the impression that their fuzzing tips are really geared towards fuzzing manually, not so much towards CI integration.
> — [felixs on lobsters · 2 points, 1 comments](https://lobste.rs/s/3as5ex/tips_for_more_effective_fuzz_testing_with#c_mtciic)

> Yes, that's true! I read it such that these tips help you quickly build fuzzers to find those low-hanging fruits and get them fixed. But for CI integration I imagine I'd rather change the structure of the program such that I don't need a "hacksaw" to get to the juicy parts, and maybe integrate the whole thing into my build system so I can scale building fuzzers easily.
> — [felixs on lobsters · 3 points](https://lobste.rs/s/3as5ex/tips_for_more_effective_fuzz_testing_with#c_gsemux)

**Source threads**

- [hackernews](https://news.ycombinator.com/item?id=42952792) · 4 points · 0 comments
- [hackernews](https://news.ycombinator.com/item?id=42991778) · 2 points · 0 comments
- [hackernews](https://news.ycombinator.com/item?id=50271106) · 115 points · 24 comments
- [hackernews](https://news.ycombinator.com/item?id=42970659) · 1 points · 0 comments
- [lobsters](https://lobste.rs/s/3as5ex/tips_for_more_effective_fuzz_testing_with) · 7 points · 3 comments

## Similar posts on daily.dev

- [The Sanitizers Handbook: Memory, Initialization, and Races](https://daily.dev/posts/the-sanitizers-handbook-memory-initialization-and-races-3hzwtj43v) · freeCodeCamp · 0 upvotes · 0 comments
- [Techniques for better software testing](https://daily.dev/posts/techniques-for-better-software-testing-s6dcxkskc) · Lobsters · 0 upvotes · 0 comments
- [Bugs that survive the heat of continuous fuzzing](https://daily.dev/posts/bugs-that-survive-the-heat-of-continuous-fuzzing-8bxtqt1dt) · GitHub Blog · 1 upvotes · 0 comments

---

Tags: [#c](https://daily.dev/tags/c), [#c++](https://daily.dev/tags/c++)

[View this post on daily.dev](https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Tips for more effective fuzz testing with AFL++","url":"https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix"},"datePublished":"2026-11-02T02:41:57.799Z","dateModified":"2026-11-02T10:43:00.685Z","description":"Fuzz testing with AFL++ finds bugs in C and C++ code, based on fuzzing roughly 1,000 projects over six years. Key tips: enable both ASan and UBSan together,...","image":"https://media.daily.dev/image/upload/s--OHB84bZF--/f_auto/v1722860399/public/Placeholder%2010","thumbnailUrl":"https://media.daily.dev/image/upload/s--OHB84bZF--/f_auto/v1722860399/public/Placeholder%2010","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"c,c++","timeRequired":"PT11M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"Tips for more effective fuzz testing with AFL++"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/tips-for-more-effective-fuzz-testing-with-afl--mboixgdix#faq","mainEntity":[{"@type":"Question","name":"why doesn't AddressSanitizer catch buffer overflows when I pass AFL++'s fuzz buffer directly into my target function","acceptedAnswer":{"@type":"Answer","text":"The buffer AFL++ allocates for __AFL_FUZZ_TESTCASE_BUF is larger than the reported length, so ASan cannot detect read overflows past that length when you pass it directly. The fix is to copy the data into a buffer sized exactly to the test case length (realloc and memcpy) before calling the target function, rather than passing the raw buffer and length. daily.dev surfaces fuzzing and sanitizer guidance for developers hardening C/C++ code against memory bugs."}},{"@type":"Question","name":"should I use AFL++ persistent mode or the normal fork mode for fuzzing a C program","acceptedAnswer":{"@type":"Answer","text":"Persistent mode, enabled via afl-gcc-fast or afl-clang-fast with __AFL_LOOP, is typically an order of magnitude faster than fuzzing a program in-place with afl-gcc or afl-clang. It does introduce pitfalls around state isolation between test iterations, such as leftover heap memory and global variables, which need to be reset or filled with a pattern each run. developers tuning fuzzing performance can track practical AFL++ configuration tips on daily.dev."}},{"@type":"Question","name":"how do I fuzz test a C function that only accepts a file path instead of a buffer","acceptedAnswer":{"@type":"Answer","text":"Create an in-memory file descriptor with memfd_create, then write the fuzz input to it with ftruncate and pwrite, and pass the path /proc/self/fd/3 (assuming fd 3) to the target function instead of a real file path. This avoids disk writes, works safely under parallel fuzzing since /proc paths are per-process, and needs no cleanup. engineers fuzzing legacy file-path-only APIs can reference concrete AFL++ patterns like this via daily.dev."}}]}
```

