<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Notes to a Future Self - fuzzing</title>
    <subtitle>Mostly software</subtitle>
    <link rel="self" type="application/atom+xml" href="https://jhugman.com/tags/fuzzing/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://jhugman.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-12T00:00:00+00:00</updated>
    <id>https://jhugman.com/tags/fuzzing/atom.xml</id>
    <entry xml:lang="en">
        <title>Automated exploratory testing and bugfixing</title>
        <published>2026-07-12T00:00:00+00:00</published>
        <updated>2026-07-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              James Hugman
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://jhugman.com/posts/automated-bug-finding/"/>
        <id>https://jhugman.com/posts/automated-bug-finding/</id>
        
        <content type="html" xml:base="https://jhugman.com/posts/automated-bug-finding/">&lt;p&gt;My current side project, the one that&#x27;s been consuming my hobby-less time for the past 15 years or so&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
is a small programming language and associated tools. The language itself is called turo or turo-lang.&lt;&#x2F;p&gt;
&lt;p&gt;This post is not about that project or the language, but about an emergent workflow which is quite interesting, and transferable to other projects.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;it&#x27;s on its fourth iteration now, and I put it down for more than a decade, so it&#x27;s not that old or mature.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-building-blocks&quot;&gt;The Building Blocks&lt;&#x2F;h2&gt;
&lt;p&gt;I say emergent, so these are the building blocks:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I have a detailed &lt;code&gt;SPEC.md&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The first thing I build is: a CLI to exercise the language. There&#x27;s a &lt;code&gt;--json&lt;&#x2F;code&gt; flag for agents to use, and &lt;code&gt;--debug&lt;&#x2F;code&gt; flag to turn on verbose logging.&lt;&#x2F;li&gt;
&lt;li&gt;The second thing I build is: a test runner which reads YAML example files and generates tests. Inputs and outputs, but can probe the output, the current turo-lang scope, the types of each of the turo-lang variables etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The example files keep the tests readable and implementation agnostic, without the ceremony of setup or teardown. It becomes a real repository of tests from test-driven development, from regressions, and debugging traces. So far, so &lt;a class=&quot;external-link&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Model-based_testing&quot;&gt;model-based testing&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Next is a skill I made. It&#x27;s a non-invasive debugging flow, which I&#x27;ve coined as doctor-patient-debugging&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;given a turo-lang program as input, evaluate the program in your head, then use the CLI. Notice how it succeeds or fails&lt;&#x2F;li&gt;
&lt;li&gt;make variations of the input across different axes; to survey the shape of the error, testing with the CLI each time&lt;&#x2F;li&gt;
&lt;li&gt;form theories based on this survey: is it a particular subsystem, or an interaction between subsystems&lt;&#x2F;li&gt;
&lt;li&gt;use those theories to make predictions which can be used to prove or disprove those theories.&lt;&#x2F;li&gt;
&lt;li&gt;only after proving a solid theory about what is happening should you open a source file.&lt;&#x2F;li&gt;
&lt;li&gt;you can then convert the CLI probes into YAML fixtures, to feed into your RED GREEN REFACTOR process.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I name it that here, but I&#x27;m sure this is an already named process. I have heard this called &lt;a class=&quot;external-link&quot; href=&quot;https:&#x2F;&#x2F;csc151.cs.grinnell.edu&#x2F;readings&#x2F;hypothesis-driven-debugging.html&quot;&gt;hypothesis-driven-debugging&lt;&#x2F;a&gt;, but I prefer my name.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The skill relies on a rich input language, a debugging interface to a CLI, and a fast and synchronous program under test.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-bug-finding-workflow&quot;&gt;The Bug-finding workflow&lt;&#x2F;h2&gt;
&lt;p&gt;The final part automates the process with a dynamic workflow, with a series of agents:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;fuzzers&lt;&#x2F;li&gt;
&lt;li&gt;doctor-patient debuggers&lt;&#x2F;li&gt;
&lt;li&gt;triagers&lt;&#x2F;li&gt;
&lt;li&gt;fixers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Have a fuzzer subagent:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Read the SPEC.md&lt;&#x2F;li&gt;
&lt;li&gt;Use the CLI to test a named area of the language. Once you find a bug, don&#x27;t hammer on it, jump to a new idea.&lt;&#x2F;li&gt;
&lt;li&gt;Once you have found a handful of bugs in an area, stop and report back the input strings and expected behaviours.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can get the workflow script to dispatch multiple fuzzers at once, one for each area in the spec. I like to set a &quot;difficulty level&quot; of the bugs: find the easily surfaced bugs which a user will find within minutes, rather than going deep on a subsystem which looks solid.&lt;&#x2F;p&gt;
&lt;p&gt;Once all the fuzzers come back, you&#x27;ll have perhaps 10–50 input strings to work through, so the next is to spin up doctor-patient debug agents that develop theories of the bug. Each of these returns a packet of YAML fixtures, an investigation trace, and a likely intervention that will fix that class of errors.&lt;&#x2F;p&gt;
&lt;p&gt;Once the doctor-patient agents come back, we can have triage agents review prioritize and dedupe the bug fixes. This is the agent that decide if the bugfix is too invasive, and needs design work, or that it is the SPEC that is incorrect, or we&#x27;re missing a feature, not just a bug.&lt;&#x2F;p&gt;
&lt;p&gt;At this point we should have a prioritized list of tests and bugfixes which we can apply as a part of an ordinary RED GREEN REFACTOR loop.&lt;&#x2F;p&gt;
&lt;p&gt;Now, we get one fixer agent to fix one bug at a time, each bug with a minimal reproduction, some boundary tests, an investigation and a likely fix. We could parallelize more by making worktrees, but I think that&#x27;s perhaps a little heavyweight for this.&lt;&#x2F;p&gt;
&lt;p&gt;Once the fixer agent is done, then we can loop back to the fuzzers again, but with the difficulty level turned up.&lt;&#x2F;p&gt;
&lt;p&gt;The fixer is the &lt;em&gt;only&lt;&#x2F;em&gt; agent that actually changes the code, so has to be running sequentially; every other agent scales horizontally.&lt;&#x2F;p&gt;
&lt;p&gt;After a few goes round this outer loop, you will have found &lt;em&gt;lots&lt;&#x2F;em&gt; of bugs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;&#x2F;h2&gt;
&lt;p&gt;For turo, the summary was:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;~400+ agent-runs, &amp;gt;45M tokens, ~45+ hours of compute across the line.
1,900 cases across 20 themed buckets — 1,473 green &#x2F; 427 ignored. Landed via 133 commits touching the corpus, 105 of them &lt;code&gt;fix(...)&lt;&#x2F;code&gt; behaviour fixes.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For a project with 60k lines of Rust (25k production), that doesn&#x27;t sound too shabby.&lt;&#x2F;p&gt;
&lt;p&gt;The fan-out of the fuzzing and the root-cause analysis from the hypothesis-driven debugging pair very well.&lt;&#x2F;p&gt;
&lt;p&gt;## Next&lt;&#x2F;p&gt;
&lt;p&gt;My next experiment with this flow, inspired by the &lt;a class=&quot;external-link&quot; href=&quot;https:&#x2F;&#x2F;bun.com&#x2F;blog&#x2F;bun-in-rust&quot;&gt;Bun In Rust blog post&lt;&#x2F;a&gt;: apply all the fixes all at once, then bug fix the bug fix.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d also like to try with different fuzzing agents: an hour of release time with a thousand users finds a different set of bugs than a single manual tester doing 1000 hours of exploratory testing.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
