From 14e454232c479b9f9bf903241b64e37bcf0c2e09 Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Mon, 14 Sep 2026 22:32:21 -0400 Subject: [PATCH 01/11] Created fb3-fall2026 folder + titled --- blog/fb3-fall2026/index.qmd | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 blog/fb3-fall2026/index.qmd diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd new file mode 100644 index 0000000..a0d6af7 --- /dev/null +++ b/blog/fb3-fall2026/index.qmd @@ -0,0 +1,10 @@ +--- +author: [Lukas Deemer, Johnny Sharsheev, Gregory M. Kapfhammer] +title: Fuzzing: Breaking Things with Random Inputs +date: '2026-09-09' +date-format: long +categories: [post, software engineering, fuzzing book] +description: Why fuzzing is important for software testing. +toc: true +page-layout: full +--- \ No newline at end of file From 2bfbb46a877bef54979e0dc2131823206d33f68e Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Tue, 15 Sep 2026 16:08:01 -0400 Subject: [PATCH 02/11] Added em dash and removed colon --- blog/fb3-fall2026/index.qmd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index a0d6af7..e406f1a 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -1,10 +1,11 @@ --- author: [Lukas Deemer, Johnny Sharsheev, Gregory M. Kapfhammer] -title: Fuzzing: Breaking Things with Random Inputs +title: Fuzzing — Breaking Things with Random Inputs date: '2026-09-09' date-format: long categories: [post, software engineering, fuzzing book] description: Why fuzzing is important for software testing. toc: true page-layout: full ---- \ No newline at end of file +--- + From 0ca52f0c7414c7f04f8cfc7b5686bf44e142a3ab Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Tue, 15 Sep 2026 16:22:05 -0400 Subject: [PATCH 03/11] What is Fuzzing? --- blog/fb3-fall2026/index.qmd | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index e406f1a..f218282 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -9,3 +9,14 @@ toc: true page-layout: full --- +## Overiew + +## Summary + +### What is Fuzzing? +#### Fuzzers +`Fuzzer` is a base class for fuzzers, with RandomFuzzer as a simple instantiation. The fuzz() method of Fuzzer objects and returns a string with a generated input. + +`>>> random_fuzzer = RandomFuzzer()` +`>>> random_fuzzer.fuzz()` +`%$<1&<%+=!"83?+)9:++9138 42/ "7;0-,)06 "1(2;6>?99$%7!!*#96=>2&-/(5*)=$;0$$+;<12"?30&` \ No newline at end of file From d728c4a261d806d4490816dc5b845e3193178321 Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Tue, 15 Sep 2026 19:08:40 -0400 Subject: [PATCH 04/11] RandomFuzzer --- blog/fb3-fall2026/index.qmd | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index f218282..e204ef6 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -9,14 +9,30 @@ toc: true page-layout: full --- -## Overiew +## Overview ## Summary ### What is Fuzzing? #### Fuzzers -`Fuzzer` is a base class for fuzzers, with RandomFuzzer as a simple instantiation. The fuzz() method of Fuzzer objects and returns a string with a generated input. +`Fuzzer` is a base class for fuzzers, with `RandomFuzzer` as a simple instantiation. The `fuzz()` method of `Fuzzer` objects and returns a string with a generated input. -`>>> random_fuzzer = RandomFuzzer()` -`>>> random_fuzzer.fuzz()` -`%$<1&<%+=!"83?+)9:++9138 42/ "7;0-,)06 "1(2;6>?99$%7!!*#96=>2&-/(5*)=$;0$$+;<12"?30&` \ No newline at end of file +```python +>>> random_fuzzer = RandomFuzzer() +>>> random_fuzzer.fuzz() +``` + +Output: `%$<1&<%+=!"83?+)9:++9138 42/ "7;0-,)06 "1(2;6>?99$%7!!*#96=>2&-/(5*)=$;0$$+;<12"?30&` + +The `RandomFuzzer` constructor allows a number of keyword arguments: + +```python +>>> print(RandomFuzzer.__init__.__doc__) +Produce strings of `min_length` to `max_length` characters + in the range [`char_start`, `char_start` + `char_range`) + +>>> random_fuzzer = RandomFuzzer(min_length=10, max_length=20, char_start=65, char_range=26) +>>> random_fuzzer.fuzz() +``` + +Output: `'XGZVDDPZOOW'` From a76230e9fbb36665678c3594a6e037b321de80c0 Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Wed, 16 Sep 2026 00:22:22 -0400 Subject: [PATCH 05/11] Runners --- blog/fb3-fall2026/Fuzzer&RandomFuzzer.png | Bin 0 -> 22696 bytes blog/fb3-fall2026/index.qmd | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 blog/fb3-fall2026/Fuzzer&RandomFuzzer.png diff --git a/blog/fb3-fall2026/Fuzzer&RandomFuzzer.png b/blog/fb3-fall2026/Fuzzer&RandomFuzzer.png new file mode 100644 index 0000000000000000000000000000000000000000..9b2b3fd9dad62ee42cfdd47a14cb20511bf7e3a6 GIT binary patch literal 22696 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 Q#f2_dQ(Z@`RK+UnAO0px-~a#s literal 0 HcmV?d00001 diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index e204ef6..5f91f99 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -28,11 +28,26 @@ The `RandomFuzzer` constructor allows a number of keyword arguments: ```python >>> print(RandomFuzzer.__init__.__doc__) -Produce strings of `min_length` to `max_length` characters - in the range [`char_start`, `char_start` + `char_range`) +``` + +Output: Produce strings of `min_length` to `max_length` characters in the range [`char_start`, `char_start` + `char_range`) +```python >>> random_fuzzer = RandomFuzzer(min_length=10, max_length=20, char_start=65, char_range=26) >>> random_fuzzer.fuzz() ``` Output: `'XGZVDDPZOOW'` + +![Fuzzer & Random Fuzzer](Fuzzer&RandomFuzzer.png) + +#### Runners +A `Fuzzer` can be paired with a `Runner` which takes the fuzzed strings as input. Its result is a class-specific *status* and an *outcome* (`PASS`, `FAIL`, or `UNRESOLVED`). A `PrintRunner` will simply print out the given input and return a `PASS` outcome: + +```python +>>> print_runner = PrintRunner() +>>> random_fuzzer.run(print_runner) +``` + +Outcome: `('EQYGAXPTVPJGTYHXFJ', 'UNRESOLVED')` + From b3aa33756268df0ce486d21083fa5db8cdab5cbe Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Wed, 16 Sep 2026 00:36:23 -0400 Subject: [PATCH 06/11] Runner 2 --- blog/fb3-fall2026/Runners.png | Bin 0 -> 32899 bytes blog/fb3-fall2026/index.qmd | 15 +++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 blog/fb3-fall2026/Runners.png diff --git a/blog/fb3-fall2026/Runners.png b/blog/fb3-fall2026/Runners.png new file mode 100644 index 0000000000000000000000000000000000000000..6ddd21fa5d6ffe05dedd8aefb68cbcc72a33e612 GIT binary patch literal 32899 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 cat = ProgramRunner('cat') +>>> random_fuzzer.run(cat) +``` + +Outcome: `(CompletedProcess(args='cat', returncode=0, stdout='BZOQTXFBTEOVYX', stderr=''), + 'PASS')` + + ![Runners](Runners.png) + + ### A Testing Assignment + + \ No newline at end of file From cabbd7a4697bf56129ca5486ceac80fdd1ba51f5 Mon Sep 17 00:00:00 2001 From: Jsharsh33v <156821800+Jsharsh33v@users.noreply.github.com> Date: Wed, 16 Sep 2026 01:27:24 -0400 Subject: [PATCH 07/11] docs: add FB3 sections and FuzzerCheck link --- blog/fb3-fall2026/index.qmd | 50 ++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index c8605e7..0ed1d32 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -65,4 +65,52 @@ Outcome: `(CompletedProcess(args='cat', returncode=0, stdout='BZOQTXFBTEOVYX', s ### A Testing Assignment - \ No newline at end of file + +### Catching Errors + +Fuzzing also needs checks for failures that do not cause obvious crashes. + +#### Generic Checkers + +Generic checkers detect common problems. For example, AddressSanitizer detects invalid memory accesses in C and C++ programs. Outputs can also be checked for leaked secret information. + +#### Program-Specific Checkers + +Program-specific checkers use assertions to verify rules about a program's data or results. The chapter's [airport-code example](https://www.fuzzingbook.org/html/Fuzzer.html#Program-Specific-Checkers) checks for three uppercase letters. Here is a simplified version: + +```{python} +def check_airport_code(code): + assert len(code) == 3, "Expected three characters" + assert all(c.isalpha() and c.isupper() for c in code), "Expected uppercase letters" + +for code in ["JFK", "jfK"]: + try: + check_airport_code(code) + print(code, "PASS") + except AssertionError as error: + print(code, "FAIL:", error) +``` + +`JFK` passes both checks. `jfK` fails because it contains lowercase letters. + +#### Static Code Checkers + +Static checkers inspect code without running it. For example, mypy can detect type mismatches, but it cannot check every program-specific rule. + +### A Fuzzing Architecture + +The classes introduced above separate two responsibilities: `Fuzzer` creates inputs, and `Runner` handles them and classifies the results. + +`run()` sends one generated input to a runner, while `runs()` repeats the process. This separation lets us reuse a generator with different targets. + +A runner reports `PASS`, `FAIL`, or `UNRESOLVED`. Passing means its checks found no failure; it does not prove correctness. `UNRESOLVED` means the runner could not judge the result. + +::: {.callout-note appearance="minimal" title="Open-Source Tool for Software Engineers" collapse="false"} + +Our team built `FuzzerCheck`, a Python command-line tool that demonstrates random fuzzing using two examples adapted from the chapter. It generates inputs, reports passing and failing trials, and displays sample failing inputs. + +You can view the project here: [FuzzerCheck on GitHub](https://github.com/Jsharsh33v/fuzzercheck). + +::: + +{{< include /_back-blog.qmd >}} \ No newline at end of file From fe523b8b9bcf909d10c78aec3461715f54916328 Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Wed, 16 Sep 2026 09:01:35 -0400 Subject: [PATCH 08/11] A Simple Fuzzer --- blog/fb3-fall2026/index.qmd | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index 0ed1d32..b3e8f1b 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -65,7 +65,55 @@ Outcome: `(CompletedProcess(args='cat', returncode=0, stdout='BZOQTXFBTEOVYX', s ### A Testing Assignment +Fuzzing was created in the Fall of 1988. While sitting in his apartment in Wisconsin, Madison, professor Barton Miller was connected to his university computer via a 1200 baud telephone line. The thunderstorm caused noise on the line, and this noise in turn caused the UNIX commands on either end to get bad inputs and crash. He wanted to investigate the extent of the problem and its causes. So he made a *programming exerise* for his students at the University of Wisconsin-Madison. This exercise would have his students create the first fuzzers. +This is how the [assignment](https://pages.cs.wisc.edu/~bart/fuzz/CS736-Projects-f1988.pdf) read: + +>The goal of this project is to evaluate the robustness of various UNIX utility programs, given an unpredictable input stream. [...] First, you will build a fuzz generator. This is a program that will output a random character stream. Second, you will take the fuzz generator and use it to attack as many UNIX utilities as possible, with the goal of trying to break them. + +This assignment captures the essence of fuzzing: *Create random inputs, and see if they break things*. Just let it run long enough, and you'll see. + +### A Simple Fuzzer + +Let's build a fuzz generator. The idea is to produce random characters, adding them to a buffer string variable (out), and finally returning the string. + +This implementation uses the following Python features and functions: + +- `random.randrange(start, end)` - return a random number [`start`, `end`) +- `range(start, end)` – create an iterator (which can be used as a list) with integers in the range [`start, end`). +- `for elem in list: body` – execute body in a loop with `elem` taking each value from `list`. +- `for i in range(start, end): body` – execute body in a loop with `i` from `start` to `end` — 1. +- `chr(n)` – return a character with ASCII code `n` + +Here is the actual `fuzzer()` function: + +```python +def fuzzer(max_length: int = 100, char-start: int = 32, char_range: int = 32) -> str: + """A string of up to `max_length` characters in the range [`char_start`, `char_start` + `char_range`]""" + string_length = random.randrange(0, max_length + 1) + out = "" + for i in range(0, string_length): + out += chr(random.randrange(char_start, char_start + char_range)) + return out +``` + +With its default arguments, the `fuzzer()` function returns a string of random characters: + +```python +fuzzer() +``` + +Output: `!7#%"*#0=)$;%6*;>638:*>80"=(/*:-(2<4 !:5*6856&?""11<7+%<%7,4.8,*+&,,$,."` + +Bart Miller had created the term "fuzz" as the name for such random, unstructured data. + +It is also possible to produce a series of lowercase letters. We use `ord(c)` to return the ASCII code of the character c. + +```python +fuzzer(1000, ord('a'), 26) +``` + +Output: `zskscocrxllosagkvaszlngpysurezehvcqcghygphnhonehczraznkibltfmocxddoxcmrvatcleysksodzlwmzdndoxrjfqigjhqjxkblyrtoaydlwwisrvxtxsejhfbnforvlfisojqaktcxpmjqsfsycisoexjctydzxzzutukdztxvdpqbjuqmsectwjvylvbixzfmqiabdnihqagsvlyxwxxconminadcaqjdzcnzfjlwccyudmdfceiepwvyggepjxoeqaqbjzvmjdlebxqvehkmlevoofjlilegieeihmetjappbisqgrjhglzgffqrdqcwfmmwqecxlqfpvgtvcddvmwkplmwadgiyckrfjddxnegvmxravaunzwhpfpyzuyyavwwtgykwfszasvlbwojetvcygectelwkputfczgsfsbclnkzzcjfywitooygjwqujseflqyvqgyzpvknddzemkegrjjrshbouqxcmixnqhgsgdwgzwzmgzfajymbcfezqxndbmzwnxjeevgtpjtcwgbzptozflrwvuopohbvpmpaifnyyfvbzzdsdlznusarkmmtazptbjbqdkrsnrpgdffemnpehoapiiudokczwrvpsonybfpaeyorrgjdmgvkvupdtkrequicexqkoikygepawmwsdcrhivoegynnhodfhryeqbebtbqnwhogdfrsrksntqjbocvislhgrgchkhpaiugpbdygwkhrtyniufabdnqhtnwreiascfvmuhettfpbowbjadfxnbtzhobnxsnf` ### Catching Errors Fuzzing also needs checks for failures that do not cause obvious crashes. From 0694366906b8b802bf98db035622fd82444dd07f Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Wed, 16 Sep 2026 09:25:44 -0400 Subject: [PATCH 09/11] Invoking --- blog/fb3-fall2026/index.qmd | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index b3e8f1b..45c2417 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -114,6 +114,85 @@ fuzzer(1000, ord('a'), 26) ``` Output: `zskscocrxllosagkvaszlngpysurezehvcqcghygphnhonehczraznkibltfmocxddoxcmrvatcleysksodzlwmzdndoxrjfqigjhqjxkblyrtoaydlwwisrvxtxsejhfbnforvlfisojqaktcxpmjqsfsycisoexjctydzxzzutukdztxvdpqbjuqmsectwjvylvbixzfmqiabdnihqagsvlyxwxxconminadcaqjdzcnzfjlwccyudmdfceiepwvyggepjxoeqaqbjzvmjdlebxqvehkmlevoofjlilegieeihmetjappbisqgrjhglzgffqrdqcwfmmwqecxlqfpvgtvcddvmwkplmwadgiyckrfjddxnegvmxravaunzwhpfpyzuyyavwwtgykwfszasvlbwojetvcygectelwkputfczgsfsbclnkzzcjfywitooygjwqujseflqyvqgyzpvknddzemkegrjjrshbouqxcmixnqhgsgdwgzwzmgzfajymbcfezqxndbmzwnxjeevgtpjtcwgbzptozflrwvuopohbvpmpaifnyyfvbzzdsdlznusarkmmtazptbjbqdkrsnrpgdffemnpehoapiiudokczwrvpsonybfpaeyorrgjdmgvkvupdtkrequicexqkoikygepawmwsdcrhivoegynnhodfhryeqbebtbqnwhogdfrsrksntqjbocvislhgrgchkhpaiugpbdygwkhrtyniufabdnqhtnwreiascfvmuhettfpbowbjadfxnbtzhobnxsnf` + +### Fuzzing External Programs + +Let's invoke an external program with fuzzed inputs. First, we create an *input file* with fuzzed test data; then we feed this input file into a program of choice. + +#### Creating Input Files +```python +basename = "input.txt" +tempdir = tempfile.mkdtemp() +FILE = os.path.oin(tempdir, basename) +print(FILE) +``` + +Output: `/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/tmp33gvbu2n/input.txt` + +Let's open it. The Python `open()` function opens a file into which we can then write arbitrary contents. Very commonly, it is used with the `with` statement, which ensures that the file is closed as soon as it is no longer needed. + +```python +data = fuzzer() +with open(FILE, "w") as f: + f.write(data) +``` + +The file can be verified by reading its contents: + +```python +contents = open(FILE).read() +print(contents) +assert(contents == data) +``` + +Output: `18%55*,5` + +#### Invoking External Programs + +With that input file, we can invoke a program on it. + +We will use the `bc` calculator program, which takes an arithmetic expression and evaluates it. + +To invoke `bc` let's use the Python `subprocess` module. This is how it works: + +```python +program = "bc" +with open(FILE, "w") as f: + f.write("2 + 2\n") +result = subprocess.run([program, FILE], +stdin=subprocess.DEVNULL, +stdout=subprocess.PIPE, +stderr=subprocess.PIPE, +universal_newlines=True) +``` + +Using `result`, we can check the program's output. In the case of `bc`, this is the result: + +```python +result.stdout +``` + +Output: `4\n` + +The status may also be checked, a value of 0 indicating the program terminated correctly. + +```python +result.returncode +``` + +Output: `0` + +Any error messages would be available in `results.stderr`: + +```python +results.stderr +``` + +Output: `''` + +Any program is able to go through this process, however, you should be careful as you could change or even damage your system. + + ### Catching Errors Fuzzing also needs checks for failures that do not cause obvious crashes. From 5f386da6dc6af8d93cba8b9b9ae64a64c558e33c Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Wed, 16 Sep 2026 10:03:33 -0400 Subject: [PATCH 10/11] Rogue --- blog/fb3-fall2026/index.qmd | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index 45c2417..e9875f8 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -192,6 +192,50 @@ Output: `''` Any program is able to go through this process, however, you should be careful as you could change or even damage your system. +### Bug Fuzzers Find + +When Miller and his students ran their first fuzzers in 1989, they found an alarming result: About **A third of the UNIX utilities** they fuzzed had issues - they crashed, hung, or otherwise failed when confronted with fuzzing input. This also included the `bc` program above. + +Because many of these UNIX utilities were used in scripts that would also process network input, this was a potential hazard, one which need fuzzers to fix. + +#### Buffer Overflows + +**Buffer overflows** are triggered when going over a program's built-in maximum lengths for inputs and input elements. + +Buffer overflow behavior can be easily simulated in a Python function: + +```Python +def crash_if_too_long(s): + buffer = "Thursday" + if len(s) > len(buffer): + raise ValueError +``` + +This leads to a crash very quickly. + +```Python +trials = 100 +with ExpectError(): + for i in range(trials): + s = fuzzer() + crash_if_too_long(s) +``` + +Output: `Traceback (most recent call last): File "/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_1932/292568387.py", line 5, in crash_if_too_long(s) File "/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_1932/2784561514.py", line 4, in crash_if_too_long raise ValueError ValueError (expected)` + +The `with ExpectError()` line in the above code ensures that the error message is printed, yet execution continues; this is to differentiate this "expected" error from "unexpected" errors in other code examples. + +#### Missing Error Checks + +Many programming languages do not have exceptions, but instead have functions return special **error codes** in exceptional circumstances. The C function `getchar()`, for instance, normally returns a character from the standard input; if no input is available anymore, it returns the special value `EOF`(end of file). + +In a situation where, for example, `getchar()` reaches and scans a space character, `getchar()` could return `EOF`, and keep returning `EOF` when called again. This would lead to an infinite loop. However, if a line with the `with ExpectTimeout()` was implemented, the code would be interrupted after a set amount of time, printing an error message. + +#### Rogue Numbers + +When fuzzing, it is very, very easy to generate **uncommon values** in the input, which can lead to a load of interesting behavior. The value could exceed program memory, lead to a crash, or an array of other unexpected outcomes. + +It is important to utilize these rogue numbers because it is much better to quickly fail the program than to allow it to destroy something later down the line. ### Catching Errors From a0a521c657e41e360bd7519b3a9e96b76e4fe9e3 Mon Sep 17 00:00:00 2001 From: MIXER-Lukas1950 Date: Wed, 16 Sep 2026 10:08:47 -0400 Subject: [PATCH 11/11] Lessons Learned plus Source --- blog/fb3-fall2026/index.qmd | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/blog/fb3-fall2026/index.qmd b/blog/fb3-fall2026/index.qmd index e9875f8..1f5c11c 100644 --- a/blog/fb3-fall2026/index.qmd +++ b/blog/fb3-fall2026/index.qmd @@ -276,6 +276,11 @@ The classes introduced above separate two responsibilities: `Fuzzer` creates inp A runner reports `PASS`, `FAIL`, or `UNRESOLVED`. Passing means its checks found no failure; it does not prove correctness. `UNRESOLVED` means the runner could not judge the result. +### Lessons Learned +- Randomly generating inputs ("fuzzing") is a simple, cost-effective way to quickly test arbitrary programs for their robustness. +- Bugs fuzzers find are mainly due to errors and deficiencies in *input processing*. +- To catch errors, have as many *consistency checkers* as possible. + ::: {.callout-note appearance="minimal" title="Open-Source Tool for Software Engineers" collapse="false"} Our team built `FuzzerCheck`, a Python command-line tool that demonstrates random fuzzing using two examples adapted from the chapter. It generates inputs, reports passing and failing trials, and displays sample failing inputs. @@ -284,4 +289,6 @@ You can view the project here: [FuzzerCheck on GitHub](https://github.com/Jshars ::: +{{< include /_fuzzingbook-reference.qmd >}} + {{< include /_back-blog.qmd >}} \ No newline at end of file