{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# When To Stop Fuzzing\n",
"\n",
"In the past chapters, we have discussed several fuzzing techniques. Knowing _what_ to do is important, but it is also important to know when to _stop_ doing things. In this chapter, we will learn when to _stop fuzzing_ – and use a prominent example for this purpose: The *Enigma* machine that was used in the second world war by the navy of Nazi Germany to encrypt communications, and how Alan Turing and I.J. Good used _fuzzing techniques_ to crack ciphers for the Naval Enigma machine.\n",
"\n",
"Turing did not only develop the foundations of computer science, the Turing machine. Together with his assistant I.J. Good, he also invented estimators of the probability of an event occurring that has never previously occurred. We show how the Good-Turing estimator can be used to quantify the *residual risk* of a fuzzing campaign that finds no vulnerabilities. Meaning, we show how it estimates the probability of discovering a vulnerability when no vulnerability has been observed before throughout the fuzzing campaign.\n",
"\n",
"We discuss means to speed up [coverage-based fuzzers](Coverage.ipynb) and introduce a range of estimation and extrapolation methodologies to assess and extrapolate fuzzing progress and residual risk."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:42.732680Z",
"iopub.status.busy": "2025-10-26T18:02:42.731926Z",
"iopub.status.idle": "2025-10-26T18:02:44.289957Z",
"shell.execute_reply": "2025-10-26T18:02:44.285569Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
" \n",
" "
],
"text/plain": [
""
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from bookutils import YouTubeVideo\n",
"YouTubeVideo('od3DcJcr0d4')"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"**Prerequisites**\n",
"\n",
"* _The chapter on [Coverage](Coverage.ipynb) discusses how to use coverage information for an executed test input to guide a coverage-based mutational greybox fuzzer_.\n",
"* Some knowledge of statistics is helpful."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.361563Z",
"iopub.status.busy": "2025-10-26T18:02:44.360473Z",
"iopub.status.idle": "2025-10-26T18:02:44.373213Z",
"shell.execute_reply": "2025-10-26T18:02:44.370062Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import bookutils.setup"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.384585Z",
"iopub.status.busy": "2025-10-26T18:02:44.383402Z",
"iopub.status.idle": "2025-10-26T18:02:44.410318Z",
"shell.execute_reply": "2025-10-26T18:02:44.397997Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"from typing import Dict, List"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": true,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## The Enigma Machine\n",
"\n",
"It is autumn in the year of 1938. Turing has just finished his PhD at Princeton University demonstrating the limits of computation and laying the foundation for the theory of computer science. Nazi Germany is rearming. It has reoccupied the Rhineland and annexed Austria against the Treaty of Versailles. It has just annexed the Sudetenland in Czechoslovakia and begins preparations to take over the rest of Czechoslovakia despite an agreement just signed in Munich.\n",
"\n",
"Meanwhile, the British intelligence is building up their capability to break encrypted messages used by the Germans to communicate military and naval information. The Germans are using [Enigma machines](https://en.wikipedia.org/wiki/Enigma_machine) for encryption. Enigma machines use a series of electromechanical rotor cipher machines to protect military communication. Here is a picture of an Enigma machine:"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": true,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"By the time Turing joined the British Bletchley park, the Polish intelligence reverse engineered the logical structure of the Enigma machine and built a decryption machine called *Bomba* (perhaps because of the ticking noise they made). A bomba simulates six Enigma machines simultaneously and tries different decryption keys until the code is broken. The Polish bomba might have been the very _first fuzzer_."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": true,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Turing took it upon himself to crack ciphers of the Naval Enigma machine, which were notoriously hard to crack. The Naval Enigma used, as part of its encryption key, a three letter sequence called *trigram*. These trigrams were selected from a book, called *Kenngruppenbuch*, which contained all trigrams in a random order."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": true,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### The Kenngruppenbuch\n",
"\n",
"Let's start with the Kenngruppenbuch (K-Book).\n",
"\n",
"We are going to use the following Python functions.\n",
"* `random.shuffle(elements)` - shuffle *elements* and put items in random order.\n",
"* `random.choices(elements, weights)` - choose an item from *elements* at random. An element with twice the *weight* is twice as likely to be chosen.\n",
"* `log(a)` - returns the natural logarithm of a.\n",
"* `a ** b` - means `a` to the power of `b` (a.k.a. [power operator](https://docs.python.org/3/reference/expressions.html#the-power-operator))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.431590Z",
"iopub.status.busy": "2025-10-26T18:02:44.431223Z",
"iopub.status.idle": "2025-10-26T18:02:44.447705Z",
"shell.execute_reply": "2025-10-26T18:02:44.441354Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import string"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.462409Z",
"iopub.status.busy": "2025-10-26T18:02:44.461615Z",
"iopub.status.idle": "2025-10-26T18:02:44.610563Z",
"shell.execute_reply": "2025-10-26T18:02:44.603479Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import numpy\n",
"from numpy import log"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.627421Z",
"iopub.status.busy": "2025-10-26T18:02:44.626614Z",
"iopub.status.idle": "2025-10-26T18:02:44.648398Z",
"shell.execute_reply": "2025-10-26T18:02:44.638663Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"We start with creating the set of trigrams:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.686359Z",
"iopub.status.busy": "2025-10-26T18:02:44.684936Z",
"iopub.status.idle": "2025-10-26T18:02:44.720201Z",
"shell.execute_reply": "2025-10-26T18:02:44.718211Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"letters = list(string.ascii_letters[26:]) # upper-case characters\n",
"trigrams = [str(a + b + c) for a in letters for b in letters for c in letters]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.745038Z",
"iopub.status.busy": "2025-10-26T18:02:44.742218Z",
"iopub.status.idle": "2025-10-26T18:02:44.773720Z",
"shell.execute_reply": "2025-10-26T18:02:44.769522Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"random.shuffle(trigrams)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.788374Z",
"iopub.status.busy": "2025-10-26T18:02:44.787418Z",
"iopub.status.idle": "2025-10-26T18:02:44.814152Z",
"shell.execute_reply": "2025-10-26T18:02:44.804068Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"['TJK', 'NWV', 'LBM', 'AZC', 'GZP', 'ADE', 'DNO', 'OQL', 'FGK', 'IPT']"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"trigrams[:10]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"These now go into the Kenngruppenbuch. However, it was observed that some trigrams were more likely chosen than others. For instance, trigrams at the top-left corner of any page, or trigrams on the first or last few pages were more likely than one somewhere in the middle of the book or page. We reflect this difference in distribution by assigning a _probability_ to each trigram, using Benford's law as introduced in [Probabilistic Fuzzing](ProbabilisticGrammarFuzzer.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Recall, that Benford's law assigns the $i$-th digit the probability $\\log_{10}\\left(1 + \\frac{1}{i}\\right)$ where the base 10 is chosen because there are 10 digits $i\\in [0,9]$. However, Benford's law works for an arbitrary number of \"digits\". Hence, we assign the $i$-th trigram the probability $\\log_b\\left(1 + \\frac{1}{i}\\right)$ where the base $b$ is the number of all possible trigrams $b=26^3$. "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.842916Z",
"iopub.status.busy": "2025-10-26T18:02:44.842081Z",
"iopub.status.idle": "2025-10-26T18:02:44.938155Z",
"shell.execute_reply": "2025-10-26T18:02:44.918385Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"k_book = {} # Kenngruppenbuch\n",
"\n",
"for i in range(1, len(trigrams) + 1):\n",
" trigram = trigrams[i - 1]\n",
" # choose weights according to Benford's law\n",
" k_book[trigram] = log(1 + 1 / i) / log(26**3 + 1)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Here's a random trigram from the Kenngruppenbuch:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.957839Z",
"iopub.status.busy": "2025-10-26T18:02:44.957401Z",
"iopub.status.idle": "2025-10-26T18:02:44.979542Z",
"shell.execute_reply": "2025-10-26T18:02:44.975982Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'PSK'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"random_trigram = random.choices(list(k_book.keys()), weights=list(k_book.values()))[0]\n",
"random_trigram"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"And this is its probability:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:44.999170Z",
"iopub.status.busy": "2025-10-26T18:02:44.998718Z",
"iopub.status.idle": "2025-10-26T18:02:45.013983Z",
"shell.execute_reply": "2025-10-26T18:02:45.009444Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"np.float64(0.0008284144853894445)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"k_book[random_trigram]"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Fuzzing the Enigma\n",
"\n",
"In the following, we introduce an extremely simplified implementation of the Naval Enigma based on the trigrams from the K-book. Of course, the encryption mechanism of the actual Enigma machine is much more sophisticated and worthy of a much more detailed investigation. We encourage the interested reader to follow up with further reading listed in the Background section.\n",
"\n",
"The staff at Bletchley Park can only check whether an encoded message is encoded with a (guessed) trigram.\n",
"Our implementation `naval_enigma()` takes a `message` and a `key` (i.e., the guessed trigram). If the given key matches the (previously computed) key for the message, `naval_enigma()` returns `True`."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.027090Z",
"iopub.status.busy": "2025-10-26T18:02:45.026441Z",
"iopub.status.idle": "2025-10-26T18:02:45.138030Z",
"shell.execute_reply": "2025-10-26T18:02:45.134327Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"from Fuzzer import RandomFuzzer\n",
"from Fuzzer import Runner"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.158641Z",
"iopub.status.busy": "2025-10-26T18:02:45.152607Z",
"iopub.status.idle": "2025-10-26T18:02:45.180172Z",
"shell.execute_reply": "2025-10-26T18:02:45.178375Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"class EnigmaMachine(Runner):\n",
" def __init__(self, k_book):\n",
" self.k_book = k_book\n",
" self.reset()\n",
"\n",
" def reset(self):\n",
" \"\"\"Resets the key register\"\"\"\n",
" self.msg2key = {}\n",
" self.cur_msg = \"\"\n",
"\n",
" def internal_msg2key(self, message):\n",
" \"\"\"Internal helper method. \n",
" Returns the trigram for an encoded message.\"\"\"\n",
" if message not in self.msg2key:\n",
" # Simulating how an officer chooses a key from the Kenngruppenbuch\n",
" # to encode the message.\n",
" self.msg2key[message] = \\\n",
" random.choices(list(self.k_book.keys()),\n",
" weights=list(self.k_book.values()))[0]\n",
" trigram = self.msg2key[message]\n",
" return trigram\n",
"\n",
" def naval_enigma(self, message, key):\n",
" \"\"\"Returns true if 'message' is encoded with 'key'\"\"\"\n",
" if key == self.internal_msg2key(message):\n",
" return True\n",
" else:\n",
" return False"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"To \"fuzz\" the `naval_enigma()`, our job will be to come up with a key that matches a given (encrypted) message. Since the keys only have three characters, we have a good chance to achieve this in much less than a second. (Of course, longer keys will be much harder to find via random fuzzing.)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.190759Z",
"iopub.status.busy": "2025-10-26T18:02:45.190457Z",
"iopub.status.idle": "2025-10-26T18:02:45.207066Z",
"shell.execute_reply": "2025-10-26T18:02:45.195961Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"class EnigmaMachine(EnigmaMachine):\n",
" def run(self, tri):\n",
" \"\"\"PASS if cur_msg is encoded with trigram tri\"\"\"\n",
" if self.naval_enigma(self.cur_msg, tri):\n",
" outcome = self.PASS\n",
" else:\n",
" outcome = self.FAIL\n",
"\n",
" return (tri, outcome)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now we can use the `EnigmaMachine` to check whether a certain message is encoded with a certain trigram."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.215675Z",
"iopub.status.busy": "2025-10-26T18:02:45.215139Z",
"iopub.status.idle": "2025-10-26T18:02:45.231024Z",
"shell.execute_reply": "2025-10-26T18:02:45.228639Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"('AAA', 'FAIL')"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"enigma = EnigmaMachine(k_book)\n",
"enigma.cur_msg = \"BrEaK mE. L0Lzz\"\n",
"enigma.run(\"AAA\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"The simplest way to crack an encoded message is by brute forcing. Suppose, at Bletchley park they would try random trigrams until a message is broken."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.261147Z",
"iopub.status.busy": "2025-10-26T18:02:45.258132Z",
"iopub.status.idle": "2025-10-26T18:02:45.276871Z",
"shell.execute_reply": "2025-10-26T18:02:45.269080Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"class BletchleyPark:\n",
" def __init__(self, enigma):\n",
" self.enigma = enigma\n",
" self.enigma.reset()\n",
" self.enigma_fuzzer = RandomFuzzer(\n",
" min_length=3,\n",
" max_length=3,\n",
" char_start=65,\n",
" char_range=26)\n",
"\n",
" def break_message(self, message):\n",
" \"\"\"Returning the trigram for an encoded message\"\"\"\n",
" self.enigma.cur_msg = message\n",
" while True:\n",
" (trigram, outcome) = self.enigma_fuzzer.run(self.enigma)\n",
" if outcome == self.enigma.PASS:\n",
" break\n",
" return trigram"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"How long does it take Bletchley park to find the key using this brute forcing approach?"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.286182Z",
"iopub.status.busy": "2025-10-26T18:02:45.285709Z",
"iopub.status.idle": "2025-10-26T18:02:45.288760Z",
"shell.execute_reply": "2025-10-26T18:02:45.288300Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"from Timer import Timer"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.297190Z",
"iopub.status.busy": "2025-10-26T18:02:45.296661Z",
"iopub.status.idle": "2025-10-26T18:02:45.431099Z",
"shell.execute_reply": "2025-10-26T18:02:45.425808Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"enigma = EnigmaMachine(k_book)\n",
"bletchley = BletchleyPark(enigma)\n",
"\n",
"with Timer() as t:\n",
" trigram = bletchley.break_message(\"BrEaK mE. L0Lzz\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Here's the key for the current message:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.441702Z",
"iopub.status.busy": "2025-10-26T18:02:45.441272Z",
"iopub.status.idle": "2025-10-26T18:02:45.455143Z",
"shell.execute_reply": "2025-10-26T18:02:45.450908Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'XQC'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"trigram"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"And no, this did not take long:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.463423Z",
"iopub.status.busy": "2025-10-26T18:02:45.462819Z",
"iopub.status.idle": "2025-10-26T18:02:45.476557Z",
"shell.execute_reply": "2025-10-26T18:02:45.471571Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'0.122877 seconds'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"'%f seconds' % t.elapsed_time()"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.487493Z",
"iopub.status.busy": "2025-10-26T18:02:45.486964Z",
"iopub.status.idle": "2025-10-26T18:02:45.514150Z",
"shell.execute_reply": "2025-10-26T18:02:45.508989Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'Bletchley cracks about 8 messages per second'"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"'Bletchley cracks about %d messages per second' % (1/t.elapsed_time())"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Turing's Observations\n",
"Okay, let's crack a few messages and count the number of times each trigram is observed."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.531276Z",
"iopub.status.busy": "2025-10-26T18:02:45.530533Z",
"iopub.status.idle": "2025-10-26T18:02:45.541185Z",
"shell.execute_reply": "2025-10-26T18:02:45.540799Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"from collections import defaultdict"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.563235Z",
"iopub.status.busy": "2025-10-26T18:02:45.562365Z",
"iopub.status.idle": "2025-10-26T18:02:45.588935Z",
"shell.execute_reply": "2025-10-26T18:02:45.576236Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"n = 100 # messages to crack"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:45.603974Z",
"iopub.status.busy": "2025-10-26T18:02:45.603259Z",
"iopub.status.idle": "2025-10-26T18:02:49.495827Z",
"shell.execute_reply": "2025-10-26T18:02:49.494852Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"observed: Dict[str, int] = defaultdict(int)\n",
"for msg in range(0, n):\n",
" trigram = bletchley.break_message(msg)\n",
" observed[trigram] += 1\n",
"\n",
"# list of trigrams that have been observed\n",
"counts = [k for k, v in observed.items() if int(v) > 0]\n",
"\n",
"t_trigrams = len(k_book)\n",
"o_trigrams = len(counts)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:49.499925Z",
"iopub.status.busy": "2025-10-26T18:02:49.499303Z",
"iopub.status.idle": "2025-10-26T18:02:49.508068Z",
"shell.execute_reply": "2025-10-26T18:02:49.507458Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'After cracking 100 messages, we observed 72 out of 17576 trigrams.'"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\"After cracking %d messages, we observed %d out of %d trigrams.\" % (\n",
" n, o_trigrams, t_trigrams)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:49.514204Z",
"iopub.status.busy": "2025-10-26T18:02:49.514004Z",
"iopub.status.idle": "2025-10-26T18:02:49.516694Z",
"shell.execute_reply": "2025-10-26T18:02:49.515891Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"singletons = len([k for k, v in observed.items() if int(v) == 1])"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:49.521622Z",
"iopub.status.busy": "2025-10-26T18:02:49.521391Z",
"iopub.status.idle": "2025-10-26T18:02:49.527032Z",
"shell.execute_reply": "2025-10-26T18:02:49.525948Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'From the 72 observed trigrams, 63 were observed only once.'"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\"From the %d observed trigrams, %d were observed only once.\" % (\n",
" o_trigrams, singletons)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Given a sample of previously used entries, Turing wanted to _estimate the likelihood_ that the current unknown entry was one that had been previously used, and further, to estimate the probability distribution over the previously used entries. This lead to the development of the estimators of the missing mass and estimates of the true probability mass of the set of items occuring in the sample. Good worked with Turing during the war and, with Turing’s permission, published the analysis of the bias of these estimators in 1953."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Suppose, after finding the keys for n=100 messages, we have observed the trigram \"ABC\" exactly $X_\\text{ABC}=10$ times. What is the probability $p_\\text{ABC}$ that \"ABC\" is the key for the next message? Empirically, we would estimate $\\hat p_\\text{ABC}=\\frac{X_\\text{ABC}}{n}=0.1$. We can derive the empirical estimates for all other trigrams that we have observed. However, it becomes quickly evident that the complete probability mass is distributed over the *observed* trigrams. This leaves no mass for *unobserved* trigrams, i.e., the probability of discovering a new trigram. This is called the missing probability mass or the discovery probability."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Turing and Good derived an estimate of the *discovery probability* $p_0$, i.e., the probability to discover an unobserved trigram, as the number $f_1$ of trigrams observed exactly once divided by the total number $n$ of messages cracked:\n",
"$$\n",
"p_0 = \\frac{f_1}{n}\n",
"$$\n",
"where $f_1$ is the number of singletons and $n$ is the number of cracked messages."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Let's explore this idea for a bit. We'll extend `BletchleyPark` to crack `n` messages and record the number of trigrams observed as the number of cracked messages increases."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:49.531262Z",
"iopub.status.busy": "2025-10-26T18:02:49.530762Z",
"iopub.status.idle": "2025-10-26T18:02:49.540626Z",
"shell.execute_reply": "2025-10-26T18:02:49.538211Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"class BletchleyPark(BletchleyPark):\n",
" def break_message(self, message):\n",
" \"\"\"Returning the trigram for an encoded message\"\"\"\n",
" # For the following experiment, we want to make it practical\n",
" # to break a large number of messages. So, we remove the\n",
" # loop and just return the trigram for a message.\n",
" #\n",
" # enigma.cur_msg = message\n",
" # while True:\n",
" # (trigram, outcome) = self.enigma_fuzzer.run(self.enigma)\n",
" # if outcome == self.enigma.PASS:\n",
" # break\n",
" trigram = enigma.internal_msg2key(message)\n",
" return trigram\n",
"\n",
" def break_n_messages(self, n):\n",
" \"\"\"Returns how often each trigram has been observed, \n",
" and #trigrams discovered for each message.\"\"\"\n",
" observed = defaultdict(int)\n",
" timeseries = [0] * n\n",
"\n",
" # Crack n messages and record #trigrams observed as #messages increases\n",
" cur_observed = 0\n",
" for cur_msg in range(0, n):\n",
" trigram = self.break_message(cur_msg)\n",
"\n",
" observed[trigram] += 1\n",
" if (observed[trigram] == 1):\n",
" cur_observed += 1\n",
" timeseries[cur_msg] = cur_observed\n",
"\n",
" return (observed, timeseries)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Let's crack 2000 messages and compute the GT-estimate."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:49.547425Z",
"iopub.status.busy": "2025-10-26T18:02:49.547264Z",
"iopub.status.idle": "2025-10-26T18:02:49.552780Z",
"shell.execute_reply": "2025-10-26T18:02:49.549560Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"n = 2000 # messages to crack"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:49.555324Z",
"iopub.status.busy": "2025-10-26T18:02:49.555214Z",
"iopub.status.idle": "2025-10-26T18:02:51.065533Z",
"shell.execute_reply": "2025-10-26T18:02:51.062529Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"bletchley = BletchleyPark(enigma)\n",
"(observed, timeseries) = bletchley.break_n_messages(n)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Let us determine the Good-Turing estimate of the probability that the next trigram has not been observed before:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:51.074671Z",
"iopub.status.busy": "2025-10-26T18:02:51.073913Z",
"iopub.status.idle": "2025-10-26T18:02:51.081982Z",
"shell.execute_reply": "2025-10-26T18:02:51.079790Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0.401"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"singletons = len([k for k, v in observed.items() if int(v) == 1])\n",
"gt = singletons / n\n",
"gt"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"We can verify the Good-Turing estimate empirically and compute the empirically determined probability that the next trigram has not been observed before. To do this, we repeat the following experiment `repeats=1000` times, reporting the average: If the next message is a new trigram, return 1, otherwise return 0. Note that here, we do not record the newly discovered trigrams as observed."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:51.088512Z",
"iopub.status.busy": "2025-10-26T18:02:51.088143Z",
"iopub.status.idle": "2025-10-26T18:02:51.094613Z",
"shell.execute_reply": "2025-10-26T18:02:51.093086Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"repeats = 1000 # experiment repetitions "
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:51.101350Z",
"iopub.status.busy": "2025-10-26T18:02:51.099827Z",
"iopub.status.idle": "2025-10-26T18:02:51.888420Z",
"shell.execute_reply": "2025-10-26T18:02:51.885599Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0.412"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"newly_discovered = 0\n",
"for cur_msg in range(n, n + repeats):\n",
" trigram = bletchley.break_message(cur_msg)\n",
" if(observed[trigram] == 0):\n",
" newly_discovered += 1\n",
"\n",
"newly_discovered / repeats"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Looks pretty accurate, huh? The difference between estimates is reasonably small, probably below 0.03. However, the Good-Turing estimate did not nearly require as much computational resources as the empirical estimate. Unlike the empirical estimate, the Good-Turing estimate can be computed during the campaign. Unlike the empirical estimate, the Good-Turing estimate requires no additional, redundant repetitions."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"In fact, the Good-Turing (GT) estimator often performs close to the best estimator for arbitrary distributions ([Try it here!](#Kenngruppenbuch)). Of course, the concept of *discovery* is not limited to trigrams. The GT estimator is also used in the study of natural languages to estimate the likelihood that we haven't ever heard or read the word we next encounter. The GT estimator is used in ecology to estimate the likelihood of discovering a new, unseen species in our quest to catalog all _species_ on earth. Later, we will see how it can be used to estimate the probability to discover a vulnerability when none has been observed, yet (i.e., residual risk)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Alan Turing was interested in the _complement_ $(1-GT)$ which gives the proportion of _all_ messages for which the Brits have already observed the trigram needed for decryption. For this reason, the complement is also called sample coverage. The *sample coverage* quantifies how much we know about decryption of all messages given the few messages we have already decrypted. "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"The probability that the next message can be decrypted with a previously discovered trigram is:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:51.896767Z",
"iopub.status.busy": "2025-10-26T18:02:51.896520Z",
"iopub.status.idle": "2025-10-26T18:02:51.910395Z",
"shell.execute_reply": "2025-10-26T18:02:51.908629Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0.599"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"1 - gt"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The *inverse* of the GT-estimate (1/GT) is a _maximum likelihood estimate_ of the expected number of messages that we can decrypt with previously observed trigrams before having to find a new trigram to decrypt the message. In our setting, the number of messages for which we can expect to reuse previous trigrams before having to discover a new trigram is:"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:51.913829Z",
"iopub.status.busy": "2025-10-26T18:02:51.913525Z",
"iopub.status.idle": "2025-10-26T18:02:51.918216Z",
"shell.execute_reply": "2025-10-26T18:02:51.917078Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"2.4937655860349124"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"1 / gt"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"But why is GT so accurate? Intuitively, despite a large sampling effort (i.e., cracking $n$ messages), there are still $f_1$ trigrams that have been observed only once. We could say that such \"singletons\" are very rare trigrams. Hence, the probability that the next messages is encoded with such a rare but observed trigram gives a good upper bound on the probability that the next message is encoded with an evidently much rarer, unobserved trigram. Since Turing's observation 80 years ago, an entire statistical theory has been developed around the hypothesis that rare, observed \"species\" are good predictors of unobserved species.\n",
"\n",
"Let's have a look at the distribution of rare trigrams."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:51.923335Z",
"iopub.status.busy": "2025-10-26T18:02:51.923171Z",
"iopub.status.idle": "2025-10-26T18:02:52.240761Z",
"shell.execute_reply": "2025-10-26T18:02:52.240235Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.244105Z",
"iopub.status.busy": "2025-10-26T18:02:52.243645Z",
"iopub.status.idle": "2025-10-26T18:02:52.251686Z",
"shell.execute_reply": "2025-10-26T18:02:52.250437Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt # type: ignore"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.256910Z",
"iopub.status.busy": "2025-10-26T18:02:52.255848Z",
"iopub.status.idle": "2025-10-26T18:02:52.429971Z",
"shell.execute_reply": "2025-10-26T18:02:52.427505Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"frequencies = [v for k, v in observed.items() if int(v) > 0]\n",
"frequencies.sort(reverse=True)\n",
"# Uncomment to see how often each discovered trigram has been observed\n",
"# print(frequencies)\n",
"\n",
"# frequency of rare trigrams\n",
"plt.figure(num=None, figsize=(12, 4), dpi=80, facecolor='w', edgecolor='k')\n",
"plt.subplot(1, 2, 1)\n",
"plt.hist(frequencies, range=[1, 21], bins=numpy.arange(1, 21) - 0.5) # type: ignore\n",
"plt.xticks(range(1, 21)) # type: ignore\n",
"plt.xlabel('# of occurrences (e.g., 1 represents singleton trigrams)')\n",
"plt.ylabel('Frequency of occurances')\n",
"plt.title('Figure 1. Frequency of Rare Trigrams')\n",
"\n",
"# trigram discovery over time\n",
"plt.subplot(1, 2, 2)\n",
"plt.plot(timeseries)\n",
"plt.xlabel('# of messages cracked')\n",
"plt.ylabel('# of trigrams discovered')\n",
"plt.title('Figure 2. Trigram Discovery Over Time');"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.435252Z",
"iopub.status.busy": "2025-10-26T18:02:52.434941Z",
"iopub.status.idle": "2025-10-26T18:02:52.440942Z",
"shell.execute_reply": "2025-10-26T18:02:52.440328Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"802 of 1009 trigrams (79.485%) have been observed 1 time (i.e., are singleton trigrams).\n",
" 1 of 1009 trigrams ( 0.001%) have been observed 152 times.\n"
]
}
],
"source": [
"# Statistics for most and least often observed trigrams\n",
"singletons = len([v for k, v in observed.items() if int(v) == 1])\n",
"total = len(frequencies)\n",
"\n",
"print(\"%3d of %3d trigrams (%.3f%%) have been observed 1 time (i.e., are singleton trigrams).\"\n",
" % (singletons, total, singletons * 100 / total))\n",
"\n",
"print(\"%3d of %3d trigrams ( %.3f%%) have been observed %d times.\"\n",
" % (1, total, 1 / total, frequencies[0]))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The *majority of trigrams* have been observed only once, as we can see in Figure 1 (left). In other words, the majority of observed trigrams are \"rare\" singletons. In Figure 2 (right), we can see that discovery is in full swing. The trajectory seems almost linear. However, since there is a finite number of trigrams (26^3 = 17,576) trigram discovery will slow down and eventually approach an asymptote (the total number of trigrams).\n",
"\n",
"### Boosting the Performance of BletchleyPark\n",
"Some trigrams have been observed very often. We call these \"abundant\" trigrams."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.442992Z",
"iopub.status.busy": "2025-10-26T18:02:52.442870Z",
"iopub.status.idle": "2025-10-26T18:02:52.454205Z",
"shell.execute_reply": "2025-10-26T18:02:52.451913Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Trigram : Frequency\n",
" TJK : 152\n",
" LBM : 69\n",
" NWV : 64\n",
" AZC : 43\n",
" GZP : 41\n",
" ADE : 37\n",
" DNO : 27\n",
" OQL : 26\n",
" TCO : 20\n",
" BDA : 19\n",
" ARO : 18\n",
" IPT : 16\n",
" FGK : 16\n",
" MSV : 15\n",
" ONO : 15\n",
" EOR : 13\n",
" JTV : 11\n",
" IBT : 11\n",
" PWN : 11\n"
]
}
],
"source": [
"print(\"Trigram : Frequency\")\n",
"for trigram in sorted(observed, key=observed.get, reverse=True): # type: ignore\n",
" if observed[trigram] > 10:\n",
" print(\" %s : %d\" % (trigram, observed[trigram]))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"We'll speed up the code breaking by _trying the abundant trigrams first_. \n",
"\n",
"First, we'll find out how many messages can be cracked by the existing brute forcing strategy at Bledgley park, given a maximum number of attempts. We'll also track the number of messages cracked over time (`timeseries`)."
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.460863Z",
"iopub.status.busy": "2025-10-26T18:02:52.459934Z",
"iopub.status.idle": "2025-10-26T18:02:52.473021Z",
"shell.execute_reply": "2025-10-26T18:02:52.471915Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"class BletchleyPark(BletchleyPark):\n",
" def __init__(self, enigma):\n",
" super().__init__(enigma)\n",
" self.cur_attempts = 0\n",
" self.cur_observed = 0\n",
" self.observed = defaultdict(int)\n",
" self.timeseries = [None] * max_attempts * 2\n",
"\n",
" def break_message(self, message):\n",
" \"\"\"Returns the trigram for an encoded message, and\n",
" track #trigrams observed as #attempts increases.\"\"\"\n",
" self.enigma.cur_msg = message\n",
" while True:\n",
" self.cur_attempts += 1 # NEW\n",
" (trigram, outcome) = self.enigma_fuzzer.run(self.enigma)\n",
" self.timeseries[self.cur_attempts] = self.cur_observed # NEW\n",
" if outcome == self.enigma.PASS: \n",
" break\n",
" return trigram\n",
"\n",
" def break_max_attempts(self, max_attempts):\n",
" \"\"\"Returns #messages successfully cracked after a given #attempts.\"\"\"\n",
" cur_msg = 0\n",
" n_messages = 0\n",
"\n",
" while True:\n",
" trigram = self.break_message(cur_msg)\n",
"\n",
" # stop when reaching max_attempts\n",
" if self.cur_attempts >= max_attempts:\n",
" break\n",
"\n",
" # update observed trigrams\n",
" n_messages += 1\n",
" self.observed[trigram] += 1\n",
" if (self.observed[trigram] == 1):\n",
" self.cur_observed += 1\n",
" self.timeseries[self.cur_attempts] = self.cur_observed\n",
" cur_msg += 1\n",
"\n",
" return n_messages"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"`original` is the number of messages cracked by the brute-forcing strategy, given 100k attempts. Can we beat this?"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.506004Z",
"iopub.status.busy": "2025-10-26T18:02:52.505359Z",
"iopub.status.idle": "2025-10-26T18:02:52.555412Z",
"shell.execute_reply": "2025-10-26T18:02:52.536931Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"max_attempts = 100000"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.574086Z",
"iopub.status.busy": "2025-10-26T18:02:52.573716Z",
"iopub.status.idle": "2025-10-26T18:02:52.818709Z",
"shell.execute_reply": "2025-10-26T18:02:52.817859Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bletchley = BletchleyPark(enigma)\n",
"original = bletchley.break_max_attempts(max_attempts)\n",
"original"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Now, we'll create a boosting strategy by trying trigrams first that we have previously observed most often."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.823290Z",
"iopub.status.busy": "2025-10-26T18:02:52.823136Z",
"iopub.status.idle": "2025-10-26T18:02:52.836681Z",
"shell.execute_reply": "2025-10-26T18:02:52.833949Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"class BoostedBletchleyPark(BletchleyPark):\n",
" def __init__(self, enigma, prior):\n",
" super().__init__(enigma)\n",
" self.prior = prior\n",
"\n",
" def break_message(self, message):\n",
" \"\"\"Returns the trigram for an encoded message, and\n",
" track #trigrams observed as #attempts increases.\"\"\"\n",
" self.enigma.cur_msg = message\n",
"\n",
" # boost cracking by trying observed trigrams first\n",
" for trigram in sorted(self.prior, key=self.prior.get, reverse=True):\n",
" self.cur_attempts += 1\n",
" (_, outcome) = self.enigma.run(trigram)\n",
" self.timeseries[self.cur_attempts] = self.cur_observed\n",
" if outcome == self.enigma.PASS:\n",
" return trigram\n",
"\n",
" # else fall back to normal cracking\n",
" return super().break_message(message)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"`boosted` is the number of messages cracked by the boosted strategy."
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:52.870164Z",
"iopub.status.busy": "2025-10-26T18:02:52.869577Z",
"iopub.status.idle": "2025-10-26T18:02:53.108558Z",
"shell.execute_reply": "2025-10-26T18:02:53.106070Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"23"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"boostedBletchley = BoostedBletchleyPark(enigma, prior=observed)\n",
"boosted = boostedBletchley.break_max_attempts(max_attempts)\n",
"boosted"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We see that the boosted technique cracks substantially more messages. It is worthwhile to record how often each trigram is being used as key and try them in the order of their occurrence.\n",
"\n",
"***Try it***. *For practical reasons, we use a large number of previous observations as prior (`boostedBletchley.prior = observed`). You can try to change the code such that the strategy uses the trigram frequencies (`self.observed`) observed **during** the campaign itself to boost the campaign. You will need to increase `max_attempts` and wait for a long while.*"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Let's compare the number of trigrams discovered over time."
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.119446Z",
"iopub.status.busy": "2025-10-26T18:02:53.119076Z",
"iopub.status.idle": "2025-10-26T18:02:53.499702Z",
"shell.execute_reply": "2025-10-26T18:02:53.499106Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHHCAYAAABXx+fLAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYc1JREFUeJzt3Qd4FNXXBvADJIQeeg+99yJViggIiEhTEFGq+ImCKIKACgFRQYqCgjQFLHSkKFJEpEnvSBWQ3nuvYb7nPTj7300jm2yZ3X1/z7MkOzs7e3eyZE7OPffeRIZhGEJEREQUQBJ7uwFEREREnsYAiIiIiAIOAyAiIiIKOAyAiIiIKOAwACIiIqKAwwCIiIiIAg4DICIiIgo4DICIiIgo4DAAIiIiooDDAIjIxZ566im9BboVK1ZIokSJ9CsFrv79++vngMhqGAARRYJf1nG5BdKF/ciRIw7vPTg4WDJmzChVq1aVDz74QI4dO+btJvqFNWvWSNOmTSVLliwSEhIiefLkkf/7v/+z3PlFu+Lyf2Ty5MnebipRjBJxLTAiRz/99JPD/R9++EGWLl0qP/74o8P2unXr6oUqsnv37unXpEmTij8FQHnz5pVWrVrJs88+Kw8fPpTLly/Lpk2bZM6cOXqx++677+Sll16yPQf74FzgPCROzL+1Hufrr7+Wbt26Sb58+aRdu3aSLVs22bt3r3z77bf6+MKFCzXgtIJ58+bJjRs3bPfRtmnTpsmXX36pgbEJ7c2VK5c8ePBAkiVL5qXWEkWPARDRY3Tp0kVGjx4tj/uvcuvWLUmRIoXLX99dx41PADR06FDp0aOHw2NHjx6VZ555RvfZuHGjlC5dWgLJzZs3JWXKlAnO/NSoUUOefPJJWbx4scPP+9ChQ7odQeTu3bslXbp0YrX3NmzYMOnZs6ccPnxYs0NEvoB/lhHFA2p8SpQoIVu2bNELFy5Y6AqKqQYIQcLzzz+vF5PMmTPLu+++K0uWLInSlRbbcefPny8NGzaU7Nmza/dI/vz5ZeDAgRIRERFt23bu3Ck1a9bUYxQoUEBmz56tj69cuVIqVaokyZMnl8KFC8sff/yRoHORO3du7epAtmfIkCGx1gAdOHBAmjdvLlmzZtWMQM6cOTVrdPXq1ShZuIoVK2rbccHHufj9998d9vnmm2+kePHiei5wTt566y25cuWKQ+CaKlUqDSAjQyYLbbA/d4sWLZLq1avrzyh16tR6rhFw2ENmBsdEUIJMGPZr3bq1hIeHa7fg+fPno7zW66+/LmnTppU7d+7EeA7xc8S5+v7776MEu/g547yePn1axo0bZws4sD8+V5H16dNHs27I0Jk2bNgg9evXl9DQUD0+PhcIuqKr1dmzZ4+8/PLLet6rVasm7qgBwn38fGbNmiXFihXTz2KVKlXk77//1sfxPvGZxWcEn2cE15HF5T0RxYYBEFE8Xbx4URo0aCBlypSRESNGSK1atWL8K/rpp5/WQOPtt9+WDz/8UNauXSu9evVy6rgIMnDx7d69u4wcOVLKly8v/fr1k969e0c5Bi5+zz33nAY6uHgiSECgMWPGDP2Ki/fgwYO1bS+88IJcv349QecCFy9cqNFVGBMESPXq1ZP169dL165dNauG4ODff/91CFwGDBggr776qgYUH3/8sd4PCwuTP//80+GiioAHgc/w4cM1qMJFE5mo+/fv6z4tW7bU9/fbb785tAMB0a+//qrvO0mSJLoN3ZsIeHB+P//8c+nbt68GAggAIl980Z2D94FAFoEIXhvtxXac38jvGYEn9ompCwjtWbZsmQZfyLJFB+8FP8MFCxbo/RYtWmgQMXPmzCj7YhvOg5kpwnlDAHnt2jUN1D777DM93/hMImMX2Ysvvqhtwn6dOnUSd1m9erW899570rZtW/15orsPn1l8Lr766it58803Nau0bt066dChg8NznX1PRNFCFxgRxeytt95C35fDtpo1a+q2sWPHRtkfj+FmGj58uO47b94827bbt28bRYoU0e3Lly+P03Fv3boVZdv//d//GSlSpDDu3LkT5RhTp061bdu3b59uS5w4sbF+/Xrb9iVLluj2SZMmxXoODh8+rPsNHTo0xn0aN26s+1y9elXv433Zv79t27bp/VmzZsV4jAMHDmgbmzZtakRERDg89vDhQ/167tw5I2nSpMYzzzzjsM+oUaP0+BMnTrTtnyNHDqN58+YOx5k5c6but2rVKr1//fp1I23atEanTp0c9jtz5owRGhrqsL1t27b63N69e0dpe5UqVYxKlSo5bJszZ06Un3Fk27dv1326detmxKZUqVJG+vTpHV6vfPnyDvts3LhRj/XDDz/YzkHBggWNevXq2c6f+VnKmzevUbduXdu28PBwfW6rVq0MZ+FzgeficxKZeVx7uB8SEuKw/7hx43R71qxZjWvXrtm29+nTx+HYzrwnotgwA0QUT/iLvH379o/dDzUdOXLk0C4wE7IBMf11HdNx0U1gQsbmwoULmjXAX+v79u1z2BeZDPuCZHR1oRumaNGimhUymd8jC5NQeE2zbdFBVwWg6y+6bimzuBbF08hsRS6cNrtRkElDZuWdd95x2AfnM02aNLaMD/ZHNgMFuvYFu8jS4Odhdu8ga4XsAbrFcE7NG7JDOD/Lly+P0s7OnTtH2damTRvtlkH3mGnKlCmavUL3TEzM84XutNjgcWQ87LNC6Cq1fz28N3x+GjdurPe3b9+u3Y7o0kJm0XxvyIzVrl1bVq1apefb3htvvCGegNe3rxcyP4vIltmfi8if0fi8J6LoMAAiiidcROMy0gt1GugeilwHgRoHZ46LehQMkUYggQt9pkyZ5JVXXtHHItfQoLYm8uvhebgYR94G9vUi8WUGGTFdyNG9g+47jGrCSCF0I6G7w77tuJgjqEFdSEzMuhcEdfZwzjCCyr4uBkHC7du35ZdffrG1EQERAiPz/OBiCug+wTm1v6Hu6Ny5cw6vExQUpOc3pm4qBD2A94UuK9QIxTYPjnm+HtcNicftzy3eA86V2e2GxApqatB9is+H/XtDN1Pk94afw927d6N8dmLqhnM1jA6L7rP4uM9ofN4TUXSCot1KRI9ln5Fx93GRoUAWARc21MUgoEIWaevWrVpLFPkvXrO2JbKYtrtiMOiuXbu0Lsa8+EYH9TooJEZBN4IL1EQNGjRI64KiCyoSqnLlypplQF0MMgao/UFAhGDFZJ471AGhMDoyBDz2EOREN6wfNTeoYUEAhAwWan9wMTaD1JggEMZroGg9JjjO/v375YknnrBtQ/0TMoB4byiUxznEfEGoYYr83jB6DzVlsWXu3P25jiy+n9H4vCei6DAAInIzjJJCQS1+gdtnAg4ePBjnY2AkFdL9mHMHxZ8mDDu2AhSqInvzuIs9lCxZUm8fffSRFoNjiPfYsWPlk08+0cAOFzicr5gubjifgIAAGR8TusVwPurUqeOwPwqGUTSO7iNkSxAQITAy4TUBwVvk5zoL3WDofsL8SAiEypYtqyPVYoNRZyh0R2Evslfm+7OHIAdBEAIsewjkUCyMc4H3htFQjRo1ivLeEJQm9L1ZhT++J/IOdoERuRm6ek6ePGnrhgEMiZ4wYUKcj2H+VWyfqcEFH0PBvQ0XbWR10AWFUTsxQQCCkVL2EAghm4KLOzRp0kTvI8sVOatlvndc9PBaGClkfz4wESO6PjCaK3KQgONjiDnqsRAQRf754GKKkUTmCDJ70Q1tjwm6n9C9hywMphuIS0AICAbxXnAekaGyh6Du/fff14kRMSu0PdTL4LOBSQjR/YUAyX7eHowURMCA0Wr2dVDxeW9W4Y/vibyDGSAiN8NFa9SoUVpki5l+cSFDdsAcFh2XdZIwoy66WFD3gG4jPAddNp6exxRdbpijB8EJuuWQ6fj5559t7SlVqlSMz0WGA3O/oHalUKFCGgzhObiA40JudgdhmgDMi4PunWbNmmmXE14HXT7oLkOtB+a6wfB4zAOD4nJkQBAMVqhQIUrQUa5cOdtxEQjZd38Bgp8xY8boUHbsi+JxvAa6k1BQjQwVfn5xgaH7eD72x/vCzzwukNXDBR01UjiH5kzQKG5HoIzzjdqlyJMgImuF7NEXX3yhNUKR3xuCSdTFIDBDJgrF9agxQ0CO4m68d3QL+hJ/fE/kJbGOESOiGIfBFy9ePNr9Iw+Dh3///ddo2LChkTx5ciNTpkzGe++9Z/z88896XPth6bEdd82aNUblypX1GNmzZzfef/992zD2yEPpoztG7ty5tQ2R4fl4j3EZBm/egoKCdEg2hn1jmPLRo0ejPCfyMHicgw4dOhj58+c3kiVLps+vVauW8ccff0R5Loayly1bVodKp0uXTt/T0qVLHfbBsHdMJRAcHGxkyZLF6Ny5s3H58uVo2//hhx9qWwoUKBDje0Q7MbQaQ9/RPrSzXbt2xubNmx2GwadMmTLWc2UORccwfWdhaD6mE8iYMaO+r1y5cukw/CNHjsT4nAkTJujrpU6dWqdXiA6mIGjWrJmRIUMGPaf4LLRo0cJYtmxZlOHq58+f98gw+MifuZimWjA/R5GnT4jLeyKKDZfCIPISTHKIGaFPnDihf8GSf9ixY4fWL2ENOWSViMiaGAAReQDqOuxH16AGCAWyWIrhn3/+8WrbyLXQzYd6ozNnziR4jTAich/WABF5AGpZMO8JMgMo1EUdDeo7zDljyPeh7gSj18aPH69BEIMfImtjBojIQ91dKNzEulLI+mCiP4zsiVy0Sr4Lw+vPnj2ro8pQ3P24mZ2JyLsYABEREVHA4TxAREREFHAYABEREVHAYRF0NDDp2KlTp7QPPy6T1BEREZH3oaoHk4Ji4tTo1uyzxwAoGgh+Iq9ITERERL7h+PHjj11gmQFQNMzRGziBsa1sTURERNaBNQeRwIjLKEwGQNEwu70Q/DAAIiIi8i1xKV9hETQREREFHAZAREREFHAYABEREVHAYQ1QAmBJg/v373u7GURukTRp0scOIyUi8lUMgOI5zwBWer5y5Yq3m0LkNgh+8ubNq4EQEZG/YQAUD2bwkzlzZkmRIgUnSyS/nQz09OnTuoo9P+NE5G8YAMWj28sMfjJkyODt5hC5TaZMmTQIevDggQQHB3u7OURELsUOfieZNT/I/BD5M7PrC0E/EZG/YQAUT+wSIH/HzzgR+TMGQERERBRwvBoADRo0SCpUqKBrdqCmpkmTJrJ//36Hfe7cuSNvvfWW1tukSpVKmjdvLmfPnn3sKK1+/fpJtmzZJHny5FKnTh05cOCAm98NxVf//v0lS5YsmnGYN2+et5tDREQBwKsB0MqVKzW4Wb9+vSxdulTra5555hm5efOmbZ93331Xfv31V5k1a5buj6LMZs2axXrcIUOGyFdffSVjx46VDRs2SMqUKaVevXoaTAWqdu3aaYBh3hBQ1q9fX3bu3Omy4yOAddbevXtlwIABMm7cOB1x1KBBA7ESfOaefvppSZ8+vdZ9FSxYUNq2bSv37t3TxydPnixp06Z1aTBYpkwZlx2PiIgsOAps8eLFDvdxMUEmaMuWLVKjRg25evWqfPfddzJ16lS9CMGkSZOkaNGiGjRVrlw52uzPiBEj5KOPPpLGjRvrth9++EEzDMguvPTSSxKoEPDg/JlD+XGOnnvuOTl27FiMz0FQ6s4RQIcOHdKv+FklpObEHe3cs2ePnrOuXbtqQI1sIjKJP//8s9OFwQiYOJ8OUTxdOy3ykJPOul1IGpHkrvuDzuosNQweAQ/gr21AIIQLG7qwTEWKFNF5SdatWxdtAHT48GG9uNs/JzQ0VCpVqqTPiS4Aunv3rt5M165dE38UEhIiWbNm1e/xtXfv3lK9enU5f/68Dnk+cuSITnw3ffp0+eabbzR7hiwatiN43L59u+1YCDJxw2PIWnz//fe63Qxili9fLk899ZQcP35c3nvvPfn99991Yj283siRIyVPnjz6PGR/wJxxGAEs5qD55JNPZPz48do2BLyDBw/WYARiaieyUBMnTpThw4fLwYMH9XOELtNRo0bp8zB9QY8ePWT+/Pn6837iiSfkyy+/lNKlS0d7vtBmnCdkFE358+e3tWPFihXSvn17h/cdHh6u7wvvr2PHjhow4dwha4kAv1evXjJ37lw5ceKEHrt169baXYvgDY+b58M8HgJWvK+4tB3nDIHa7du3pWXLlpIxY0b9IwM/t1WrVknt2rX152F+BuCdd97R/2erV69O8OeLyC3+/ERk1VBvtyIwVO8hUruvBArLBEC46OGX8ZNPPiklSpTQbQhk8Fdz5C4GZHPwWHTM7dgnrs9BLZJ54YkPXLRv3/f8UOHkwUninTW5ceOG/PTTT1KgQIEo8xkhMEIQUbZsWUmWLJl2T8UGF2Z0ZSFwNDNMCD4QvKLrsUqVKnqBDQoK0ou02fWG5yFQQBCB7i8TAiS8Pl4XbUBQ8/zzz8vu3bu1Cyqmdo4ZM0a6d++uwRK60hBQr1mzxrb/iy++qFmcRYsWaVCM4yMo+Oeff2xBtz0ECmgXggdkJCOrWrWqBoEIYMzaNdSpmYYNG6aPISgyod4NgU727Nnl77//lk6dOum2999/X4OWXbt2adDyxx9/6P5oZ1zaPmXKFPn00081IMT/IQSHODcIFAHtz5cvn/z444/Ss2dP3YafD55nH+ARWc7JLY++Jg56dCP3SRxY59cy7xa1QPjl/9dff3n8tfv06aMXThMu5GFhYXF+PoKfYv2WiKft+biepEga9x/hggULbBdo1FmhSBzbIq/3hED0cXVW9nBMXJyRmbDPLiDAQmD77bffOmQ0ENAie4J6LzO4tX8eAgdkSsxs3eeff64ZJQQbo0ePjrGdCK6QberWrZttG4rsAZ+rjRs3yrlz5zQTZr4OsjOzZ8+W119/Pcr7QtCxZMkSqVmzprYPGUcEHW3atJE0adJocI5gBO/Nvv0mdNuiPfbQ7WhC8IcgEMEKAiCcQ5xLBIr2x4tL27/++mvNOJkZKQReyGAh0DXhcZx/MwBCbR3q4lq0aBHrz5fIqwzj0dfG34iUbunt1pAfscQw+C5duuiFGBe5nDlz2rbjIoDaichrbmEUWHQXHPM55j5xfQ4uKrig2d/8Ua1atbQ7BDdcUJGdQabk6NGjDvuhe8UVduzYoV1RyHDgwo4bshW46Jq1P5Eh+EShO7IY9nAfWaaY2ongAM9DgBJTWxAMmKMJzRu6TGNqS5IkSTRgQHcVsiQ5cuSQzz77TIoXL+6QsYpJdOdxxowZ+l7wWcTrIyCKrQYrrm1HBqpixYoOz4t8H11p+Hmgfg6QiULwg0ECRESBxqsZIHQdocAUNRHICJjpelP58uW1NmLZsmVay2H+oscFA90q0cExcHHBc8zRNLiook6kc+fObuuKQjbG0/C6zsCFDl1eJmRmkMGYMGGCZk/s97OHDBF+VtHNiB0bXLTxM0Q3S2SoOUoo+3Yie/K4tiDjhc9ZZI8bxYXA59VXX9XbwIEDpVChQlpz9Lhu08jnETVoqPnB8xB84tybXVXuars9DDBo1KiRBnX4f4LutOiOSWQt//3u4cSc5E8BELq9MMILhZ3IEpg1Orgw4IKGr0jbo3sKmQNkZhAwIfixL4BGYTTqeJo2bardEegawQUd9SL4Rd+3b1+tuYjPMO24wGs60xVlFWg3ghsUzcYGwQp+NgiCzK4s+4JoQHdQ5JFR5cqV04wHLrxxzaphP/ysULuDricT7kfOaNjD5wddSgh8kemKDG3Be0D3EvaLr3Tp0mkwYk7VEN37jsnatWsld+7c8uGHH9q2Rc6+xXQeH9f2woULy6ZNm7R7zoT7kb322mvSqlUrzbSioDtypo3IciL98UXkF11gKFpFoSpGC+GiYt5w0TRhpAuGaiMDhEJOZHfmzJnjcBxkhcwRZIB6CgRKqI1ADQj+gkZhKQplAxlqdHAhxQ3dSThHODfICsQGPx+MxkI3ELpcUIeD7IE9XJhR2IyfxYULFzRDhGwHRiJhiDuKoNFlg4zD22+/rd1KMUGNCup+8DnA8VDsjIDLvrYnOhh9hWwKRkJh9NXWrVu1NgYwKhCBM4Jg1MZgJBkCEgQjmzdvjvZ4KDRG1hD7432jCBu1SfhqnjO8b5xDBF5437du3YqxfQjIkb1E1gfHQzuR/Yx8HnGe8H5xPPzM4tJ2/CwxZQRG4+G94w8A/DwiF8kj84QgE4+b9UJEvoEZIHIxg6K4evUq/uTQr5Hdvn3b2LNnj371JW3bttX3ZN5Sp05tVKhQwZg9e7Ztn8OHD+tj27Zti/L8MWPGGGFhYUbKlCmNNm3aGJ9++qmRO3du2+Pnzp0z6tata6RKlUqPsXz5ct1++vRp3T9jxoxGSEiIkS9fPqNTp062czt37lzd315ERITRv39/I0eOHEZwcLBRunRpY9GiRXFq59ixY43ChQvr87Jly2Z07drV9ti1a9f0fvbs2fVxvJ/WrVsbx44di/acbd261XjllVeMvHnzatszZMhg1KhRw/jll18c9nvjjTf0MbQpPDxct+HcfPnll1GO2bNnT90X56lly5a6T2hoqO3xO3fuGM2bNzfSpk2rx5s0aVKc2/7xxx/recaxO3ToYLz99ttG5cqVo7Shb9++RpIkSYxTp04ZsfHVzzr5mcnPGUZ4GsPYOcvbLSEfv35Hlgj/uDqo8nWoGUL3G7JKkbtuUMCLv9DRtRboGSWytrp162rGFEPf7aFbGRm9X375Jdbn87NOlvB9I5HDq0SafydS8gVvt4Z8+Podme8VrhBRFOh6Q2E2urgwem3atGk6lxCWmDHhFwLmHkLd3eOCHyLL4N/o5CYMgIj8AGp9Fi5cqJMhInODomgs2WE/IzpqsTD9wRtvvKHZISKfwlFg5GIMgIj8AEZNmrNHx4RD3omILDYRIhERUexdYMwAkWsxACIiIgtjDRC5BwMgIiKyPtYAkYsxACIiIutiFxi5CQMgIiIiCjgMgIiIyMK4GCq5BwMg8um5b+bNm+ftZhCRO7ELjNyEAVCAaNeunQYM5i1DhgxSv359XTDTX4MWLPeAxUxz5colISEhuiwEZkrGyvLuaA8WKcXxsJApERFZGwOgAIKA5/Tp03rD6uVBQUHy3HPPib9q3ry5bNu2TVdI/+eff3T5B6xsf/HiRaeOc+/ePbe1kYgeh11g5B4MgAKImQXBrUyZMtK7d285fvy4ZkpMWCvq6aef1pmFkSV6/fXX5caNG7bHHz58KB9//LHkzJlTj4fjLF682CFY6NKli2TLlk0X0MydO7cMGjRIH8uTJ49+bdq0qWZKzPswf/58KVeunD4nX758MmDAAHnw4IHt8QMHDkiNGjX08WLFijmscRWdK1euyOrVq+Xzzz+XWrVqaTsqVqwoffr0keeffz7W9vTv31/f17fffuuwECjeZ7Vq1SRt2rR6bhA8Hjp0yPaa2BfKli2rx0OwZcKxihYtqscqUqSIfPPNNw7tXbt2rb4mHn/iiSc0K2Vmk7BecYECBWTYsGEOz8Fj2OfgwYOxngsiIoqKS2G4qo/6/i3Pv25winj/VYSg5qefftILKy7mcPPmTe0iqlKlimzatEnOnTsnr732mgY0kydP1n1Gjhwpw4cPl3HjxumFfuLEiRpQ7N69WwoWLChfffWVZlpmzpypXU8IsHADHDNz5swyadIkzUZh0U5AoNKmTRt9bvXq1TWoQOAF4eHhGnQ1a9ZMsmTJIhs2bNBFPd95551Y31+qVKn0hkCicuXKGqxFFlN7AEEF1tKaM2eObTvOT/fu3aVUqVJ6/vr166fBEwKRxIkT6zpbCLKwJEXx4sUladKk+rwpU6bovqNGjdJzhqxUp06dJGXKlNK2bVtdvbhRo0by7LPP6kKlR48edXh/CHI6dOig7ezRo4dtO+4jKMTPkMhvsQaI3MWgKK5evYr/cfo1stu3bxt79uzRrzZ3bxhGeBrP3/C6cdS2bVsjSZIkRsqUKfWG95ctWzZjy5Yttn3Gjx9vpEuXzrhx43/H/e2334zEiRMbZ86c0fvZs2c3Pv30U4djV6hQwXjzzTf1+65duxpPP/208fDhw2jbgdedO3euw7batWsbn332mcO2H3/8UdsHS5YsMYKCgoyTJ0/aHl+0aFG0x7I3e/ZsfT/JkiUzqlatavTp08fYsWPHY9sTHh5uBAcHG+fOnTNic/78eX3+33//rfcPHz6s97dt2+awX/78+Y2pU6c6bBs4cKBRpUoV/X7MmDFGhgwZHD5TEyZMcDgW3jt+fhs2bND79+7dMzJmzGhMnjzZcJdoP+tEnjah9qPfd3sXeLsl5OPX78jYBRZA0BWEbAVuyFYg29OgQQPNOMDevXuldOnSmpkwPfnkk5qB2b9/v2YqTp06pdvs4T6eaxZb4/hYjfztt9+W33///bHt2rFjh3armVkb3JAhQa3SrVu39NhhYWGSPXt223OQpYpLDRDai4wUMjxYDBTdbGY2KzboMsuUKZPDNnTDtWrVSrvo0qRJY+syO3bsWIzHQdYIGa2OHTs6vL9PPvnE1n2Gc4usktnVBsgk2cN7b9iwoWbc4Ndff5W7d+/Kiy+++Nj3QkREUbELzFVdUR+c8s7rOgGBjX13CepSQkNDZcKECXpBdgUEGIcPH5ZFixZpV1CLFi2kTp06Mnv27Bifg+4k1Pygmysy+6AgPvD8unXr6q1v377apYduNQRqsbEPAk3opkJghPOFgASBYYkSJWItkjbrp/CcSpUqOTxm3+UWF2j7q6++Kl9++aV2f7Vs2VJSpHDuM0Dkc9gFRm7CAMgVUIeTNOoF0+pQW4Laldu3b+t9FOkiO4KshRkAYMg49kFGB1kPXPixrWbNmrbj4L59xgL74eKM2wsvvKDZl0uXLkn69OklODhYIiIiogRNyILEVMuCdqGOCBkhFFfD+vXr4/WeUUBtP+w9uvZEByPH0EYEMqhTgr/++sthH7Pmx/54qFvCOfv333+ldevW0R4b5xb1WMjomLVKqE+KDDVC+LmMGTNGC7JXrVoV5/dN5Ls4CozcgwFQAMEF9syZM/r95cuXtSgXGQpkNgAXaGRHUJiLkVAYHda1a1fNOuBCDj179tR98ufPr6OWkIlAlxcKfeGLL77QIAXFvgicZs2apaPOMHIK0G2EIfjoNsPFPl26dFogjBFVKJpGwITnoVts165dmplCBqlQoULarqFDh2pX3IcffvjYgAXdQygeRvdS6tSpZfPmzTJkyBBp3Lixbb/o2hMdbEex+Pjx4/X9odsLo+jsoaAao+cQnGCUHLJPyLAhu4XuQHyPYBA/B7QFPwMUVb/88sv6flD4jWPi2OaILwSp9hkjZK4wkg0F53HpBiQiohh4pCrJ34ugfQCKoP/7U0pvqVOn1uJlFArb27lzp1GrVi0tHE6fPr3RqVMn4/r167bHIyIijP79+xs5cuTQQuHSpUtrQbJ9IXWZMmW00DpNmjRa4Lx161bb47/88otRoEABLWrOnTu3bfvixYu1UDl58uT6vIoVK+qxTPv37zeqVatmJE2a1ChUqJDuH1sR9J07d4zevXsb5cqVM0JDQ40UKVIYhQsXNj766CPj1q1bsbYHRdB4X5EtXbrUKFq0qBESEmKUKlXKWLFiRZQ2oHg5LCxMC8dr1qxp2z5lyhQ9L2g/CrNr1KhhzJkzx/b4mjVr9Jh4vHz58lo0jWPv27fPoQ2HDh3S7UOGDDHczVc/6+Rnxj31qAh63/9+zxC5ogg6Ef6JKTgKVMgw4K91DLdGd469O3fuaI2L/fwwRK6GjFr79u31M4iskglTBtSuXVu7BM2snLvws06WML6WyKmtIq1miBSu7+3WkA9fvyNjFxiRBfzwww86uixHjhza/derVy8tIDeDH3SboUsSXZPo2nN38ENkHawBIvfgMHgiC0Bt1iuvvKIF3++++64GOag3Mk2bNk1HoGGGa9QxEQUMjgIjN2EGiMgC3n//fb3FBMXPjxu6T0REcccMEBERWRi7wMg9GADFE2vHyd/xM07WwgCIXIsBkJMwcR5giQYif2bOcO3sjNVELsVAnNyENUBOwsUAk/phpXTAUgT2k9UR+QMs84FRZ/h8BwXx1wRZoQvM2+0gf8PfbPGAmY3BDIKI/BFm5Mbs3AzwyRr4OSTXYgAUD7ggYDkELH1w//59bzeHyC2wthmCICKvYg8Y+WMAhMUcsbbTli1bdKHLuXPnSpMmTWyPx/SXJ+ZBwZpU0cFEcVh7KfJik/v27XNLdxjrI4iI3ImjwMg9vPrnHVYdL126tIwePTraxxEU2d8mTpyoQVHz5s1jPW7x4sUdnhd51W4iIiIKbF7NADVo0EBvj6u1Mc2fP19q1aqlSwbEBkWbkZ9LREQ+iDNBk5v4TAf/2bNn5bfffpOOHTs+dt8DBw5I9uzZNVBq3bq1HDt2LNb9sc4SFlCzvxERkYWwC4wCNQD6/vvvJXXq1NKsWbNY96tUqZJMnjxZFi9eLGPGjNHVrKtXry7Xr1+P8TmDBg3S1WPNW1hYmBveAREROY9V0BTgARDqf5DNSZYsWaz7oUsNC0mWKlVK6tWrJwsXLtQFJGfOnBnjc/r06SNXr1613Y4fP+6Gd0BERE5jFxgF8jD41atXy/79+2XGjBlOPxeTFhYqVEgOHjwY4z4hISF6IyIii2IXGAViBui7776T8uXL64gxZ924cUMOHTqk8/YQEZGvYRcY+WEAhOBk+/btegPU6+B7+6JlFCTPmjVLXnvttWiPUbt2bRk1apTtfo8ePWTlypVy5MgRWbt2rTRt2lTn6mnVqpUH3hEREbkHM0DkR11gmzdv1mHtpu7du+vXtm3baiEzTJ8+XVeljimAQXbnwoULtvsnTpzQfS9evCiZMmWSatWqyfr16/V7IiLyMVwMldwkkYHoghwg64TRYCiITpMmjbebQ0QUuEZVELnwj0i730TyVPN2a8iPrt8+UQNEREQBCsGPYhcYuRYDICIisqabF//3farM3mwJ+SEGQEREZE0R9/73fcaC3mwJ+SEGQEREZPGV4JN4uyHkhxgAERGRNZljdDgJIrkBAyAiIrIoLoNB7sMAiIiIrIkZIHIjBkBERGRxDIDI9RgAERGRRTEDRO7DAIiIiKzJtlABAyByPQZARERkUcwAkfswACIiImviUpXkRgyAiIjIotgFRu7DAIiIiKyJw+DJjRgAERGRxTEAItdjAERERNbEDBC5EQMgIiKyOAZA5HoMgIiIyKLMDJC320H+iAEQERFZEydCJDdiAERERBbFGiByHwZARERkTcwAkRsxACIiIotiBojchwEQERFZEzNA5EYMgIiIyKK4Fhi5DwMgIiKyJk6ESG7EAIiIiCyOARC5HgMgIiKyKGaAyH0YABERkTWxCJrciAEQERFZFDNA5D4MgIiIyJqYASI3YgBEREQWxQwQ+WkAtGrVKmnUqJFkz55dEiVKJPPmzXN4vF27drrd/la/fv3HHnf06NGSJ08eSZYsmVSqVEk2btzoxndBRERuwQwQ+WsAdPPmTSldurQGLDFBwHP69Gnbbdq0abEec8aMGdK9e3cJDw+XrVu36vHr1asn586dc8M7ICIi92EGiNwnSLyoQYMGeotNSEiIZM2aNc7H/OKLL6RTp07Svn17vT927Fj57bffZOLEidK7d+8Et5mIiDyU/blx/r87DIAoAGuAVqxYIZkzZ5bChQtL586d5eLFizHue+/ePdmyZYvUqVPHti1x4sR6f926dTE+7+7du3Lt2jWHGxERedGcTiLTWj76nvEPeSsD1KxZszgfcM6cOeIq6P7Ca+fNm1cOHTokH3zwgWaMEMwkSZIkyv4XLlyQiIgIyZIli8N23N+3b1+MrzNo0CAZMGCAy9pNREQJdHLLo69JQkSKx/0aROTSACg0NNT2vWEYMnfuXN32xBNP6DZkXa5cueJUoBQXL730ku37kiVLSqlSpSR//vyaFapdu7bLXqdPnz5aN2RCBigsLMxlxyciongWQLdbIBJW0dutoUANgCZNmmT7vlevXtKiRQutrTGzMMi6vPnmm5ImTRr3tVRE8uXLJxkzZpSDBw9GGwDhMbTp7NmzDttxP7Y6ItQZ4UZERFbBleDJYjVAKCbu0aOHQxcUvkcGBY+504kTJ7QGKFu2bNE+njRpUilfvrwsW7bMtu3hw4d6v0qVKm5tGxERuRCHwJPVAqAHDx5EW0+DbQg2nHHjxg3Zvn273uDw4cP6/bFjx/Sxnj17yvr16+XIkSMaxDRu3FgKFCigw9pNyASNGjXKdh+B2IQJE+T777+XvXv3auE0htubo8KIiMgXcAg8WWwYPAKJjh07alFyxYqP+mU3bNgggwcPdjrI2Lx5s9SqVct236zDadu2rYwZM0Z27typgQzqizBZ4jPPPCMDBw506K5CO1D8bGrZsqWcP39e+vXrJ2fOnJEyZcrI4sWLoxRGExGRL/SAMQAi90hkoKrZCcjyDBs2TEaOHKkTEwK6pLp16ybvvfdetKOzfA2KoFHkffXqVbfXNRERUTS+LCFy9bhIpz9FcpT3dmvID6/fTmeAMK/O+++/rzdzvhwGCURE5FKsASIrToSIOqA//vhDl6XA+lxw6tQprdshIiJKONYAkXs5nQE6evSoTlCIQmXMoFy3bl1JnTq1fP7553ofw+OJiIhcgwEQWSQDhFofTIB4+fJlSZ48uW1706ZNHYafExERJbgLjBkgskoGaPXq1bJ27Vqdc8denjx55OTJk65sGxERBSxOhEgWywBhFBhmfo5ukkJ0hRERESUYi6DJagEQ5uIZMWKE7T6KoFH8HB4eLs8++6yr20dERAGJXWBksS4wzAGEIuhixYrJnTt35OWXX5YDBw7oOlwYFUZERJRgzACR1QIgrJK+Y8cOmTFjhn5F9gczQ7du3dqhKJqIiCj+mAEiCwVA9+/flyJFisiCBQs04MGNiIjI5ZgBIivVAAUHB2u3FxERkXsxA0QWK4J+6623dNJDzAZNRETkXgyAyCI1QJs2bdIJD3///XcpWbKkpEyZ0uHxOXPmuLJ9REQUiDgRIlktAEqbNq00b97cPa0hIiJSnAiRLBYATZo0yT0tISIiMrEImqy8Gvy4cePk+vXruo2rwRMRkeuwC4zci6vBExGRhXvAGACRe3A1eCIisiBmgMi9uBo8ERFZuAaIyD24GjwREVkQM0DkXlwNnoiIrIejwMhqXWDDhw+XevXqcTV4IiJyP2aAyCoBUM6cOXUV+OnTp8vOnTu5GjwREbkBa4DIYgEQsj7JkiWTV155xT0tIiIiYhcYWa0GKHPmzNK2bVtZunSpFkQTERG5HougyWIZoO+//16mTp0qjRs3ltDQUGnZsqVmgzA3EBEReVnEA5Etk0SunxafFnH/v28YAJFFAiBMeIgblsCYPXu2Fj5XrlxZ8uXLp4FQv3793NNSIiJ6vCOrRRb2EP+QSCQ4hbcbQX4qkWEkfLapPXv2aBE0iqKjmyPI11y7dk2zW1evXpU0adJ4uzlERHG3Z77IzDYiqbKKFG8qPi17WZHSLb3dCvLT67fTGSD7YuhffvlFu8MWL14sWbJkkZ49e8b3cERE5ArGf7WZGfKLNBjs7dYQWZbTAdCSJUs06Jk3b54EBQXJCy+8IL///rvUqFHDPS0kIiLnA6BETo9xIQoo8aoBeu655+SHH37QmZ+Dg4Pd0zIiInKeWdXA0VNEsXL6T4SzZ8/KzJkzdRRYQoOfVatWSaNGjSR79uy6pAaySqb79+9Lr169pGTJkpIyZUrdp02bNnLq1KlYj9m/f389lv2tSJEiCWonEZHP4Pw5RO7JAGHBUxQ6I1jZu3evbsOyGAiIkiRJ4tSxbt68KaVLl5YOHTpIs2bNHB67deuWbN26Vfr27av7XL58Wbp16ybPP/+8bN68OdbjFi9eXP744w/bfXTVEREFBHaBEcWJ05HBwYMHtevr5MmTUrhwYd02aNAgCQsLk99++03y588f52M1aNBAb9FBFTcmW7Q3atQoqVixohw7dkxy5coV43ER8GTNmjXO7SAi8hsMgIjixOn/IW+//bYGOcePH9cMDW4ISPLmzauPuROGtaFLK23atLHuh8VZ0WWGuYkwPB/ti83du3d16Jz9jYjIN5k1QAyAiGLj9P+QlStXypAhQyR9+vS2bRkyZJDBgwfrY+6CYfeoCWrVqlWsY/srVaokkydP1qH5Y8aMkcOHD0v16tV14saYIIOFjJN5QzaLiMi3M0CsASJyaQAUEhISbTCBVeGTJk0q7oCC6BYtWgjmbERQExt0qb344otSqlQpqVevnixcuFCuXLmihdsx6dOnj2aXzBuyW0REPoldYERx4vT/EAyBf/3112XDhg0akOC2fv16eeONN7RA2V3Bz9GjR7UmyNmZmdFdVqhQIa1dii2ow3Htb0REvj0MngEQUWyc/h/y1VdfaQ1QlSpVJFmyZHp78sknpUCBAjJy5EhxR/CDmh6M6kJXm7OQmTp06JBky5bNpW0jIrIkZoCI3DMKDBmV+fPna0bFHAZftGhRDYDiE5zYZ2ZQr7N9+3atL0LAglmmUWS9YMECHXp/5swZ3Q+Pm91ttWvX1skZu3Tpovd79Oihcwvlzp1b5wwKDw/X4fmoHSIi8nusASKKk3hPkIOAJz5Bjz3M51OrVi3b/e7du+vXtm3b6oSGWGsMypQp4/C85cuXy1NPPaXfI7tz4cIF22MnTpzQYOfixYuSKVMmqVatmnbR4XsiooAJgDgRIpFrA6DmzZvrXDwYkWUPI8M2bdoks2bNivOxEMTEthh9XBaqP3LkiMP96dOnx/n1iYj8FrvAiFwbAGH5CmRnoht9NXz4cGcPR0RkPRH3RRb2FLkS+xxilnT1v1GsDICIXBsAxTTcHeuCcQJBIvILxzeKbJkkPi01Z8MncmkAhMVJZ8yYIf369YvS9YQ1wYiIfF7E3Udf0+QUqd1XfE6SpCIF63q7FUT+FQBhcVIsXIri46efflq3LVu2TKZNm+ZU/Q8RkWWZ9Ycp0omUfsnbrSEiKwRAGGKOleA/++wzmT17tiRPnlxnXcY8PTVr1nRHG4mIPIuTCRL5vXgNg2/YsKHeiIj8EicTJPJ7Tv/vxjpZmGvHtHHjRnnnnXdk/Pjxrm4bEZF3cC4dIr/ndAD08ssv60SEgJmZ69Spo0HQhx9+KB9//LE72khE5FnMABH5Paf/d+/atUsnQgSssI5RYWvXrpUpU6bI5MmT3dFGIiIPYw0Qkb9LHJ8FSrF6OqDw2VwBvkiRInL69GnXt5CIyNOYASLye07/7y5evLiMHTtWVq9eLUuXLpX69evrdiw8Gp/V2omILIcLihL5PacDoM8//1zGjRun63hh0dHSpUvrdixcanaNERH5NGaAiPye08PgEfhg9XUse5EuXTrb9tdff11SpEjh6vYREXke5wEi8nvxmgcoSZIkDsEP5MmTx1VtIiKyyDB4IgroAKhcuXK63AWCnrJly0qiWPrFt27d6sr2ERF5HjNARH4vTgFQ48aNbSO/mjRp4u42ERF5F2uAiPxenAKg8PDwaL8nIvJLDICI/F68aoCIyA/dvyPyQ2ORiwe83RLve3D30VcOgycK7AAItT+x1f3Yu3TpUkLbRETecG6PyPH13m6FtWQp4e0WEJE3A6ARI0bYvr948aJ88sknUq9ePalSpYpuW7dunSxZskT69u3rrnYSkacKf1NnE3l1nrdb431JgkXS5/N2K4jITRIZhvlbL26aN28utWrVki5dujhsHzVqlC6NMW+e7//ixBxHoaGhcvXqVUmTJo23m0PkGcc3iXxXRyRdHpFuO7zdGiIit16/na7wQ6bHXP7CHrYhACIiX5/7hnUvROT/nA6AsN7X/Pnzo2zHNq4FRuTLOPcNEQUOp0eBDRgwQF577TVZsWKFVKpUSbdt2LBBFi9eLBMmTHBHG4nIEzj0m4gCiNMBULt27aRo0aLy1VdfyZw5c3Qb7v/111+2gIiIfBBXQCeiABKveYAQ6EyZMsX1rSEi72EGiIgCCH/TEdEjDICIKIDwNx0RPcIFQIkogPA3HRE9wmHwRBRAGAARUaQMEAMgIvJ/iV0x6yJmf967d69rWkRE3sEaICIKIE7/pmvRooUuewG3b9+WJ554QreVKlVKfv75Z6eOtWrVKmnUqJFkz55dF1uNvIwGVuno16+fZMuWTZInTy516tSRAwcev1L16NGjJU+ePJIsWTIdsbZx40Yn3yVRIGIGiIgCh9MBEIKW6tWr6/dz587VIOXKlSs6LxAWSXXGzZs3pXTp0hqwRGfIkCF63LFjx+pkiylTptRFWO/cuRPjMWfMmCHdu3eX8PBw2bp1qx4fzzl37pyT75QowDADREQBxOnFUJGJ+eeffyQsLEzatGmj2ZvBgwfLsWPHpFixYnLjxo34NSRRIg2omjRpovfRLBz7vffekx49eug2LG6WJUsWmTx5srz00kvRHgcZnwoVKtiyVA8fPtS2du3aVXr37h2ntnAxVPIbEQ9Erp+K276Hlov8+rZIzgoir3FdPyLyPc5cv52eCBHBxLp16yR9+vS6/MX06dN1++XLl7XLyVUOHz4sZ86c0W4vE94UAhy8fnQB0L1792TLli3Sp08f27bEiRPrMfCcmNy9e1dv9ieQyOfhb5tva4uc3u7kE9kFRkT+z+lc9zvvvCOtW7eWnDlzaobmqaeesnWNlSxZ0mUNQ/ADyPjYw33zscguXLggERERTj0HBg0apMGVeUOQR+QXXVpm8JMkRCQo2eNvSVOJFH+UhSUi8mdOZ4DefPNNqVixohw/flzq1q2rGRbIly+f0zVAVoGMEeqG7DNADILI59n3br+3TyRFem+2hojI99cCw8gv3Ow1bNhQXClr1qz69ezZszoKzIT7ZcqUifY5GTNmlCRJkug+9nDfPF50QkJC9EbknxMbsrCZiCjBARCKk2fPni3Lly/XkVUoMrZnrhCfUHnz5tWgZdmyZbaAB5kZjAbr3LlztM9JmjSplC9fXp9jFlOjfbjfpUsXl7SLyGcwACIicl0AhBqgcePGSa1atbS2BqO34gsjxg4ePOhQ+Lx9+3YtsM6VK5e+FrrVChYsqAFR3759te7IDG6gdu3a0rRpU1uAg66stm3baoYKXXUjRozQ4fbt27ePdzuJfJNdFxjn9iEiSlgA9OOPP2qW59lnn5WE2rx5swZSJrMOBwEMhrq///77Gry8/vrrOtdQtWrVdOSZ/WizQ4cOafGzqWXLlnL+/HmdQBGFz8ge4TmRC6OJ/B4zQERErpsHCJmYRYsWSZEiRcRfcR4g8gt3r4sMyvno+w/PiAQn93aLiIgsc/12+s/C/v37y4ABA3QZDCKyMGaAiIhc1wWGdb+mTZsmmTNn1vW2goODHR7H8hNEZAEOyV3WABERJSgAQn0OZlt+5ZVXElwETURuxAwQEZHrAqDffvtNlixZogXJROQjGSAGQEREDpz+rYgZklkYTOQLOAyeiMhlAdDw4cN1ePqRI0ecfSoRea0LjAEQEVGCusBQ+3Pr1i3Jnz+/pEiRIkoR9KVLl5w9JBG5MwBi9xcRUcIDIMysTEQ+gAEQEZFrR4ERkQcLmY+tE7n5v9nO4+y2mY1l9xcRkUtWgzfduXNH7t2757CNBdJELrR/kcj0Vgk7RhLHbmoiIopHAIS1uXr16iUzZ86UixcvRnk8IiLCVW0jomsnH31Nnl4kY6H4HaPY8y5tEhFRQAZAGAG2fPlyGTNmjLz66qsyevRoOXnypK4QP3jwYPe0kijQ63jy1RR5cbK3W0NEFLgB0K+//io//PCDPPXUU9K+fXupXr26FChQQHLnzi1TpkyR1q1bu6elRAE9mSHreIiIXMnp4SEY5p4vXz5bvY857B0zQ69atcqljSMKeBzJRUTkFk7/VkXwc/jwYf2+SJEiWgtkZobSpk3r+hYSBTIGQEREbuH0b1V0e+3YsUO/7927t9YAJUuWTN59913p2bOnO9pIFLgYABERWaMGCIGOqU6dOrJv3z5dHR51QKVKlXJ1+4gC3H81QAyAiIhcyqnfqvfv35fatWvLgQMHbNtQ/NysWTMGP0RuzQCxCJqIyGsBENb92rlzp0sbQESxYABEROQWieOzGOp3333nntYQUfTD4NkFRkTk3RqgBw8eyMSJE+WPP/6Q8uXLS8qUKR0e/+KLL1zZPqLAxgCIiMgaAdCuXbukXLly+v0///zj8FgipumJ3NMFxokQiYi8GwBhGQwi8hAOgycicgv+ViWyNHaBERFZIgPUtGnTaLu6sA0TImI+oJdfflkKFy7sqjYSBS5mgIiIrBEAhYaGyrx583TZCxRBw9atW+XKlSvyzDPPyIwZM+Tzzz+XZcuWyZNPPumONlMgeHBXZPNEkZvnJaAd+evRVwZARETeDYCyZs2qGZ5Ro0ZJ4sSPfik/fPhQunXrJqlTp5bp06fLG2+8Ib169ZK//vrvlzeRs/YvElnc29utsI6QVN5uARGRX0lkGOY427jJlCmTrFmzRgoVKuSwHSPCqlatKhcuXJC///5bqlevrlkhX3Tt2jXNdF29elVXvCcv2PqDyC9dRdLmEincUAJa0pQiFV8XSZ3F2y0hIvKb63e85gHC+l+RAyBsi4iI0O9RC8Qh8eSS2pcsJUQaDPZ2a4iIyM84HQC9+uqr0rFjR/nggw+kQoUKum3Tpk3y2WefSZs2bfT+ypUrpXjx4q5vLQUOFv8SEZGVAqAvv/xSsmTJIkOGDJGzZ8/qNtzHKvGo+wEUQ9evX9/1raXA4VzPLBERkVOc/vM6SZIk8uGHH8rp06e1xgc3fI+MEB6DXLlySc6cOcUV8uTJo91pkW9vvfVWtPtPnjw5yr7okiMfwwwQERFZKQNkzxMFwuheM2uLzKU46tatKy+++GKs7dq/f7/tPuuRfBDXwCIiIm8HQFj7C/P6pEuXTsqWLRtrQIE5gVwJo87sDR48WPLnzy81a9aM8TloH4brkw9jBoiIiLwdADVu3FhCQkL0+yZNmoi33Lt3T3766Sfp3r17rEHYjRs3JHfu3Do/EYI3FGjHVpR99+5dvdkPoyNvMzNAzN4REZGXAqDw8HD9iq6oWrVqSalSpXQmaE/DDNSoOWrXrl2M+2AJjokTJ2obMQ/AsGHDdH6i3bt3x1iXNGjQIBkwYIAbW05OYwaIiIisNBEiCor37t0refPmFU+rV6+eJE2aVH799dc4P+f+/ftStGhRadWqlQwcODDOGaCwsDBOhOhNa78W+f0jkVItRZqN93ZriIgo0CdCLFGihPz7778eD4COHj0qf/zxh8yZM8ep5wUHB2vd0sGDB2PcB917ZhcfWYQtLmcXGBERuZ7T/QuffPKJ9OjRQxYsWKDD3xFt2d/cZdKkSZI5c2Zp2NC5ZRHQbYelObJly+a2tpEbsAuMiIjcyOkM0LPPPqtfn3/+eYdCZPSk4b79kHVXQTEzAqC2bdtKUJBjkzH7dI4cObSOBz7++GOpXLmyFChQQOuFhg4dqtmj1157zeXtIjdiAERERFYKgJYvXy6ehq6vY8eOSYcOHaI8hu3mqvRw+fJl6dSpk5w5c0aH7ZcvX17Wrl0rxYoV83CryTUBELvAiIjIAgEQan9QIBx5GDoyQMePHxd3wNIaMdVqr1ixIspSHbiRr+MweCIislgAhNof1OPYu3Tpkj7mji4wChCXDov80V/k7nWRy4cfbWMXGBERWSEAMmt9opt8kGtuUYLsnCGyZ57jtlSc0ZuIiLwYAGH2ZUDw07dvX0mRIoXtMWR9NmzYIGXKlHFDEylgPPhvLqb8Tz+a/yc4uUjBZ7zdKiIiCuQAaNu2bbYMEIaVY0JCE74vXbq0Do8nSnDdT6YiIqVf8nZjiIjIjwU5O/qrffv2MnLkSM6QTK7Hoe9ERGTVGiDMx0PkFhz6TkREHsI/tck6zKkOmAEiIiI345WGrIMBEBEReQivNGS9LjAugEpERFYIgMqVK6dLTJhrbd26dcvd7aJAxCJoIiLykDhdafbu3Ss3b97U7wcMGKCTHhK5HrvAiIjIQqPAMMEhhr9Xq1ZN5wEaNmyYpEqVKtp9+/Xr5+o2UqBgBoiIiKwUAE2ePFnCw8NlwYIFOhP0okWLJCgo6lPxGAMgijcOgyciIisFQIULF5bp06fr94kTJ5Zly5ZFWQyVKMGYASIiIqtOhPjwoTlSh8hdw+CZASIiIosFQHDo0CEZMWKEFkdDsWLFpFu3bpI/f35Xt48CCTNARETkIU5faZYsWaIBz8aNG6VUqVJ6w0rwxYsXl6VLl7qnlRRYGSDOA0RERFbLAPXu3VveffddGTx4cJTtvXr1krp167qyfRQoLh8R2f7To++ZASIiIjdz+kqDbq+OHTtG2d6hQwfZs2ePq9pFgebw6v99n7mYN1tCREQBwOkAKFOmTLJ9+/Yo27GNI8MowfU/2cuKFHrG260hIiI/53QXWKdOneT111+Xf//9V6pWrarb1qxZI59//rl0797dHW2kQAqAUmf3dkuIiCgAOB0A9e3bV1KnTi3Dhw+XPn366Lbs2bNL//795e2333ZHGykQcBJEIiKycgCE2Z5RBI3b9evXdRsCIqKE4TpgRERk8XmATAx8yPWTIDIAIiIi9+PVhqyBXWBERORBDIDIGjgLNBEReRCvNmQNDICIiMiDeLUha2ANEBEReVC8rjZdunSRS5cuub41FLjMDBDXASMiIisFQCdOnLB9P3XqVLlx44Z+X7JkSTl+/Lh7WkeBg11gRERkxWHwRYoUkQwZMsiTTz4pd+7c0aAnV65ccuTIEbl//757W0n+jwEQERF5UJyvNleuXJFZs2ZJ+fLl5eHDh/Lss89KoUKF5O7du7JkyRI5e/asyxuH2aUx8aL9DYFYbNBG7JMsWTLNTi1cuNDl7SJ3MGuAvN0OIiIKBHEOgJDlqVixorz33nuSPHly2bZtm0yaNEmSJEkiEydOlLx580rhwoVd3sDixYvL6dOnbbe//vorxn3Xrl0rrVq10tXq0b4mTZrobdeuXS5vF7kYM0BERGTFLrC0adNKmTJltAvs3r17cvv2bf0+KChIZsyYITly5JBNmza5voFBQZI1a9Y47Tty5EipX7++9OzZU+8PHDhQli5dKqNGjZKxY8eK37l5UeT+TfELt688+soAiIiIrBQAnTx5UtatW6dZlgcPHmhXWIUKFTQY2rp1q+TMmVOqVavm8gYeOHBAF1tFl1aVKlVk0KBBWnsUHbQv8or09erVk3nz5sX6GujGw8107do1sbxdc0Rmd/hf15HfYB8YERG5X5z/3M6YMaM0atRIA5AUKVJotqdr165al9OjRw8JDQ2VmjVrurRxlSpVksmTJ8vixYtlzJgxcvjwYalevbptEdbIzpw5I1myZHHYhvvYHhu8J7TfvIWFhYnlndr6KPhJlEQkKJl/3JKnFylU39tnloiIAkC8F0NFoNCiRQutt/nzzz81KFq5cqVLG9egQQPb96VKldKAKHfu3DJz5kx9XVfp06ePQ+YIGSDLB0HmxIFVu4jU/djbrSEiIvL/AGjnzp1a8wMISIKDg7VOp2XLluJOqEPCyLODBw9G+zjaEHk0Gu4/roYoJCREbz6FMycTERHFW7yunsiOJE786KkYYeWpbAkmXzx06JBky5Yt2sdRI7Rs2TKHbSiCxna/w1FTRERE8Wbpqydqi9CthskWUXzdtGlTHXaPoe7Qpk0b7b4ydevWTeuFhg8fLvv27dN5hDZv3qxLd/gfs/iZRcNEREQeqwHyBCy/gWDn4sWLkilTJh1ltn79ev0ejh07ZstEQdWqVXWZjo8++kg++OADKViwoI4AK1GihPgdZoCIiIj8MwCaPn16rI+vWLEiyrYXX3xRb36PARAREVG88erpqxgAERERxRuvnr7KNgqMNUBERETOYgDk8xkgBkBERETOYgDkq9gFRkREFG+8evosDoMnIiKKLwZAvoozQRMREcUbr56+il1gRERE8carp69iAEREROSfEyH6tWunRE5sjv/zrxx/9JWjwIiIiJzGAMhbJjUQuXwk4cdJHOyK1hAREQUUBkDecvXko6/Zy4okCYnfMVKkFyn6nEubRUREFAgYAHnNf6O4Wk4RCc3h7cYQEREFFFbQehtreIiIiDyOAZC35/HhRIZEREQexwDIa8wAiIiIiDyNAZC3cDV3IiIir2EA5DXsAiMiIvIWBkDexgwQERGRxzEA8moBNDAAIiIi8jQGQN4OgJgBIiIi8jgGQF7BDBAREZE3MQDyNmaAiIiIPI4BkNdrgIiIiMjTGAB5BWuAiIiIvIkBkDdwFBgREZFXcTV4r2AGiIiIPO/ijbsyfdNxuXXvgbebIpXyZpAahTJ57fUZAHkDM0BEROQFk9YckVHLD4pVLoUMgAIOi6CJiMjzrt+5r19Lh6WVcrnSerUt5XOn8+rrMwDyBk6ESEREXvDwv8vPU4Uyybt1C0kgYxG0V7ALjIiIPO/hf3+AJ+Yf3wyAvI4fQiIi8vCf34l46bF2ADRo0CCpUKGCpE6dWjJnzixNmjSR/fv3x/qcyZMnS6JEiRxuyZIlE0thETQREXmBYcsAScCzdAC0cuVKeeutt2T9+vWydOlSuX//vjzzzDNy8+bNWJ+XJk0aOX36tO129OhRsRbWABERkec9fPjoayJee6xdBL148WKH+8juIBO0ZcsWqVGjRozPww82a9asYlnMABERkRewBshHMkCRXb16Vb+mT58+1v1u3LghuXPnlrCwMGncuLHs3r071v3v3r0r165dc7i5FzNARETkeawB8sEA6OHDh/LOO+/Ik08+KSVKlIhxv8KFC8vEiRNl/vz58tNPP+nzqlatKidOnIi11ig0NNR2Q+DkVswAERGRVzNAEvB8JgBCLdCuXbtk+vTpse5XpUoVadOmjZQpU0Zq1qwpc+bMkUyZMsm4ceNifE6fPn00u2Tejh8/Lu7FDBAREXme+fd3Yl57rF0DZOrSpYssWLBAVq1aJTlz5nTqucHBwVK2bFk5eDDmqb9DQkL05jHMABERkRdHgZHFM0D4QSH4mTt3rvz555+SN29ep48REREhf//9t2TLlk0siVE4ERF5eCboxLz2WDsDhG6vqVOnaj0P5gI6c+aMbkedTvLkyfV7dHflyJFD63jg448/lsqVK0uBAgXkypUrMnToUB0G/9prr4k18UNIRESewRogHwmAxowZo1+feuoph+2TJk2Sdu3a6ffHjh2TxIn/l8i6fPmydOrUSYOldOnSSfny5WXt2rVSrFgxsQymIImIyJs1QIkZAQX5el/lihUrHO5/+eWXerM2FkETEZHnGf9dfxJ5uyEWYOkAyO8goFs2QOTE5v9tYwBERBQn87adlLnbTjosJ03O2XPq0Xx6iXjtYQDkUVeOifxll51KlcWbrSEi8ilDl+yXk1due7sZfiFzag+OfLYoBkCeFHHv0deg5CKNRojkrODtFhER+Yy7Dx4tZNWzXmHJFmqxRa59SPqUSaV6wUwS6BgAeZJZ0xQUIlL6JW+3hojIxzz6HVqnaBYpnDW1txtDPs7S8wD5HcNchpennYgo/nPYeLsl5A94JfYkBkBERAmew4YFvOQKvBJ7EgMgIqJ4e/hfCojxD7kCr8Qe9V/+lgEQEZHTuJAnuRKvxF7JAPE/LxGRs8z5f1gDRK7AAMiT2AVGROSCdawYAVHC8UrsjfwtAyAiongHQESuwCuxVwIg/vVCRBTvYfDsAyMXYADkjS4wLkNHROQ8zgNELsQAyJNYA0RElPB5gPhHJLkAr8QexRogIqKEF0F7uyXkD3gl9iRmgIiIElwDxJmgyRV4JfYkzgNERBQvht0IMGaAyBW4GrwnXT/z6CszQETR6v3zTvl9z1lvN4MsHgAxA0SuwADIG87v83YLiCx5gZu+6bi3m0EWlyNtckmdjJcuSjh+irwhT3Vvt4DIcuznuJv9RhUJTR7szeaQReVMl0KCkzCLTgnHAMgbNUCJk3i7JUSWnuW3QOZUkjZFUq+2h4j8G8NoT+IoMKIY2S9ywBoPInI3Xok9iWuBEcUpA8T4h4jcjVdiT2IGiChONUBc7ZuI3I1XYk/iWmBEccoAcZ4XInI3BkCexAwQUYyYASIiT+KV2JMYABHFKQNERORuvBJ7lG0hG283hMiy6zwBM0BE5G4MgDyJa4ERxcwhAPJmQ4goEDAA8iQOgyeKYxE0IyAici9eiT2JNUBEMeI8QETkST5xJR49erTkyZNHkiVLJpUqVZKNGzfGuv+sWbOkSJEiun/JkiVl4cKFYgkcBk8UpxogzgRNRBLoAdCMGTOke/fuEh4eLlu3bpXSpUtLvXr15Ny5c9Huv3btWmnVqpV07NhRtm3bJk2aNNHbrl27xOvYBUYUI+O/IiDW/xCRJyQyDGuPPUXGp0KFCjJq1Ci9//DhQwkLC5OuXbtK7969o+zfsmVLuXnzpixYsMC2rXLlylKmTBkZO3ZsnF7z2rVrEhoaKlevXpU0adK47L3cXTpQQtYMk5uFm8nl+qNddlwif3Dhxj1pMnqNBCVOJAc/e9bbzSEiH+TM9dvSq8Hfu3dPtmzZIn369LFtS5w4sdSpU0fWrVsX7XOwHRkje8gYzZs3L8bXuXv3rt7sT6A7XN65WLKKyJI956T7juVueQ0iX8feLyLyBEsHQBcuXJCIiAjJkiWLw3bc37dvX7TPOXPmTLT7Y3tMBg0aJAMGDBB3O5KljiS7dlhWyBMSEsRuMKLoPFcqu7ebQEQBwNIBkKcgw2SfNUIGCN1srlb5FQRZA+Qrlx+ZiIiI/CYAypgxoyRJkkTOnj3rsB33s2ZFZ1JU2O7M/hASEqI3IiIiCgyW7odJmjSplC9fXpYtW2bbhiJo3K9SpUq0z8F2+/1h6dKlMe5PREREgcfSGSBA11Tbtm3liSeekIoVK8qIESN0lFf79u318TZt2kiOHDm0jge6desmNWvWlOHDh0vDhg1l+vTpsnnzZhk/fryX3wkRERFZheUDIAxrP3/+vPTr108LmTGcffHixbZC52PHjunIMFPVqlVl6tSp8tFHH8kHH3wgBQsW1BFgJUqU8OK7ICIiIiux/DxA3uCueYCIiIjIGtdvS9cAEREREbkDAyAiIiIKOAyAiIiIKOAwACIiIqKAwwCIiIiIAg4DICIiIgo4DICIiIgo4DAAIiIiooDDAIiIiIgCjuWXwvAGc3JszChJREREvsG8bsdlkQsGQNG4fv26fg0LC/N2U4iIiCge13EsiREbrgUWjYcPH8qpU6ckderUkihRIpdHpwisjh8/znXGXIDn07V4Pl2P59S1eD5d65qfnU+ENAh+smfP7rBQenSYAYoGTlrOnDnd+hr4oPnDh80qeD5di+fT9XhOXYvn07XS+NH5fFzmx8QiaCIiIgo4DICIiIgo4DAA8rCQkBAJDw/Xr5RwPJ+uxfPpejynrsXz6VohAXw+WQRNREREAYcZICIiIgo4DICIiIgo4DAAIiIiooDDAIiIiIgCDgMgDxo9erTkyZNHkiVLJpUqVZKNGzdKoBk0aJBUqFBBZ9nOnDmzNGnSRPbv3++wz507d+Stt96SDBkySKpUqaR58+Zy9uxZh32OHTsmDRs2lBQpUuhxevbsKQ8ePHDYZ8WKFVKuXDkd3VCgQAGZPHmy3/9MBg8erLOXv/POO7ZtPJ/OO3nypLzyyit6zpInTy4lS5aUzZs32x7H2JF+/fpJtmzZ9PE6derIgQMHHI5x6dIlad26tU4ulzZtWunYsaPcuHHDYZ+dO3dK9erV9XxhNt4hQ4ZEacusWbOkSJEiug/asXDhQvElERER0rdvX8mbN6+eq/z588vAgQMd1mri+YzdqlWrpFGjRjq7Mf5/z5s3z+FxK50/Iw5tsQyMAiP3mz59upE0aVJj4sSJxu7du41OnToZadOmNc6ePWsEknr16hmTJk0ydu3aZWzfvt149tlnjVy5chk3btyw7fPGG28YYWFhxrJly4zNmzcblStXNqpWrWp7/MGDB0aJEiWMOnXqGNu2bTMWLlxoZMyY0ejTp49tn3///ddIkSKF0b17d2PPnj3G119/bSRJksRYvHix3/5MNm7caOTJk8coVaqU0a1bN9t2nk/nXLp0ycidO7fRrl07Y8OGDfrelyxZYhw8eNC2z+DBg43Q0FBj3rx5xo4dO4znn3/eyJs3r3H79m3bPvXr1zdKly5trF+/3li9erVRoEABo1WrVrbHr169amTJksVo3bq1/n+YNm2akTx5cmPcuHG2fdasWaPneciQIXreP/roIyM4ONj4+++/DV/x6aefGhkyZDAWLFhgHD582Jg1a5aRKlUqY+TIkbZ9eD5jh/+TH374oTFnzhxEjcbcuXMdHrfS+Rsch7ZYBQMgD6lYsaLx1ltv2e5HREQY2bNnNwYNGmQEsnPnzul/6JUrV+r9K1eu6H8o/JI07d27V/dZt26d7ZdB4sSJjTNnztj2GTNmjJEmTRrj7t27ev/99983ihcv7vBaLVu21ADMH38m169fNwoWLGgsXbrUqFmzpi0A4vl0Xq9evYxq1arF+PjDhw+NrFmzGkOHDrVtw3kOCQnRiwbg4oBzvGnTJts+ixYtMhIlSmScPHlS73/zzTdGunTpbOfYfO3ChQvb7rdo0cJo2LChw+tXqlTJ+L//+z/DV6D9HTp0cNjWrFkzvdACz6dzIgdAVjp/D+PQFithF5gH3Lt3T7Zs2aKpQPv1xnB/3bp1EsiuXr2qX9OnT69fcZ7u37/vcK6Qbs2VK5ftXOErUq9ZsmSx7VOvXj1d1G/37t22feyPYe5jHsPffibo4kIXVuT3zPPpvF9++UWeeOIJefHFF7U7sGzZsjJhwgTb44cPH5YzZ844vFesPYQuP/tzim4GHMeE/XFONmzYYNunRo0akjRpUodzii7hy5cvx+m8+4KqVavKsmXL5J9//tH7O3bskL/++ksaNGig93k+E8ZK5+9wHNpiJQyAPODChQvaD25/gQHcx4clUD18+FBrVZ588kkpUaKEbsP5wH9A/GeN6Vzha3Tn0nwstn1wUb99+7Zf/UymT58uW7du1fqqyHg+nffvv//KmDFjpGDBgrJkyRLp3LmzvP322/L999/r4+b7ie294iuCJ3tBQUEa6LvivPvSOe3du7e89NJLGngHBwdrQIn/96hHAZ7PhLHS+TsTh7ZYCVeDJ69mLXbt2qV/DVL8HD9+XLp16yZLly7VokRyTWCOv5Q/++wzvY8LNj6nY8eOlbZt23q7eT5n5syZMmXKFJk6daoUL15ctm/frgEQCnp5PsmbmAHygIwZM0qSJEmijLzB/axZs0og6tKliyxYsECWL18uOXPmtG3H+UB3ypUrV2I8V/ga3bk0H4ttH4yAwMgEf/mZoNvp3LlzOjoLf9HhtnLlSvnqq6/0e/zlxfPpHIxeKVasmMO2okWL6kg5MN9PbO8VX/FzsYdRdRiJ44rz7kvnFCMKzSwQulpfffVVeffdd20ZS57PhLHS+csah7ZYCQMgD0AXRPny5bUf3P6vTNyvUqWKBBLU8CH4mTt3rvz55586NNYezhPS5PbnCn3QuPiY5wpf//77b4f/0MiA4GJsXriwj/0xzH3MY/jLz6R27dp6LvBXtXlD9gLdC+b3PJ/OQZds5KkZUL+SO3du/R6fWfwyt3+v6ApELYX9OUXQiQDVhM87zgnqIcx9MLwZNVr257Rw4cKSLl26OJ13X3Dr1i2tNbGHYBnnAng+E8ZK5y9vHNpiKd6uwg4UGCKMSvjJkydrRf7rr7+uQ4TtR94Egs6dO+sQyRUrVhinT5+23W7duuUwbBtD4//8808dtl2lShW9RR62/cwzz+hQegzFzpQpU7TDtnv27KmjnkaPHh3tsG1//JnYjwIDnk/npxMICgrS4dsHDhwwpkyZou/9p59+chjqi/c2f/58Y+fOnUbjxo2jHXZctmxZHUr/119/6Sg9+2HHGB2DYcevvvqqDjvG+cPrRB52jLYMGzZMz3t4eLhPDNu217ZtWyNHjhy2YfAYyo1pFjCy0MTz+fhRnpiiAjdctr/44gv9/ujRo5Y7f4Pj0BarYADkQZg7BRcizJWCIcOYjyHQ4D9vdDfMDWTCf5Q333xTh2TiP2DTpk01SLJ35MgRo0GDBjpPBX6Zvvfee8b9+/cd9lm+fLlRpkwZPd/58uVzeA1//plEDoB4Pp3366+/alCIgK5IkSLG+PHjHR7HcN++ffvqBQP71K5d29i/f7/DPhcvXtQLDOa8wZQC7du31wuZPcyTgiH3OAaCBFw8Ips5c6ZRqFAhPaeYiuC3334zfMm1a9f084jPRbJkyfSzgzlt7Idb83zGDv/3ovu9ieDSaufvYRzaYhWJ8I+3s1BEREREnsQaICIiIgo4DICIiIgo4DAAIiIiooDDAIiIiIgCDgMgIiIiCjgMgIiIiCjgMAAiIiKigMMAiIhitG/fPqlcubIutFqmTBmxiiNHjkiiRIl0uY+Y4PF58+Z5tF1E5DsYABH5gfPnz+t6XDdv3tS1fFKmTGlbvDMhwsPD9VhYGyvyGkBWd/r0aWnQoIG3myH9+/ePNni0WoDWrl07adKkibebQeQxQZ57KSJyl3Xr1knp0qU1WMHCg+nTp5dcuXIl+LiHDh2Shg0b2hYCdQUEaFig1d2suPo0EVkHM0BEfmDt2rW6ijn89ddftu9jg5WgP/74Y8mZM6eEhIRolmLx4sUOGQqsHo198D0yGTEdZ8iQIVKgQAE9DgKvTz/91KGrasaMGVKzZk3tSpsyZYpcvHhRWrVqJTly5JAUKVJIyZIlZdq0aXE+bmQRERHSoUMHKVKkiC3zZZ9hMdsxZ84cqVWrlr4mAkYEjvYmTJggYWFh+njTpk3liy++kLRp08Z6Hnv16iWFChXS5+TLl0/69u1rW1F78uTJMmDAANmxY4e+Pm7YlidPHn0cr4Ft5n2YP3++lCtXTs8VjofnP3jwwOHnMm7cOHnuuef0NYsWLarv4+DBg/LUU09pEFy1alUNXiNnofA88/21aNFCrl69anv8+++/19c227lixQq5d++edOnSRbJly6btQSA8aNCgWM8Hkc/w9mJkRBQ/WAk6NDRUb1iRGQtN4nssUohFCPF9586dY3w+VpTGoojTpk0z9u3bp6tz4zj//POPPo4FU7HYIRZGxfeRF0404XlYaBWrwB88eNBYvXq1MWHCBH0Mq3/j10yePHmMn3/+WVeVP3XqlHHixAlj6NChuqL1oUOHjK+++kpXl8dK1c4cF8+/c+eOLvCKla7PnTtnez4enzt3rsP+WNgUq5JjccYXXnjByJ07t23RV6yQnThxYm0XHseK9+nTp9fzGJuBAwfqKtl4jV9++UUXgfz888/1sVu3bun5w3nEOcQN29BOcxFgbDPbvWrVKv2Z4D3jvPz+++967vr37+/wvrBQ5YwZM7SdTZo00X2efvppY/HixcaePXuMypUr6+rfJqzanTJlSt0H52zlypVGgQIFjJdfflkfx8+2RYsW+hyznVisFOciLCxM24UFc/EzmDp1aqzng8hXMAAi8lG4cOOiixWcEbjgKwIFrPaMCxweO3/+fIzPz549u/Hpp586bKtQoYKuHG8qXbq0XjxjW+kbwZYZmERmBh4jRox47Ptp2LChBgvOHBcXZKw2jRWsr1y54rBPdAHQt99+a3t89+7dum3v3r16v2XLltoGe61bt35sABQZgoby5cvb7uP84TxGZt8+E97LZ5995rDtxx9/NLJly+bwvI8++sh2f926dbrtu+++s21DUIuA2L4NCDAReJoWLVqkAR+CHcDK4o0bN3Z47a5du2rQhBW+ifwNu8CIfFRQUJB2nWCkVoUKFaRUqVJy5swZyZIli9SoUUMfy5gxY7TPvXbtmpw6dSpKVxnu7927N85twL53796V2rVrx7rfE088EaXLauDAgdr1hXqlVKlSyZIlS2zdV3E9LrrRUPj9+++/S2ho6GPbi3NkQrcOnDt3Tr+i0LtixYoO+0e+Hx107+G8oeYI7+Ojjz6KdwE6usrQ5YjjmLdOnTppQfetW7eifR/4eQPOpf22O3fu6M/ZhC5EdDmaqlSpot2MeN+xFUZjpF3hwoXl7bff1vNM5C9YBE3ko4oXLy5Hjx7VehNcyHCxRK0Ibvge9Rq7d+92axuSJ08ep/1Ql2Jv6NChMnLkSBkxYoReuPH4O++8ozUnzhz32WeflZ9++klrYJ5++unH7m9ffI06F8C5iy+8buvWrbVOp169ehqETZ8+XYYPHx6v4924cUOP1axZsyiPoQYntvfh6vcGqEU6fPiwLFq0SP744w+tG6pTp47Mnj07QcclsgJmgIh81MKFC/Wvc2QeEATg+xIlSmhQge/xeEzSpEkj2bNnlzVr1jhsx/1ixYrFuQ0FCxbUYMXZIfJ4ncaNG8srr7yixcgo9v3nn3+cPm7nzp1l8ODB8vzzz8vKlSslIZDl2LRpk8O2yPejKz5HoPnhhx9qlgvtRlBqD9MTIOMVGQKWyNsRcCAjg8LvyLfEiRP26xpZKWT9TOvXr9dj4n3H1k58Vlq2bKkF4sh2/fzzz3Lp0qUEtYXICpgBIvJRuPCiy+vs2bMaTOCvfmR8mjdvbuveiU3Pnj11np/8+fPrCKFJkyZp4IRRWnGFrARGQb3//vt6AUVXEOYkQjs6duwY4/MQKCCLgAAiXbp0OtoK78MMvpw5bteuXfXCjVFRyFRUq1Ytzu2PfBx0HaItjRo1kj///FOPZ2ZTYnofCCyQ9UE35G+//SZz58512Addkcii4NxixF3q1Kl1VBu2I8DDe8N9nId+/frp+0B31QsvvKABCrrFdu3aJZ988okkBM5p27ZtZdiwYdo1hi4tZHTM6QLQHnRDIgDLkCGDZrO+/vpr/SyVLVtW2zJr1izd/3Ej44h8greLkIgo/lDsigJgwEgdjOyJq4iICB1dhBFFKKJGoS4KY+09rgjaPM4nn3yiI6pwnFy5ctkKee1Ha9m7ePGiFtyiYDtz5sxa1NumTRuHIlxnjzt8+HAjderUOiIrpiJo+/0vX76s25YvX27bNn78eD0fyZMn19FVeP2sWbPG+v579uxpZMiQQd8LCqm//PJLh8JpjFJr3ry5kTZtWtvIL8CIMfy8goKC9D2aMJKratWq2gaMCKtYsaK2K6bi6ejeG94TtuE92hdif/PNN1r8jgJpjIK7dOmS7TkYiVa3bl19H+Z5weuWKVNGR5ChLSjS3rp1a6zng8hXJMI/3g7CiIisCAXIKDJfvXq1+DLM84M5kWJbOoQo0LALjIjoP+geqlu3rhZlo/sLkwN+88033m4WEbkBAyAiov9s3LhRZ5++fv26FmZ/9dVX8tprr3m7WUTkBuwCIyIiooDDYfBEREQUcBgAERERUcBhAEREREQBhwEQERERBRwGQERERBRwGAARERFRwGEARERERAGHARAREREFHAZAREREFHD+H8nMPLF9+g9jAAAAAElFTkSuQmCC",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# print plots\n",
"line_old, = plt.plot(bletchley.timeseries, label=\"Bruteforce Strategy\")\n",
"line_new, = plt.plot(boostedBletchley.timeseries, label=\"Boosted Strategy\")\n",
"plt.legend(handles=[line_old, line_new])\n",
"plt.xlabel('# of cracking attempts')\n",
"plt.ylabel('# of trigrams discovered')\n",
"plt.title('Trigram Discovery Over Time');"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We see that the boosted fuzzer is constantly superior over the random fuzzer."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Estimating the Probability of Path Discovery\n",
"\n",
"\n",
"\n",
"\n",
"So, what does Turing's observation for the Naval Enigma have to do with fuzzing _arbitrary_ programs? Turing's assistant I.J. Good extended and published Turing's work on the estimation procedures in Biometrica, a journal for theoretical biostatistics that still exists today. Good did not talk about trigrams. Instead, he calls them \"species\". Hence, the GT estimator is presented to estimate how likely it is to discover a new species, given an existing sample of individuals (each of which belongs to exactly one species). \n",
"\n",
"Now, we can associate program inputs to species, as well. For instance, we could define the path that is exercised by an input as that input's species. This would allow us to _estimate the probability that fuzzing discovers a new path._ Later, we will see how this discovery probability estimate also estimates the likelihood of discovering a vulnerability when we have not seen one, yet (residual risk)."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Let's do this. We identify the species for an input by computing a hash-id over the set of statements exercised by that input. In the [Coverage](Coverage.ipynb) chapter, we have learned about the [Coverage class](Coverage.ipynb#A-Coverage-Class) which collects coverage information for an executed Python function. As an example, the function [`cgi_decode()`](Coverage.ipynb#A-CGI-Decoder) was introduced. The function `cgi_decode()` takes a string encoded for a website URL and decodes it back to its original form.\n",
"\n",
"Here's what `cgi_decode()` does and how coverage is computed."
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.505983Z",
"iopub.status.busy": "2025-10-26T18:02:53.504696Z",
"iopub.status.idle": "2025-10-26T18:02:53.530729Z",
"shell.execute_reply": "2025-10-26T18:02:53.530345Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"from Coverage import Coverage, cgi_decode"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.532988Z",
"iopub.status.busy": "2025-10-26T18:02:53.532822Z",
"iopub.status.idle": "2025-10-26T18:02:53.535689Z",
"shell.execute_reply": "2025-10-26T18:02:53.535128Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"encoded = \"Hello%2c+world%21\"\n",
"with Coverage() as cov:\n",
" decoded = cgi_decode(encoded)"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.537922Z",
"iopub.status.busy": "2025-10-26T18:02:53.537792Z",
"iopub.status.idle": "2025-10-26T18:02:53.543547Z",
"shell.execute_reply": "2025-10-26T18:02:53.543154Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'Hello, world!'"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"decoded"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.546013Z",
"iopub.status.busy": "2025-10-26T18:02:53.545886Z",
"iopub.status.idle": "2025-10-26T18:02:53.550270Z",
"shell.execute_reply": "2025-10-26T18:02:53.549823Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{('cgi_decode', 19), ('cgi_decode', 16), ('cgi_decode', 25), ('cgi_decode', 31), ('cgi_decode', 28), ('cgi_decode', 34), ('cgi_decode', 40), ('cgi_decode', 18), ('cgi_decode', 24), ('cgi_decode', 27), ('cgi_decode', 30), ('cgi_decode', 33), ('cgi_decode', 39), ('cgi_decode', 17), ('cgi_decode', 20), ('cgi_decode', 23), ('cgi_decode', 29), ('cgi_decode', 26), ('cgi_decode', 32), ('cgi_decode', 38)}\n"
]
}
],
"source": [
"print(cov.coverage());"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Trace Coverage\n",
"First, we will introduce the concept of execution traces, which are a coarse abstraction of the execution path taken by an input. Compared to the definition of path, a trace ignores the sequence in which statements are exercised or how often each statement is exercised.\n",
"\n",
"* `pickle.dumps()` - serializes an object by producing a byte array from all the information in the object\n",
"* `hashlib.md5()` - produces a 128-bit hash value from a byte array"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.556696Z",
"iopub.status.busy": "2025-10-26T18:02:53.556495Z",
"iopub.status.idle": "2025-10-26T18:02:53.560224Z",
"shell.execute_reply": "2025-10-26T18:02:53.558618Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import pickle\n",
"import hashlib"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.577738Z",
"iopub.status.busy": "2025-10-26T18:02:53.577456Z",
"iopub.status.idle": "2025-10-26T18:02:53.580082Z",
"shell.execute_reply": "2025-10-26T18:02:53.579667Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"def getTraceHash(cov):\n",
" pickledCov = pickle.dumps(cov.coverage())\n",
" hashedCov = hashlib.md5(pickledCov).hexdigest()\n",
" return hashedCov"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Remember our model for the Naval Enigma machine? Each message must be decrypted using exactly one trigram while multiple messages may be decrypted by the same trigram. Similarly, we need each input to yield exactly one trace hash while multiple inputs can yield the same trace hash."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Let's see whether this is true for our `getTraceHash()` function."
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.582821Z",
"iopub.status.busy": "2025-10-26T18:02:53.582688Z",
"iopub.status.idle": "2025-10-26T18:02:53.586449Z",
"shell.execute_reply": "2025-10-26T18:02:53.585743Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"inp1 = \"a+b\"\n",
"inp2 = \"a+b+c\"\n",
"inp3 = \"abc\"\n",
"\n",
"with Coverage() as cov1:\n",
" cgi_decode(inp1)\n",
"with Coverage() as cov2:\n",
" cgi_decode(inp2)\n",
"with Coverage() as cov3:\n",
" cgi_decode(inp3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"The inputs `inp1` and `inp2` execute the same statements:"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.589005Z",
"iopub.status.busy": "2025-10-26T18:02:53.588885Z",
"iopub.status.idle": "2025-10-26T18:02:53.591781Z",
"shell.execute_reply": "2025-10-26T18:02:53.591425Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"('a+b', 'a+b+c')"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"inp1, inp2"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.594941Z",
"iopub.status.busy": "2025-10-26T18:02:53.594232Z",
"iopub.status.idle": "2025-10-26T18:02:53.604320Z",
"shell.execute_reply": "2025-10-26T18:02:53.603590Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"set()"
]
},
"execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov1.coverage() - cov2.coverage()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The difference between both coverage sets is empty. Hence, the trace hashes should be the same:"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.608293Z",
"iopub.status.busy": "2025-10-26T18:02:53.608104Z",
"iopub.status.idle": "2025-10-26T18:02:53.611683Z",
"shell.execute_reply": "2025-10-26T18:02:53.610849Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'43a2e90236e9e31869e325b43bd82c7a'"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"getTraceHash(cov1)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.615832Z",
"iopub.status.busy": "2025-10-26T18:02:53.615444Z",
"iopub.status.idle": "2025-10-26T18:02:53.622575Z",
"shell.execute_reply": "2025-10-26T18:02:53.621788Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'43a2e90236e9e31869e325b43bd82c7a'"
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"getTraceHash(cov2)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.625116Z",
"iopub.status.busy": "2025-10-26T18:02:53.624976Z",
"iopub.status.idle": "2025-10-26T18:02:53.626909Z",
"shell.execute_reply": "2025-10-26T18:02:53.626426Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"assert getTraceHash(cov1) == getTraceHash(cov2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"In contrast, the inputs `inp1` and `inp3` execute _different_ statements:"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.630325Z",
"iopub.status.busy": "2025-10-26T18:02:53.630052Z",
"iopub.status.idle": "2025-10-26T18:02:53.634144Z",
"shell.execute_reply": "2025-10-26T18:02:53.633485Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"('a+b', 'abc')"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"inp1, inp3"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.636257Z",
"iopub.status.busy": "2025-10-26T18:02:53.636157Z",
"iopub.status.idle": "2025-10-26T18:02:53.645049Z",
"shell.execute_reply": "2025-10-26T18:02:53.639806Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"{('cgi_decode', 28)}"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov1.coverage() - cov3.coverage()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Hence, the trace hashes should be different, too:"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.649779Z",
"iopub.status.busy": "2025-10-26T18:02:53.649430Z",
"iopub.status.idle": "2025-10-26T18:02:53.653179Z",
"shell.execute_reply": "2025-10-26T18:02:53.652739Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'43a2e90236e9e31869e325b43bd82c7a'"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"getTraceHash(cov1)"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.662902Z",
"iopub.status.busy": "2025-10-26T18:02:53.662030Z",
"iopub.status.idle": "2025-10-26T18:02:53.680355Z",
"shell.execute_reply": "2025-10-26T18:02:53.672406Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'6c55c4d7417eb2e234aed580bab70638'"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"getTraceHash(cov3)"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.702716Z",
"iopub.status.busy": "2025-10-26T18:02:53.701064Z",
"iopub.status.idle": "2025-10-26T18:02:53.744170Z",
"shell.execute_reply": "2025-10-26T18:02:53.729643Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"assert getTraceHash(cov1) != getTraceHash(cov3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Measuring Trace Coverage over Time\n",
"In order to measure trace coverage for a `function` executing a `population` of fuzz inputs, we slightly adapt the `population_coverage()` function from the [Chapter on Coverage](Coverage.ipynb#Coverage-of-Basic-Fuzzing)."
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.765617Z",
"iopub.status.busy": "2025-10-26T18:02:53.765463Z",
"iopub.status.idle": "2025-10-26T18:02:53.773932Z",
"shell.execute_reply": "2025-10-26T18:02:53.771257Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"def population_trace_coverage(population, function):\n",
" cumulative_coverage = []\n",
" all_coverage = set()\n",
" cumulative_singletons = []\n",
" cumulative_doubletons = []\n",
" singletons = set()\n",
" doubletons = set()\n",
"\n",
" for s in population:\n",
" with Coverage() as cov:\n",
" try:\n",
" function(s)\n",
" except BaseException:\n",
" pass\n",
" cur_coverage = set([getTraceHash(cov)])\n",
"\n",
" # singletons and doubletons -- we will need them later\n",
" doubletons -= cur_coverage\n",
" doubletons |= singletons & cur_coverage\n",
" singletons -= cur_coverage\n",
" singletons |= cur_coverage - (cur_coverage & all_coverage)\n",
" cumulative_singletons.append(len(singletons))\n",
" cumulative_doubletons.append(len(doubletons))\n",
"\n",
" # all and cumulative coverage\n",
" all_coverage |= cur_coverage\n",
" cumulative_coverage.append(len(all_coverage))\n",
"\n",
" return all_coverage, cumulative_coverage, cumulative_singletons, cumulative_doubletons"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Let's see whether our new function really contains coverage information only for *two* traces given our three inputs for `cgi_decode`."
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.780502Z",
"iopub.status.busy": "2025-10-26T18:02:53.779967Z",
"iopub.status.idle": "2025-10-26T18:02:53.788845Z",
"shell.execute_reply": "2025-10-26T18:02:53.786981Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"all_coverage = population_trace_coverage([inp1, inp2, inp3], cgi_decode)[0]\n",
"assert len(all_coverage) == 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Unfortunately, the `cgi_decode()` function is too simple. Instead, we will use the original Python [HTMLParser](https://docs.python.org/3/library/html.parser.html) as our test subject."
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.803625Z",
"iopub.status.busy": "2025-10-26T18:02:53.803351Z",
"iopub.status.idle": "2025-10-26T18:02:53.808101Z",
"shell.execute_reply": "2025-10-26T18:02:53.806877Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"from Coverage import population_coverage\n",
"from html.parser import HTMLParser"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.824012Z",
"iopub.status.busy": "2025-10-26T18:02:53.823682Z",
"iopub.status.idle": "2025-10-26T18:02:53.830964Z",
"shell.execute_reply": "2025-10-26T18:02:53.830264Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"trials = 50000 # number of random inputs generated"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Let's run a random fuzzer for $n=50000$ times and plot trace coverage over time."
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.835293Z",
"iopub.status.busy": "2025-10-26T18:02:53.834934Z",
"iopub.status.idle": "2025-10-26T18:02:53.839730Z",
"shell.execute_reply": "2025-10-26T18:02:53.838185Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"# create wrapper function\n",
"def my_parser(inp):\n",
" parser = HTMLParser() # resets the HTMLParser object for every fuzz input\n",
" parser.feed(inp)"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:02:53.852446Z",
"iopub.status.busy": "2025-10-26T18:02:53.851879Z",
"iopub.status.idle": "2025-10-26T18:03:12.087106Z",
"shell.execute_reply": "2025-10-26T18:03:12.085560Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# create random fuzzer\n",
"fuzzer = RandomFuzzer(min_length=1, max_length=100,\n",
" char_start=32, char_range=94)\n",
"\n",
"# create population of fuzz inputs\n",
"population = []\n",
"for i in range(trials):\n",
" population.append(fuzzer.fuzz())\n",
"\n",
"# execute and measure trace coverage\n",
"trace_timeseries = population_trace_coverage(population, my_parser)[1]\n",
"\n",
"# execute and measure code coverage\n",
"code_timeseries = population_coverage(population, my_parser)[1]\n",
"\n",
"# plot trace coverage over time\n",
"plt.figure(num=None, figsize=(12, 4), dpi=80, facecolor='w', edgecolor='k')\n",
"plt.subplot(1, 2, 1)\n",
"plt.plot(trace_timeseries)\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of traces exercised')\n",
"plt.title('Trace Coverage Over Time')\n",
"\n",
"# plot code coverage over time\n",
"plt.subplot(1, 2, 2)\n",
"plt.plot(code_timeseries)\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of statements covered')\n",
"plt.title('Code Coverage Over Time');"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Above, we can see trace coverage (left) and code coverage (right) over time. Here are our observations.\n",
"1. **Trace coverage is more robust**. There are less sudden jumps in the graph compared to code coverage.\n",
"2. **Trace coverage is more fine-grained.** There are more traces than statements covered in the end (y-axis).\n",
"3. **Trace coverage grows more steadily**. Code coverage exercises more than half the statements it has exercised after 50k inputs with the first input. Instead, the number of traces covered grows slowly and steadily since each input can yield only one execution trace.\n",
"\n",
"It is for this reason that one of the most prominent and successful fuzzers today, American Fuzzy Lop (AFL), uses a similar *measure of progress* (a hash computed over the branches exercised by the input)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Evaluating the Discovery Probability Estimate\n",
"\n",
"Let's find out how the Good-Turing estimator performs as estimate of discovery probability when we are fuzzing to discover execution traces rather than trigrams. \n",
"\n",
"To measure the empirical probability, we execute the same population of inputs (n=50000) and measure in regular intervals (`measurements=100` intervals). During each measurement, we repeat the following experiment `repeats=500` times, reporting the average: If the next input yields a new trace, return 1, otherwise return 0. Note that during these repetitions, we do not record the newly discovered traces as observed."
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:03:12.098496Z",
"iopub.status.busy": "2025-10-26T18:03:12.098152Z",
"iopub.status.idle": "2025-10-26T18:03:12.104952Z",
"shell.execute_reply": "2025-10-26T18:03:12.103699Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"repeats = 500 # experiment repetitions\n",
"measurements = 100 # experiment measurements"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:03:12.107546Z",
"iopub.status.busy": "2025-10-26T18:03:12.107409Z",
"iopub.status.idle": "2025-10-26T18:03:29.568218Z",
"shell.execute_reply": "2025-10-26T18:03:29.567783Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"emp_timeseries = []\n",
"all_coverage = set()\n",
"step = int(trials / measurements)\n",
"\n",
"for i in range(0, trials, step):\n",
" if i - step >= 0:\n",
" for j in range(step):\n",
" inp = population[i - j]\n",
" with Coverage() as cov:\n",
" try:\n",
" my_parser(inp)\n",
" except BaseException:\n",
" pass\n",
" all_coverage |= set([getTraceHash(cov)])\n",
"\n",
" discoveries = 0\n",
" for _ in range(repeats):\n",
" inp = fuzzer.fuzz()\n",
" with Coverage() as cov:\n",
" try:\n",
" my_parser(inp)\n",
" except BaseException:\n",
" pass\n",
" if getTraceHash(cov) not in all_coverage:\n",
" discoveries += 1\n",
" emp_timeseries.append(discoveries / repeats)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now, we compute the Good-Turing estimate over time."
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:03:29.571099Z",
"iopub.status.busy": "2025-10-26T18:03:29.570951Z",
"iopub.status.idle": "2025-10-26T18:03:37.572085Z",
"shell.execute_reply": "2025-10-26T18:03:37.570170Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"gt_timeseries = []\n",
"singleton_timeseries = population_trace_coverage(population, my_parser)[2]\n",
"for i in range(1, trials + 1, step):\n",
" gt_timeseries.append(singleton_timeseries[i - 1] / i)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Let's go ahead and plot both time series."
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:03:37.583162Z",
"iopub.status.busy": "2025-10-26T18:03:37.582780Z",
"iopub.status.idle": "2025-10-26T18:03:37.863115Z",
"shell.execute_reply": "2025-10-26T18:03:37.862199Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkYAAAHHCAYAAABa2ZeMAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAmRpJREFUeJztnQd4U+X+x79NJ21pC7SFskFmZQ8niigOXLgVvc7ruFfce1zH3z1x4hbRe70OvO6tiICI7L03lNUyuneb//N7T970JE3azCZpv5/nOU1ycprz5uQk7/f8ZpTVarWCEEIIIYTAEuoBEEIIIYSECxRGhBBCCCE2KIwIIYQQQmxQGBFCCCGE2KAwIoQQQgixQWFECCGEEGKDwogQQgghxAaFESGEEEKIDQojQgghhBAbFEaENMLDDz+MqKioUA+DmJg6dar6TBYuXBiw1zzuuOMwYMCARrfbunWr2reMoaFzpHv37rjiiisCNr6WiBw/OY6ENCUURqRFTqh6SUhIQMeOHXHyySfj5ZdfRlFRUaiHGNGIuDAf37Zt22LkyJGYMmUKamtr0ZJZvXq1ElAirILBt99+i1NOOQXt2rVT53WfPn1wxx13YP/+/QgnzOdHQ8vvv/8e6qGSFkpMqAdASCh45JFH0KNHD1RVVWHPnj3qR/iWW27BpEmT8PXXX2PQoEH2bf/1r3/hnnvuCel4I4nOnTvjySefVPfz8vLwwQcf4O9//zvWr1+Pp556CpFOt27dUFZWhtjY2Aa3W7duHSwWi4Mw+r//+z8lHgNtBREB9Pzzz2Pw4MG4++67lSBdvHgxXn31VXz88ceYPn06+vbti3Dg3//+t8NjOT9++eWXeuv79++Pt99+u8ULatL0UBiRFsm4ceMwYsQI++N7770Xv/32G04//XSceeaZWLNmDVq1aqWei4mJUUtzRnpJl5eX29+zP6SmpuJvf/ub/fF1112nJmWZpB999FGXgkImv8rKSmXpCHe0pbEx4uPjm2Q8H330kRJFF154IT788ENER0c7uKLGjBmD888/XwmlpjyPS0pKkJSUVG+9+dwQ/vrrLyWMnNcTEiroSiPExvHHH48HHngA27Ztw3/+858G40fkh3zUqFFIS0tDcnKymvjvu+8+h21EaMj/iktDJtKsrCycc8452LRpk8Pkcfvtt6NLly5qIpXXee6555RQ0Ujci0xursREp06dcN555zmse/HFF3HooYeqfbZv314Jk4MHDzr8r1gsRAT+9NNPSiCKIHrzzTcxevRoZXVwhYxNXI7ekpiYiCOOOEK9V7EgCXI8b7jhBjWRy1jlvf/444/quSVLlijhmpKSoo7tCSecoCZPV5SWlqr3J+4j2f6yyy6r916/+uornHbaacplKvs55JBDlECrqalx+ZqLFi3CUUcdpY6JWBXfeOONRmOMXGGOMZJtRZwI8lma3UWXX3450tPTlfXSmZNOOqlRS49Yodq0aYO33nrLQRQJhx12mLIgrVixAp999plaJ8ddjqscO2cmTJiADh06OBybH374Acccc4wSOa1bt1bHctWqVQ7/J+9TXlPO7VNPPVVtd8kllyDQMUb62Mt3ZPLkyejZs6c6v+Q47dixQ31v5LMVq6V8fuPHj8eBAwfqva4n74m0XCiMCDFx6aWXqtuff/7Z7TbyAyqioqKiQrnk5GpdrExz5syxbyMTi2wjk9bw4cPVNjfffDMKCgqwcuVKtY38iMv/vfDCCyo2RNx4MgneeeeduO222+yvJZaAWbNmKZefmT/++AO7du3CRRddZF8nIkH+/+ijj8ZLL72EK6+8UokPETTOE6+4emQiPPHEE9W2Q4YMUe9/+fLl9jFqFixYoFxhvl7Vb968WU3aIiQ1YqG79dZb1fuT/csEKMdWJqxly5bhrrvuUkJ1y5Ytyv00b968eq8rk7xY90SAiiiS93rWWWc5CEsRJTJpyzGV/cjn8eCDD7p0j4qokoldtnnmmWfUBPvPf/5TxUj5w7HHHoubbrpJ3RcBLW4jWcRdJMdc4oBEpJqRz1uOUUPHfMOGDepzFAEgwtAVclx0DJIgx1tE6nfffeewnQilb775RgltLbBkjCIa5Pg9/fTT6vMQl6BcFDjHSlVXV6vzLDMzUwmXc889F8FCPufXXnsNN954o7qwmDlzJi644ALl9haBLWLw2muvVe9H3IxmvHlPpIViJaQF8d5778mMaV2wYIHbbVJTU61Dhw61P37ooYfU/2heeOEF9TgvL8/ta0yZMkVtM2nSpHrP1dbWqtsvv/xSbfPYY485PH/eeedZo6KirBs3blSP161bp7Z75ZVXHLa7/vrrrcnJydbS0lL1ePbs2Wq7Dz/80GG7H3/8sd76bt26qXXynJn8/HxrQkKC9e6773ZYf9NNN1mTkpKsxcXF1oYYPXq0tV+/furYyLJmzRr1v7KvM844w76dPLZYLNZVq1Y5/P9ZZ51ljYuLs27atMm+bteuXdbWrVtbjz322Hqf4/Dhw62VlZX29c8884xa/9VXX9nX6eNj5rrrrrMmJiZay8vLHcYu//v888/b11VUVFiHDBlizczMtO9ny5YtajsZg7tzRB/jyy+/3P542rRpapsZM2Y4bFdTU2Pt3Lmz9cILL3RYL+eOnAebN2+2ukOfQ3JONkRKSop12LBh9vOvU6dO1nPPPddhm08//VS91qxZs9TjoqIia1pamvWaa65x2G7Pnj3qO2JeL+9T/veee+6xesvEiRPrHTvz68px1Ohjn5GRoc5Vzb333qvWDx482FpVVWVfP2HCBHU+6c/Zm/dEWi60GBHihFxJNpSdpq0e4qJxFxj6v//9T7lH5IrWGe2W+/7779WVubYkaOQKWLSDmPsFccWJNeeTTz5xsEiJa+SMM86wxwVNmzZNxfeIBWjfvn32Rawf8p5mzJjhsB9xEzm7xuT/xfogcSva6iL7kn2LJcZVzIgza9euRUZGhlrEIvLKK6+oK3Rnq4u47bKzsx3ek1jqZD/iItGIC/Liiy9WFrLCwkKH1xCrgDlmSaw7Ekcjx1ZjjpuSz1WOiVilxEIiYzUj/ytWN01cXJx6nJubq1xswUACtMXtJEH/5vNOrCLi0pPPyR16e3EHNYQ8r4+dnH/i1pNjVFxcbN9GPmNxzYrlRLuL8/PzlVXRfD7JOXv44YfXO5/08W8KZPxyrmpkPIJY18xxVLJeYtd27tzp83siLQ8KI0KckMmioYlGXBHiqrr66qtVDI+4sj799FMHkSSxFuIWayjYVWKZJO7FeV8iJvTz5n2Kq07/wEtsikzWst7sVhFXnbgytDDRi7wn2d6MuwlXXC/bt2/H7Nmz1eNff/0Ve/futbsZG0NcYjIByf+JmBGXkLhxRCg2tH+JPxKx4iqmRo6JHF+JIzHTu3dvh8ciAEVImV0i4p47++yz1UQq7iY5Hto9JcfLjHwezuJPhKkQTDeLHHPJdPviiy/UY3GPiRBr7Jjrc6exMhPyvPk8k/NG9idiTJDzQ4SSCA4t3OV80rF3zueTCFjn80nOdXE9NgVdu3Z1eKxFksTquVqv4868fU+kZdK8U20I8ZKcnBw1Wfbq1cvtNmKBkJgfubqUOA2JaZCrbfmxlR9X5wDYQCATmWTOiVVIygqIEJMffYlN0ohwEFEklgZXyI+/8/twhViRRPBJALrExsitBOSOHTvWo7GKsPBk20BkwDWGWAfEMiWCSOLBJPBagtIlQ0viUMIlFVwsZ2LZk2MtIkluxVolcTMNoUW0xIW5QwS2WIvM1jkJhhcBK+eRWOMkFkeEkllo62MjMTny+TvjLPolsN1cniCYuPuOuVuvrZ/evifSMuFZQIgJXUulsewrmQAkW0oWCZp+4okncP/99yuxJKJAJmAJFpaAZ3f1bqQejlhVnK/mtXtHnjdbVyTDSASYBBx//vnnyuVkTgmXfcrriTXLH9Ehk4tMlhK0LMGpX375Ja655pqgCD5n4SYZRmItcUaOiRxzZ4uAWADMGXti+di9e7cKoNaWNQlsluMlIk8jAd2ukGB25zRzCToX/K091Fj1dBFEEiAu4//vf/+r3I+SbdYQYs2SRT4jCSx3ZemUOkGCJAOYEdEl/yOiSc4reX8imMznkyBi21NRHO40x/dEAg9daYTYkAwgSfUVEdJQqrGr9F+JARIkU02QjByJXZDaPe6uXmXylrga520kS00mUUlZNyNX85K2LrE68trmq3s90cnryXtwRjKGxHriKeLCEfeDxNeI2GiKGjMivCTtWmK3zG4rceOJUJDYF+fMK0lRN2fbvf766+q96mOnxZw5S01iTiSjyRXyv1K2wLytPBbRJhYdf9Biy93nIHEv8rlL9qJk8Xl6zCXDTj6rf/zjH/VKEIg7TsStlHxwzhKT80fO1/fff19ZPZ2tU3JxIMdbRL+rUgK69EIk0RzfEwk8tBiRFokENosVQiZCmXhFFElcjFhpJO6ioQJ+4pIRV5pc0cv2EpcgE63EV+jAVbn6lyt1sQDMnz9fBfuKJUIsOtdff70KcJbAabF2iKVJhIDUDxJXnAgDcZfpq1uNTFySeiyLVDZ2vuIVl5EIGak6vXTpUiUyxFolVhVxwYl1wFzzqCGGDh2qJlP5P3HXDBs2DE3BY489Zq8RJcdJXBsiTGQCl/R5Z0S4iNVOjo1YmuRzkP+VMgiCBC+L1UVqBUmQuwgPsQqahZJzjJEICfk8xBIjlhQ5liLAGqt03RginkWoyeuLu1asfeJ+FeuFIOJLXKNyzCXAX84vTxARL+UU5POVtHN5LO9Z3IUioqXGkwTqO49fPlNxGcv5J8fXWWiLgBChKSJZtpVYOhmjxJ+JC1ksk66EfzjTHN8TCQKhTosjpCnRad56kVTeDh06WE888UTrSy+9ZC0sLKz3P86p2NOnT7eOHz/e2rFjR/X/citpwevXr3f4P0kTv//++609evSwxsbGqv1IKr45FV3Sh2+99Vb1GrJN7969rc8++6w9pd+Zo48+Wo3l6quvdvse33rrLZXG3qpVK5XmPnDgQOtdd92l0t41kgJ92mmnNXisdOr7E088YfUUSXk/9NBDG91OXlfStF2xePFi68knn6xKEUhK/ZgxY6x//vmny89x5syZ1muvvdbapk0btf0ll1xi3b9/v8O2c+bMsR5xxBHqeMhxlmPx008/1Uud12NfuHCh9cgjj1RlC+Q4vfrqqw6v52u6vvD2229be/bsaY2OjnaZuq9T5uU9eYuk7st5LMciPj7e2qtXL+vtt9/eYFkJOT9lf7KtO2SM8nlIOrsck0MOOcR6xRVXqOOkkfcp5Rx8wZd0ffmOOI9R1ktJBE/Kc3jynkjLJUr+BENwEUIiG7FASAFGsZ44ZwGR4CDWQokdE4ukWBkJIU0PhREhpB7ysyCuPXHDsLZL0yEB0lLJe+PGjY0GaxNCggNjjAghdiQOSmKsRAxJfy2xYJDg8/HHH6uUe4lzEUsdRREhoYMWI0KIHXGbSVaeBP9K8PPjjz8e6iG1CEQISXFKCYCWprWsp0NI6KAwIoQQQgixwTpGhBBCCCE2KIwIIYQQQmzQkd0A0ldHWgRImX0GQxJCCCGRgUQJSbslKdrqbQ8/CqMGEFHk3JuJEEIIIZHBjh07VFcCb6AwagDdkFEOrHOPJkIIIYSEJ9IcWQwbrhorNwaFUQNo95mIIgojQgghJLLwJQyGwdeEEEIIITYojAghhBBCbFAYEUIIIYTYYIwRIYSQiKOmpgZVVVWhHgYJIbGxsYiOjg7461IYEUIIiaj6NHv27EF+fn6oh0LCAOnr2KFDh4DWGqQwIoQQEjFoUZSZmYnExEQW323BArm0tBS5ubnqcVZWVsBem8KIEEJIxLjPtChq165dqIdDQkyrVq3UrYgjOScC5VZj8DUhhJCIQMcUiaWIEPO5EMh4s2YvjL799lv07dsXvXv3xjvvvBPq4RBCCPETus9IMM+FZu1Kq66uxm233YYZM2YgNTUVw4cPx9lnn00TLCGEEEJansVo/vz5OPTQQ9GpUyckJydj3Lhx+Pnnn0M9LEIIIaRJuOKKK3DWWWd5ZHn58ssvA7bf7t2748UXX0QkEtbCaNasWTjjjDPQsWNHtx/a5MmT1QeQkJCAww8/XIkhza5du5Qo0sj9nTt3Ntn4CSGEEC1QZB5zXk455ZSg7vell17C1KlTG91u9+7dynhAwlwYlZSUYPDgwUr8uOKTTz5RrrKHHnoIixcvVtuefPLJ9vS9cKW2pgZ7d27Gzs2rYK2tDfVwCCGENAEigkSAmJePPvooqPuUMBKp9eOOyspKdSu1gOLj44M6lkghrIWRqNfHHntMxQW5YtKkSbjmmmtw5ZVXIjs7G2+88YaKUJ8yZYp6XixNZguR3Jd17qioqEBhYaHDEgxKSwrR/u2h6PTBUagoLw3KPgghhIQXIjxEgJiXNm3aqOfEevTmm2/i9NNPV/NY//79MXfuXGzcuBHHHXcckpKScNRRR2HTpk3213v44YcxZMgQ9X9dunRR/3fBBRegoKDArStNXuuGG27ALbfcgvT0dGVM0Ps3e2VycnIwYcIEtG3bVu17xIgRmDdvnnpOxjB+/Hi0b99ehamMHDkSv/76K5oLYS2MGkJU7qJFizB27Fj7OovFoh7LySQcdthhWLlypRJExcXF+OGHH+wngSuefPJJpa71IidaMIiLr0s1ragoD8o+CCGkRRT5q6wOySL7DjSPPvooLrvsMixduhT9+vXDxRdfjOuuuw733nsvFi5cqPYposaMCKdPP/0U33zzDX788UcsWbIE119/fYP7ef/99xEXF4c5c+Yog4IzxcXFGD16tJo7v/76ayxbtgx33XUXam0eDnn+1FNPxfTp09X+xBImYS/bt29HcyBis9L27dunin2JYjUjj9euXavux8TE4Pnnn8eYMWPUByofbEMZaXLyiWtOIxajYIgj6e9Sa42CJcqKqgpajAghxBfKqmqQ/eBPIdn36kdORmJcjNflY8TCYua+++5TiyDeD7H4CHfffTeOPPJIPPDAA/YL+ptvvlltY6a8vBwffPCBPZ72lVdewWmnnabmPrFIuULK1zzzzDNux/nf//4XeXl5WLBggbIYCb169bI/L2ErspgF3RdffKFElLNwi0QiVhh5yplnnqkWT82cTeFjjbJYUI5YtEIlqirKgr4/QgghoUcu0l9//XWHdVp4CIMGDbLf1xf9AwcOdFgnQkgu2lNSUtS6rl27OiQZiZgSQ8C6devcCiMpXdMQS5cuxdChQx3GZkYsRuLG++6771SclJTGKSsro8Uo1IhvVMp/792712G9PHZ3MoQTlVEURoQQ4g+tYqOV5SZU+/YWidUxW15ceROcCxe6WqddWr4i4/Ck1YY77rjjDvzyyy947rnn1PuR7c877zx7IHekE7HCSPyjonrFx6kDy+RkkceRYMqrRJzk3aG6kjFGhBDiCyIUvHVnNTfESiOlaXRi0V9//aXibaXjg68MGjRIdYo4cOCAS6uRxCZJULdOjBIL0tatW9FcCOvgaznYYtKTRdiyZYu6r811Eg/09ttvq0CyNWvW4J///KdK8Xf2wYYjVVHGVUA1LUaEENIikMznPXv2OCwSL+sPUsPv8ssvVwHSs2fPxk033aTilPzxnEyYMEH9vxgdRARt3rwZ//vf/+yJTRKj9Pnnn6v5WPYrQeL+WrHCibCW2hKFLz5ZjQ6MlpNAClZdeOGFKkDswQcfVCeYpC1KVL5zQLa3SN0kWSS4O1hUKYsRUFNJYUQIIS0BmZ+ysrIc1ollRycM+YK4ss455xyVJSYWHkn3f+211/z2yPz888+4/fbb1etKDJGUxNE1BaVUzlVXXaXKB0hYiwSKB6u8TSiIsgYj57CZIB+0pO1LTQgd6BYoNj46FL1qNmPlmPcwYPQ5AX1tQghpjkjgsXgOevTooSwlLR0JgJbaQ9qr0hIpd3NO+DN/h7UrrTlTHWWzGFUxxogQQggJFyiMQkSNLcaolsKIEEIICRsojEJEjcWol1TLrDRCCCE+utJashstWFAYhYhqi+FKs1ZTGBFCCCHhAoWRCyTyXiLwpTFesKiNtlmM6EojhBBCwgYKIxdMnDgRq1evVn1igkWt3WJUEbR9EEIIIcQ7KIxCRG20IYxAVxohhBASNlAYhQjtSgMtRoQQQkjYQGEUKmJshagojAghhJCwgcIoRFhtrrSoGgojQgghwW+4K1Wym4orrrjC3uA90qAwCrHFyEJhRAghLQLp6XnzzTer/mbSvkL6eh599NF4/fXXUVpaGpIxHXfccUo0uVuOO+44n173pZdeUj1NI5GwbiIbKpqiiSxijBgjCiNCCGn+SId6EUFpaWl44oknMHDgQMTHx2PFihV466230KlTJ5x55plNPq7PP/8clZWV6v6OHTtw2GGH4ddff8Whhx5qbyjrDTJviqCSPmWRCi1GIUrXj7JZjKJqjBOSEEJI8+X6669HTEwMFi5ciAsuuAD9+/dHz549MX78eHz33Xc444wz1Hbbt29X65KTk1XzU9l27969Dq8lFqZDDjlEiZa+ffvi3//+t8PzGzZswLHHHqusUlKT75dffnE7rrZt26JDhw5qycjIUOvatWunHq9du1bdz8/Pt28vlbZF+GzdulU9FquQiL2vv/5a7UvEnrwHZ1eaWJ5uuukm3HXXXfZ9SuVuM7K/UaNG2cctAq2pXYACLUYhIirWsBhF19JiRAghPmG1AlWhcUEhNlECdzzadP/+/fj555+VpSgpKcnlNiIAamtr7aJo5syZqK6uVhfqF154IX7//Xe13RdffKHccS+++CLGjh2Lb7/9FldeeSU6d+6MMWPGqNc455xzlJtu3rx5qrv8LbfcgmBSWlqKp59+Gu+8844SUpmZmS63e//993Hbbbepcc2dO1eJJ7GinXjiicrSJEKqa9eu6vmioiLcfvvtCAUURiFCW4yia2kxIoQQnxBR9ETH0Oz7vl1AnGuR48zGjRthtVqVdcdMeno6ysuNWnYigEToiGtty5Yt6NKli1r/wQcfKLeWeDCkG8Nzzz2nBIVYoAQRGn/99ZdaL8JIrCxiefnpp5/QsaNxbESQjRs3DsGiqqoKr732GgYPHtzgdoMGDcJDDz2k7vfu3Ruvvvoqpk+froSRWLU2bdqkBKBYk4THH39cPdfU0JUWIiyxWhjRYkQIIS2R+fPnK9eUCJ+KigqsWbNGCSItigRxKYmrSp4T5FasLGbksfl5+X8tioQjjzzSYXsRSWKVkkXHEvlDXFycEj2N4bxNVlYWcnNz1f1169apcWtRJEi8UyigxShERMdpYVQV6qEQQkhkIu4ssdyEat8eIllo4iqTyd+MxBgJrVq1QlMiLq+ysjJ1PzY21u12FothOxFrl9k65IyMX95fYzjvS7sPww1ajEKExRZjFGulK40QQnxCJmNxZ4Vi8TC+SJC4G3EJieuopKTE7XYSkC2ZYbJoJBFIgp/FcqS3mTNnjsP/yWPz8/L/u3fvtj8vrjYzkgEnYk2Wbt26uR1Phi0Y2/xaYuEKBuJmlHGbA82DmQDVEBRGISI6zrjaiKEwIoSQZo/E4Egw9YgRI/DJJ58ol5dYkP7zn/+omKDo6GgVYyRp/JdccgkWL16sXG2XXXYZRo8erf5PuPPOO1UmmGSmSfbZpEmTVMr9HXfcoZ6X1+jTpw8uv/xyLFu2DLNnz8b999/v05h79eql3FuSPSb7kuy5559/HsFAhKNk2sm4ly9frsTev/71L/WcJ9aoQEJhFGJXGi1GhBDS/JFJf8mSJUq43HvvvSpQWcTOK6+8okTNo48+qgTAV199hTZt2qh0e9lW3G0ipDSSuSXFEyXYWuKD3nzzTbz33nv2Qozi/pLMNXGVSYzO1VdfrYKYfSE2NhYfffSREm4SHySZZ4899hiCgQhDScsvLi5WQeYybi3oJH2/KYmymp2HpF6Bx/Xr16t0R6knEUjWLZ+Hvp+fhANIRduHtwf0tQkhpDkiGVySsdWjR48mnyxJ0yNWI6lrJFl9Iiy9OScKCwtVkUlf5m8GX7tA0iZl0Qc2GMTYLEZxYPA1IYQQ8sUXX6hMOUnlFzEk9Zok486dKAoWFEYhIjbeyEKIoyuNEEIIgRR1vPvuu1XlbKnxJK7EYMU0NQSFUaiFUVQ1IOmKtrRIQgghpCVy2WWXqSXUcDYOEXEJdTUwrNVG5VNCCCGEhBYKoxARG18XJFZZSWFECCGewpwhEsxzgcIoRMTHxaPWatRmqCwPURNEQgiJIHTlZGlaSoj5XGiogre3MMYoRMTFRKMcsWiFSlRVGKXZCSGENFzrRvqG6f5aiYmJTV78j4SPpUhEkZwLck7IuREoKIxChHyZKyiMCCHEK3STUS2OSMsmLS3NofFsIKAwaqTAYzCpgmH6q2aMESGEeHxRKV3ZMzMzXTY0JS2H2NjYgFqKNBRGISrwKFRGxalbWowIIcQ7ZEIMxqRICIOvQ0hVlGExqqmkMCKEEELCAQqjEFJlsxhRGBFCCCHhAYVRCKm2C6OKUA+FEEIIIRRGYSKMqhh8TQghhIQDFEYhpNpiCKPaKrrSCCGEkHCAwiiE1NiFES1GhBBCSDhAYRRCau3CiDFGhBBCSDhAYRQGFiNU02JECCGEhAMURiGkNjpB3VppMSKEEELCAgqjEFIbTYsRIYQQEk5QGLlA+qRlZ2dj5MiRQd2PNTreuFNDixEhhBASDlAYuUD6pK1evRoLFiwI6n6sMYYwiqqmMCKEEELCAQqjUGKLMYqixYgQQggJCyiMQoi2GFkojAghhJCwgMIohERpV1pNZaiHQgghhBAKo9ASFUuLESGEEBJOUBiFEEuMEWMUXUuLESGEEBIOUBiFkKhYLYxoMSKEEELCAQqjEGKxC6OqUA+FEEIIIRRG4SGMYqy0GBFCCCHhAIVRCImOswkjxhgRQgghYQGFUQiJjmulbmOtFEaEEEJIOEBhFEJitMUIjDEihBBCwgEKozCwGMVZKYwIIYSQcIDCKITEaGEEutIIIYSQcIDCKITEJmhhVA3U1oZ6OIQQQkiLh8LIBZMnT0Z2djZGjhwZ1P3E2tL1FeyXRgghhIQcCiMXTJw4EatXr8aCBQuCup+4VobFSLBWlwV1X4QQQghpHAqjEBIfm4Baa5S6X1VRHurhEEIIIS0eCqMQEh8XjQrEqvtVFbQYEUIIIaGGwiiExEVbUIkYdb+SwogQQggJORRGIcRiiUIF4tT96koKI0IIISTUUBiFmErtSiunMCKEEEJCDYVRiKmKMixGNVUURoQQQkiooTAKMVVRhsWoprIi1EMhhBBCWjwURmFiMaquLA31UAghhJAWD4VRiKnWrrRK1jEihBBCQg2FUYiptugYIwojQgghJNRQGIWYGpvFyFrFGCNCCCEk1FAYhZgam8WolhYjQgghJORQGIWYmuh4dWulMCKEEEJCDoVRiKm1WYys1RRGhBBCSKihMAoxtdGGMEI1Y4wIIYSQUENhFGKs0QnGLYURIYQQEnIojEJMrS3GKIquNEIIISTkUBiFmhibMKqhxYgQQggJNRRGocYWYxRVUxnqkRBCCCEtHgqjUBNjxBjRYkQIIYSEHgojF0yePBnZ2dkYOXJkk7nSoimMCCGEkJBDYeSCiRMnYvXq1ViwYEHQ9xUV20rdWmopjAghhJBQQ2EUYix2i1FVqIdCCCGEtHgojEJMVKwRYxRNixEhhBASciiMQowlziaMrMxKI4QQQkINhVGIsdgsRjG1FEaEEEJIqKEwCjExNotRDC1GhBBCSMihMAox0XFGVlqslcHXhBBCSKihMAoTi1EsLUaEEEJI5AmjzZs3B2ckLdxiFAcKI0IIISTihFGvXr0wZswY/Oc//0F5OTvC+0tsvGExikM1YLWGejiEEEJIi8ZrYbR48WIMGjQIt912Gzp06IDrrrsO8+fPD87oWgCx8YbFSFHNWkaEEEJIRAmjIUOG4KWXXsKuXbswZcoU7N69G6NGjcKAAQMwadIk5OXlBWekzZS4+MS6B9W0wBFCCCERGXwdExODc845B9OmTcPTTz+NjRs34o477kCXLl1w2WWXKcFEGicuLh611ijjAS1GhBBCSGQKo4ULF+L6669HVlaWshSJKNq0aRN++eUXZU0aP358YEfaTImPjUYlYtT96sqyUA+HEEIIadEYM7IXiAh67733sG7dOpx66qn44IMP1K3FYmisHj16YOrUqejevXswxtvsiIuxoAKxSEAVKivKvP9ACCGEEBIwvJ6HX3/9dVx11VW44oorlLXIFZmZmXj33XcDMb5mT1y0BcWIA1CK6gpajAghhJCIEkbiKuvatavdQqSxWq3YsWOHei4uLg6XX355IMfZbImJNixGQhWFESGEEBJZMUaHHHII9u3bV2/9gQMHlBuNeE+VTRhVVzIrjRBCCIkoYSSWIVcUFxcjIcEoVki8oypKCyNajAghhJCIcKVJQUchKioKDz74IBIT6+rv1NTUYN68earGEfGeqqg4wEphRAghhESMMFqyZIndYrRixQoVR6SR+4MHD1Yp+8R3YVRDVxohhBASGcJoxowZ6vbKK69Ula9TUlKCOa4WRY0II7mtYoFHQgghJKKy0qSGEQksVZY4oAaoraIrjRBCCAl7YSStP6Roo1iJ5H5DfP7554EaW4uhRoQRgFq60gghhJDwF0apqakq6FrfJ4GlxhKvbq1sIksIIYSEvzAyu8/oSgs8tTaLkZUxRoQQQkhkNpElgaM2mhYjQgghJGIsRkOHDrW70hpj8eLF/o6pxVEbbSt9UE2LESGEEBL2wuiss84K/khaMFabxSiKFiNCCCEk/IXRQw89FPyRtGC0MEJNZaiHQgghhLRoWkSM0dlnn402bdrgvPPOQ1iiLUY1dKURQgghYS+M2rZti3379qn7IjDksbslHLn55pvxwQcfIFyxxmhXGoURIYQQEvautBdeeAGtW7dW91988UVEGscddxx+//13hC0xCerGQosRIYQQEv7C6PLLL3d5PxDMmjULzz77LBYtWoTdu3fjiy++qBfsPXnyZLXNnj17VLPaV155BYcddhiaC1GxhsXIUssYI0IIISSieqUJNTU1SsCsWbNGPc7Ozsb48eMRE+P9y5WUlCixc9VVV7lsN/LJJ5/gtttuwxtvvIHDDz9cWaxOPvlkrFu3DpmZmWqbIUOGoLq6ut7//vzzz+jYsSPCnShtMaqlxYgQQggJJV4rmVWrVuHMM89U1pu+ffuqdU8//TQyMjLwzTffYMCAAV693rhx49TijkmTJuGaa67BlVdeqR6LQPruu+8wZcoU3HPPPWrd0qVLEQgqKirUoiksLERTEBVrCKNoZqURQgghkZWVdvXVV+PQQw9FTk6OKuYoy44dOzBo0CBce+21AR1cZWWlcrGNHTu2bsAWi3o8d+5cBJonn3xS9YLTS5cuXdAUWGzCKMZKixEhhBASUcJIrDMiICQ7TSP3H3/8cSxZsiSgg5NMOHHbtW/f3mG9PBaLlaeIkDr//PPx/fffo3Pnzm5F1b333ouCggL7IoKvKYjWFqPaqibZHyGEEEIC5Err06cP9u7dq6xGZnJzc9GrVy+EI7/++qtH28XHx6ulqbHEaYsRXWmEEEJI2FuMJNZGL2Ituummm/DZZ58pd5oscv+WW25RsUaBJD09HdHR0UqImZHHHTp0QHMh2iaMYpmVRgghhIS/xSgtLc2hiazVasUFF1xgXyePhTPOOEO5vgJFXFwchg8fjunTp9tT+Gtra9XjG264Ac2FmLhW6jYWFEaEEEJI2AujGTNmBG0AxcXF2Lhxo/3xli1bVByTVNHu2rWrStWX2kkjRoxQtYskXV9S/HWWWrOyGFkZY0QIIYSEvTAaPXp00AawcOFCjBkzxv5YhJAgYmjq1Km48MILkZeXhwcffFAFXEvNoh9//LFeQHYgkYKSsgTS+tUQsTaLURyqxPwGmKxzhBBCCGk6oqzaD+YlpaWl2L59u0qpNyNp+80FiamStH3JUEtJSQnaflZvyUH2+7Zg9vv3ArYsNUIIIYQ07fztdVaaWG/EjfXDDz+4fL6prCzNidh4w2KkqC6nMCKEEEIipY6RZJ/l5+dj3rx5aNWqlXJrvf/+++jduze+/vrr4IyymRMXZyoRwOrXhBBCSMjw2mL022+/4auvvlLB0FKFulu3bjjxxBOVqUpS+U877bTgjLQZEx8bg3JrLBKiqgyLESGEEEIiw2IkGWG6eatUvBbXmjBw4EDVHoR4T1yMBRWIVfdrKimMCCGEkIgRRtI4VjrbC4MHD8abb76JnTt3quauWVlZaA5IRlp2djZGjhzZJPuLV8IoTt2vqihrkn0SQgghJACutJtvvhm7d+9W9x966CGccsop+PDDD1UxRkmvbw5MnDhRLTqqvSksRgdtH0VVZRkYek0IIYREiDD629/+Zr8vVam3bduGtWvXqmKM0sKDeE+MJQoV1lggCqimxYgQQgiJHGFkRkogSWbasGHDAjeiFoi0VqmMoiuNEEIIibgYI+Hdd9/FgAEDkJCQoBa5/8477wR+dC2IKpswqmbwNSGEEBI5FiNpzTFp0iTceOONOPLII9W6uXPn4tZbb1WVsB955JFgjLPZUx0VC1iBmioKI0IIISRihNHrr7+Ot99+GxMmTLCvO/PMM1UrEBFLFEZ+WIxEGFXSlUYIIYREjCutqqpKFXd0RgKxq6urAzWuFke1xXCl1dKVRgghhESOMLr00kuV1ciZt956C5dccgmaA01dx0iojjLagtTSlUYIIYSEtyvttttuc8igkkDrn3/+GUcccYRaJ33TJL7osssuQ3OgqesYCbUWo/J1bVVFk+yPEEIIIT4KoyVLltRzmwmbNm1St1K/SJZVq1Z58nLEBTUWw2JkZa80QgghJLyF0YwZM4I/khZObbQRY2StZvA1IYQQElF1jDQ5OTlqIYGzGIGuNEIIISRyhFFtba1KyZfYm27duqklLS0Njz76qHqO+IY1xrAYga40QgghJHLqGN1///2q8vVTTz2Fo48+Wq37448/8PDDD6O8vByPP/54MMbZ7KmJTlS30VXFoR4KIYQQ0mLxWhi9//77KitNijpqpLhjp06dcP3111MY+UhxfHt1m1i2J9RDIYQQQlosXrvSDhw4gH79+tVbL+vkueZAKOoYFSd0VLfJ5buabJ+EEEII8VMYDR48GK+++mq99bJOnmsOSA2j1atXY8GCBU22z9JEmzCqzAVqa5psv4QQQgjxw5X2zDPP4LTTTsOvv/7q0ER2x44d+P777719OWKjslUGqqzRiEUNULQbSO0c6iERQgghLQ6vLUajR4/G+vXrcfbZZyM/P18t55xzDtatW4djjjkmOKNsAcTFxmG3ta3xIH9HqIdDCCGEtEhivG0ge8opp+CNN95gkHWASUuMxU5rBroiDygQYWRY4wghhBASphaj2NhYLF++PHijacGkJ8djJ9KNB/nbQj0cQgghpEXitSvtb3/7m6pjRAJLenIccqxaGNGVRgghhERE8HV1dTWmTJmigq+lmWxSUpLD85Mm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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"line_emp, = plt.semilogy(emp_timeseries, label=\"Empirical\")\n",
"line_gt, = plt.semilogy(gt_timeseries, label=\"Good-Turing\")\n",
"plt.legend(handles=[line_emp, line_gt])\n",
"plt.xticks(range(0, measurements + 1, int(measurements / 5)),\n",
" range(0, trials + 1, int(trials / 5))) # type: ignore\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('discovery probability')\n",
"plt.title('Discovery Probability Over Time');"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Again, the Good-Turing estimate appears to be *highly accurate*. In fact, the empirical estimator has a much lower precision as indicated by the large swings. You can try and increase the number of repetitions (`repeats`) to get more precision for the empirical estimates, however, at the cost of waiting much longer."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Discovery Probability Quantifies Residual Risk\n",
"\n",
"Alright. You have gotten a hold of a couple of powerful machines and used them to fuzz a software system for several months without finding any vulnerabilities. Is the system vulnerable?\n",
"\n",
"Well, who knows? We cannot say for sure; there is always some residual risk. Testing is not verification. Maybe the next test input that is generated reveals a vulnerability.\n",
"\n",
"Let's say *residual risk* is the probability that the next test input reveals a vulnerability that has not been found, yet. Böhme \\cite{Boehme2018stads} has shown that the Good-Turing estimate of the discovery probability is also an estimate of the maximum residual risk."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"**Proof sketch (Residual Risk)**. Here is a proof sketch that shows that an estimator of discovery probability for an arbitrary definition of species gives an upper bound on the probability to discover a vulnerability when none has been found: Suppose, for each \"old\" species A (here, execution trace), we derive two \"new\" species: Some inputs belonging to A expose a vulnerability while others belonging to A do not. We know that _only_ species that do not expose a vulnerability have been discovered. Hence, _all_ species exposing a vulnerability and _some_ species that do not expose a vulnerability remain undiscovered. Hence, the probability to discover a new species gives an upper bound on the probability to discover (a species that exposes) a vulnerability. **QED**."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"An estimate of the discovery probability is useful in many other ways.\n",
"\n",
"1. **Discovery probability**. We can estimate, at any point during the fuzzing campaign, the probability that the next input belongs to a previously unseen species (here, that it yields a new execution trace, i.e., exercises a new set of statements).\n",
"2. **Complement of discovery probability**. We can estimate the proportion of *all* inputs the fuzzer can generate for which we have already seen the species (here, execution traces). In some sense, this allows us to quantify the *progress of the fuzzing campaign towards completion*: If the probability to discovery a new species is too low, we might as well abort the campaign.\n",
"3. **Inverse of discovery probability**. We can predict the number of test inputs needed, so that we can expect the discovery of a new species (here, execution trace)."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## How Do We Know When to Stop Fuzzing?\n",
"\n",
"In fuzzing, we have measures of progress such as [code coverage](Coverage.ipynb) or [grammar coverage](GrammarCoverageFuzzer.ipynb). Suppose, we are interested in covering all statements in the program. The _percentage_ of statements that have already been covered quantifies how \"far\" we are from completing the fuzzing campaign. However, sometimes we know only the _number_ of species $S(n)$ (here, statements) that have been discovered after generating $n$ fuzz inputs. The percentage $S(n)/S$ can only be computed if we know the _total number_ of species $S$. Even then, not all species may be feasible."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### A Success Estimator\n",
"\n",
"If we do not _know_ the total number of species, then let us at least _estimate_ it: As we have seen before, species discovery slows down over time. In the beginning, many new species are discovered. Later, many inputs need to be generated before discovering the next species. In fact, given enough time, the fuzzing campaign approaches an _asymptote_. It is this asymptote that we can estimate."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"In 1984, Anne Chao, a well-known theoretical bio-statistician, has developed an estimator $\\hat S$ which estimates the asymptotic total number of species $S$:\n",
"\\begin{align}\n",
"\\hat S_\\text{Chao1} = \\begin{cases}\n",
"S(n) + \\frac{f_1^2}{2f_2} & \\text{if $f_2>0$}\\\\\n",
"S(n) + \\frac{f_1(f_1-1)}{2} & \\text{otherwise}\n",
"\\end{cases}\n",
"\\end{align}\n",
"* where $f_1$ and $f_2$ is the number of singleton and doubleton species, respectively (that have been observed exactly once or twice, resp.), and \n",
"* where $S(n)$ is the number of species that have been discovered after generating $n$ fuzz inputs."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"So, how does Chao's estimate perform? To investigate this, we generate `trials=400000` fuzz inputs using a fuzzer setting that allows us to see an asymptote in a few seconds: We measure trace coverage. After half-way into our fuzzing campaign (`trials`/2=100000), we generate Chao's estimate $\\hat S$ of the asymptotic total number of species. Then, we run the remainder of the campaign to see the \"empirical\" asymptote."
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:03:37.869199Z",
"iopub.status.busy": "2025-10-26T18:03:37.868715Z",
"iopub.status.idle": "2025-10-26T18:04:40.934908Z",
"shell.execute_reply": "2025-10-26T18:04:40.933813Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"trials = 400000\n",
"fuzzer = RandomFuzzer(min_length=2, max_length=4,\n",
" char_start=32, char_range=32)\n",
"population = []\n",
"for i in range(trials):\n",
" population.append(fuzzer.fuzz())\n",
"\n",
"_, trace_ts, f1_ts, f2_ts = population_trace_coverage(population, my_parser)"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.941072Z",
"iopub.status.busy": "2025-10-26T18:04:40.940847Z",
"iopub.status.idle": "2025-10-26T18:04:40.947856Z",
"shell.execute_reply": "2025-10-26T18:04:40.947124Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"200000"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"time = int(trials / 2)\n",
"time"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.950460Z",
"iopub.status.busy": "2025-10-26T18:04:40.950271Z",
"iopub.status.idle": "2025-10-26T18:04:40.953173Z",
"shell.execute_reply": "2025-10-26T18:04:40.952628Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"f1 = f1_ts[time]\n",
"f2 = f2_ts[time]\n",
"Sn = trace_ts[time]\n",
"if f2 > 0:\n",
" hat_S = Sn + f1 * f1 / (2 * f2)\n",
"else:\n",
" hat_S = Sn + f1 * (f1 - 1) / 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"After executing `time` fuzz inputs (half of all), we have covered this many traces:"
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.956465Z",
"iopub.status.busy": "2025-10-26T18:04:40.956300Z",
"iopub.status.idle": "2025-10-26T18:04:40.959183Z",
"shell.execute_reply": "2025-10-26T18:04:40.958765Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"200000"
]
},
"execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"time"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.962301Z",
"iopub.status.busy": "2025-10-26T18:04:40.962184Z",
"iopub.status.idle": "2025-10-26T18:04:40.965351Z",
"shell.execute_reply": "2025-10-26T18:04:40.964687Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"text/plain": [
"66"
]
},
"execution_count": 79,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Sn"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can estimate there are this many traces in total:"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.967743Z",
"iopub.status.busy": "2025-10-26T18:04:40.967585Z",
"iopub.status.idle": "2025-10-26T18:04:40.970261Z",
"shell.execute_reply": "2025-10-26T18:04:40.969781Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"73.2"
]
},
"execution_count": 80,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"hat_S"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Hence, we have achieved this percentage of the estimate:"
]
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.972707Z",
"iopub.status.busy": "2025-10-26T18:04:40.972566Z",
"iopub.status.idle": "2025-10-26T18:04:40.975515Z",
"shell.execute_reply": "2025-10-26T18:04:40.975061Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"90.1639344262295"
]
},
"execution_count": 81,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"100 * Sn / hat_S"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"After executing `trials` fuzz inputs, we have covered this many traces:"
]
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.981241Z",
"iopub.status.busy": "2025-10-26T18:04:40.979586Z",
"iopub.status.idle": "2025-10-26T18:04:40.984194Z",
"shell.execute_reply": "2025-10-26T18:04:40.983644Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"400000"
]
},
"execution_count": 82,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"trials"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.988625Z",
"iopub.status.busy": "2025-10-26T18:04:40.988308Z",
"iopub.status.idle": "2025-10-26T18:04:40.992359Z",
"shell.execute_reply": "2025-10-26T18:04:40.991704Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/plain": [
"72"
]
},
"execution_count": 83,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"trace_ts[trials - 1]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The accuracy of Chao's estimator is quite reasonable. It isn't always accurate -- particularly at the beginning of a fuzzing campaign when the [discovery probability](WhenIsEnough.ipynb#Measuring-Trace-Coverage-over-Time) is still very high. Nevertheless, it demonstrates the main benefit of reporting a percentage to assess the progress of a fuzzing campaign towards completion.\n",
"\n",
"***Try it***. *Try setting `trials` to 1 million and `time` to `int(trials / 4)`.*"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Extrapolating Fuzzing Success\n",
"\n",
"\n",
"Suppose you have run the fuzzer for a week, which generated $n$ fuzz inputs and discovered $S(n)$ species (here, covered $S(n)$ execution traces). Instead, of running the fuzzer for another week, you would like to *predict* how many more species you would discover. In 2003, Anne Chao and her team developed an extrapolation methodology to do just that. We are interested in the number $S(n+m^*)$ of species discovered if $m^*$ more fuzz inputs were generated:\n",
"\n",
"\\begin{align}\n",
"\\hat S(n + m^*) = S(n) + \\hat f_0 \\left[1-\\left(1-\\frac{f_1}{n\\hat f_0 + f_1}\\right)^{m^*}\\right]\n",
"\\end{align}\n",
"* where $\\hat f_0=\\hat S - S(n)$ is an estimate of the number $f_0$ of undiscovered species, and \n",
"* where $f_1$ is the number of singleton species, i.e., those we have observed exactly once. \n",
"\n",
"The number $f_1$ of singletons, we can just keep track of during the fuzzing campaign itself. The estimate of the number $\\hat f_0$ of undiscovered species, we can simply derive using Chao's estimate $\\hat S$ and the number of observed species $S(n)$.\n",
"\n",
"Let's see how Chao's extrapolator performs by comparing the predicted number of species to the empirical number of species."
]
},
{
"cell_type": "code",
"execution_count": 84,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:40.995111Z",
"iopub.status.busy": "2025-10-26T18:04:40.994966Z",
"iopub.status.idle": "2025-10-26T18:04:41.076610Z",
"shell.execute_reply": "2025-10-26T18:04:41.075955Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"source": [
"prediction_ts: List[float] = [None] * time # type: ignore\n",
"f0 = hat_S - Sn\n",
"\n",
"for m in range(trials - time):\n",
" assert (time * f0 + f1) != 0 , 'time:%s f0:%s f1:%s' % (time, f0,f1)\n",
" prediction_ts.append(Sn + f0 * (1 - (1 - f1 / (time * f0 + f1)) ** m))"
]
},
{
"cell_type": "code",
"execution_count": 85,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:41.079347Z",
"iopub.status.busy": "2025-10-26T18:04:41.079174Z",
"iopub.status.idle": "2025-10-26T18:04:42.579995Z",
"shell.execute_reply": "2025-10-26T18:04:42.579626Z"
},
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAycAAADpCAYAAAA+o0jwAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAMTgAADE4Bf3eMIwAAVVVJREFUeJzt3Qd409X6B/C3e0PLKKPQsvfee4oCynAvloqIXq96cXsdKIobUa5enHCRvyhDUEFRWQICMmQjUMoq0EKhk+6R//M9IbGF0qZt0t/I9/M84Zedk9C8OeM953hYLBaLEBERERERacxT6wIQEREREREBGydERERERKQLbJwQEREREZEusHFCRERERES6wMYJERERERHpAhsnRERERESkC2ycEBERERGRLniLwfj5+UnNmjW1LgaR6SUkJEh2drYYBWMDUeVgbCAiV8YFwzVOEGBOnTqldTGITK9evXpiJIwNRJWDsYGIXBkXmNZFRERERES6wMYJERERERHpAhsnRERERESkC2ycEBERERGRLrBxQkREREREumC41bqIiIio7PLy8tRSn0FBQery7t275ejRo5KcnKyuu+2227QuIhFd5uLFi7J3714pKCiQypaTkyMeHh7SqVMnqVKlSqW9LhsnREREBoIGRlxcnJw/f14uXLigjjh5eXnJww8/rO7zf//3f/LRRx+phgdOKSkpkp6eLjfeeKN8++236j5vvPGGfP311+p827Zt2Tgh0qE//vhDNm7cWK7H5ufnS2Zmpnh7e4u/v7+6bv/+/arBgziSlZWlTjjft29fqV27tmRkZMiHH36orkOHxsiRI2XWrFnmaZwgaA4ePNh+GW8YvTTnzp1Tb3jcuHESExOjNkhCEO3Xr58ri0NEOsHYQPQ3VALQsEAFIi0tTRYsWCDx8fHqZGt44IRKSkBAgKxatUpuuOGGK56nbt269sYJGiT4ToWGhkpkZKRUrVpVne/evbv9/pMnT1bPg+tr1aolesDYQO7MYrGov3kcbRAT4O6771YjGdjsEN+HxMRE9T2vU6eO/Tvz9ttvy/r16yUpKUmd0CkB//73v2XixInqfM+ePSU2NvaK137iiSdkyJAh6jXWrl0rISEhqkFyxx13VHp8cGnjpHr16rJr1y775XfeeUd+++03qVatmtx7773So0cPWblypWzbtk315hw7dkx8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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(num=None, figsize=(12, 3), dpi=80, facecolor='w', edgecolor='k')\n",
"plt.subplot(1, 3, 1)\n",
"plt.plot(trace_ts, color='white')\n",
"plt.plot(trace_ts[:time])\n",
"plt.xticks(range(0, trials + 1, int(time)))\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of traces exercised')\n",
"\n",
"plt.subplot(1, 3, 2)\n",
"line_cur, = plt.plot(trace_ts[:time], label=\"Ongoing fuzzing campaign\")\n",
"line_pred, = plt.plot(prediction_ts, linestyle='--',\n",
" color='black', label=\"Predicted progress\")\n",
"plt.legend(handles=[line_cur, line_pred])\n",
"plt.xticks(range(0, trials + 1, int(time))) # type: ignore\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of traces exercised')\n",
"\n",
"plt.subplot(1, 3, 3)\n",
"line_emp, = plt.plot(trace_ts, color='grey', label=\"Actual progress\")\n",
"line_cur, = plt.plot(trace_ts[:time], label=\"Ongoing fuzzing campaign\")\n",
"line_pred, = plt.plot(prediction_ts, linestyle='--',\n",
" color='black', label=\"Predicted progress\")\n",
"plt.legend(handles=[line_emp, line_cur, line_pred])\n",
"plt.xticks(range(0, trials + 1, int(time))) # type: ignore\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of traces exercised');"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The prediction from Chao's extrapolator looks quite accurate. We make a prediction at `time=trials/4`. Despite an extrapolation by 3 times (i.e., at trials), we can see that the predicted value (black, dashed line) closely matches the empirical value (gray, solid line).\n",
"\n",
"***Try it***. Again, try setting `trials` to 1 million and `time` to `int(trials / 4)`."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": true,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Lessons Learned\n",
"\n",
"* One can measure the _progress_ of a fuzzing campaign (as species over time, i.e., $S(n)$).\n",
"* One can measure the _effectiveness_ of a fuzzing campaign (as asymptotic total number of species $S$).\n",
"* One can estimate the _effectiveness_ of a fuzzing campaign using the Chao1-estimator $\\hat S$.\n",
"* One can extrapolate the _progress_ of a fuzzing campaign, $\\hat S(n+m^*)$.\n",
"* One can estimate the _residual risk_ (i.e., the probability that a bug exists that has not been found) using the Good-Turing estimator $GT$ of the species discovery probability."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Next Steps\n",
"\n",
"This chapter is the last in the book! If you want to continue reading, have a look at the [Appendices](99_Appendices.ipynb). Otherwise, _make use of what you have learned and go and create great fuzzers and test generators!_"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Background\n",
"\n",
"* A **statistical framework for fuzzing**, inspired from ecology. Marcel Böhme. [STADS: Software Testing as Species Discovery](https://mboehme.github.io/paper/TOSEM18.pdf). ACM TOSEM 27(2):1--52\n",
"* Estimating the **discovery probability**: I.J. Good. 1953. [The population frequencies of species and the\n",
"estimation of population parameters](https://www.jstor.org/stable/2333344). Biometrika 40:237–264.\n",
"* Estimating the **asymptotic total number of species** when each input can belong to exactly one species: Anne Chao. 1984. [Nonparametric estimation of the number of classes in a population](https://www.jstor.org/stable/4615964). Scandinavian Journal of Statistics 11:265–270\n",
"* Estimating the **asymptotic total number of species** when each input can belong to one or more species: Anne Chao. 1987. [Estimating the population size for capture-recapture data with unequal catchability](https://www.jstor.org/stable/2531532). Biometrics 43:783–791\n",
"* **Extrapolating** the number of discovered species: Tsung-Jen Shen, Anne Chao, and Chih-Feng Lin. 2003. [Predicting the Number of New Species in Further Taxonomic Sampling](http://chao.stat.nthu.edu.tw/wordpress/paper/2003_Ecology_84_P798.pdf). Ecology 84, 3 (2003), 798–804."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": true,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Exercises\n",
"I.J. Good and Alan Turing developed an estimator for the case where each input belongs to exactly one species. For instance, each input yields exactly one execution trace (see function [`getTraceHash`](#Trace-Coverage)). However, this is not true in general. For instance, each input exercises multiple statements and branches in the source code. Generally, each input can belong to one *or more* species. \n",
"\n",
"In this extended model, the underlying statistics are quite different. Yet, all estimators that we have discussed in this chapter turn out to be almost identical to those for the simple, single-species model. For instance, the Good-Turing estimator $C$ is defined as \n",
"$$C=\\frac{Q_1}{n}$$ \n",
"where $Q_1$ is the number of singleton species and $n$ is the number of generated test cases.\n",
"Throughout the fuzzing campaign, we record for each species the *incidence frequency*, i.e., the number of inputs that belong to that species. Again, we define a species $i$ as *singleton species* if we have seen exactly one input that belongs to species $i$."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
},
"solution2": "shown",
"solution2_first": true
},
"source": [
"### Exercise 1: Estimate and Evaluate the Discovery Probability for Statement Coverage\n",
"\n",
"In this exercise, we create a Good-Turing estimator for the simple fuzzer."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
},
"solution2": "shown",
"solution2_first": true
},
"source": [
"#### Part 1: Population Coverage\n",
"\n",
"Implement a function `population_stmt_coverage()` as in [the section on estimating discovery probability](#Estimating-the-Discovery-Probability) that monitors the number of singletons and doubletons over time, i.e., as the number $i$ of test inputs increases."
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.582182Z",
"iopub.status.busy": "2025-10-26T18:04:42.582050Z",
"iopub.status.idle": "2025-10-26T18:04:42.583720Z",
"shell.execute_reply": "2025-10-26T18:04:42.583404Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden",
"solution2_first": true
},
"outputs": [],
"source": [
"from Coverage import population_coverage\n",
"..."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"**Solution.** Here we go:"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.585142Z",
"iopub.status.busy": "2025-10-26T18:04:42.585050Z",
"iopub.status.idle": "2025-10-26T18:04:42.588097Z",
"shell.execute_reply": "2025-10-26T18:04:42.587588Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"def population_stmt_coverage(population, function):\n",
" cumulative_coverage = []\n",
" all_coverage = set()\n",
" cumulative_singletons = []\n",
" cumulative_doubletons = []\n",
" singletons = set()\n",
" doubletons = set()\n",
"\n",
" for s in population:\n",
" with Coverage() as cov:\n",
" try:\n",
" function(s)\n",
" except BaseException:\n",
" pass\n",
" cur_coverage = cov.coverage()\n",
"\n",
" # singletons and doubletons\n",
" doubletons -= cur_coverage\n",
" doubletons |= singletons & cur_coverage\n",
" singletons -= cur_coverage\n",
" singletons |= cur_coverage - (cur_coverage & all_coverage)\n",
" cumulative_singletons.append(len(singletons))\n",
" cumulative_doubletons.append(len(doubletons))\n",
"\n",
" # all and cumulative coverage\n",
" all_coverage |= cur_coverage\n",
" cumulative_coverage.append(len(all_coverage))\n",
"\n",
" return all_coverage, cumulative_coverage, cumulative_singletons, cumulative_doubletons"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
},
"solution2": "shown",
"solution2_first": true
},
"source": [
"#### Part 2: Population\n",
"\n",
"Use the random `fuzzer(min_length=1, max_length=1000, char_start=0, char_range=255)` from [the chapter on Fuzzers](Fuzzer.ipynb) to generate a population of $n=10000$ fuzz inputs."
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {
"cell_style": "split",
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.590061Z",
"iopub.status.busy": "2025-10-26T18:04:42.589911Z",
"iopub.status.idle": "2025-10-26T18:04:42.591799Z",
"shell.execute_reply": "2025-10-26T18:04:42.591535Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden",
"solution2_first": true
},
"outputs": [],
"source": [
"from Fuzzer import RandomFuzzer\n",
"from html.parser import HTMLParser\n",
"...;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"**Solution.** This is fairly straightforward:"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {
"cell_style": "split",
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.593413Z",
"iopub.status.busy": "2025-10-26T18:04:42.593295Z",
"iopub.status.idle": "2025-10-26T18:04:42.594906Z",
"shell.execute_reply": "2025-10-26T18:04:42.594691Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"trials = 2000 # increase to 10000 for better convergences. Will take a while.."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"We create a wrapper function..."
]
},
{
"cell_type": "code",
"execution_count": 90,
"metadata": {
"cell_style": "split",
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.596640Z",
"iopub.status.busy": "2025-10-26T18:04:42.596516Z",
"iopub.status.idle": "2025-10-26T18:04:42.598169Z",
"shell.execute_reply": "2025-10-26T18:04:42.597945Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"def html_parser(inp):\n",
" parser = HTMLParser() # resets the HTMLParser object for every fuzz input\n",
" parser.feed(inp)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"... and a random fuzzer:"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {
"cell_style": "split",
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.599871Z",
"iopub.status.busy": "2025-10-26T18:04:42.599693Z",
"iopub.status.idle": "2025-10-26T18:04:42.601707Z",
"shell.execute_reply": "2025-10-26T18:04:42.601367Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"fuzzer = RandomFuzzer(min_length=1, max_length=1000,\n",
" char_start=0, char_range=255)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"We fill the population:"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {
"cell_style": "split",
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.603653Z",
"iopub.status.busy": "2025-10-26T18:04:42.603523Z",
"iopub.status.idle": "2025-10-26T18:04:42.925733Z",
"shell.execute_reply": "2025-10-26T18:04:42.924660Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"population = []\n",
"for i in range(trials):\n",
" population.append(fuzzer.fuzz())"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
},
"solution2": "hidden",
"solution2_first": true
},
"source": [
"#### Part 3: Estimating Probabilities\n",
"\n",
"Execute the generated inputs on the Python HTML parser (`from html.parser import HTMLParser`) and estimate the probability that the next input covers a previously uncovered statement (i.e., the discovery probability) using the Good-Turing estimator."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"**Solution.** Here we go:"
]
},
{
"cell_type": "code",
"execution_count": 93,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:42.930465Z",
"iopub.status.busy": "2025-10-26T18:04:42.930111Z",
"iopub.status.idle": "2025-10-26T18:04:43.336864Z",
"shell.execute_reply": "2025-10-26T18:04:43.336442Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"measurements = 100 # experiment measurements\n",
"step = int(trials / measurements)\n",
"\n",
"gt_timeseries = []\n",
"singleton_timeseries = population_stmt_coverage(population, my_parser)[2]\n",
"for i in range(1, trials + 1, step):\n",
" gt_timeseries.append(singleton_timeseries[i - 1] / i)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
},
"solution2": "hidden",
"solution2_first": true
},
"source": [
"#### Part 4: Empirical Evaluation\n",
"\n",
"Empirically evaluate the accuracy of the Good-Turing estimator (using $10000$ repetitions) of the probability to cover new statements using the experimental procedure at the end of [the section on estimating discovery probability](#Estimating-the-Discovery-Probability)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"**Solution.** This is as above:"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:43.339180Z",
"iopub.status.busy": "2025-10-26T18:04:43.339054Z",
"iopub.status.idle": "2025-10-26T18:04:43.340731Z",
"shell.execute_reply": "2025-10-26T18:04:43.340421Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"# increase to 10000 for better precision (less variance). Will take a while..\n",
"repeats = 100"
]
},
{
"cell_type": "code",
"execution_count": 95,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:43.342833Z",
"iopub.status.busy": "2025-10-26T18:04:43.342724Z",
"iopub.status.idle": "2025-10-26T18:04:51.441747Z",
"shell.execute_reply": "2025-10-26T18:04:51.386088Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"emp_timeseries = []\n",
"all_coverage = set()\n",
"for i in range(0, trials, step):\n",
" if i - step >= 0:\n",
" for j in range(step):\n",
" inp = population[i - j]\n",
" with Coverage() as cov:\n",
" try:\n",
" my_parser(inp)\n",
" except BaseException:\n",
" pass\n",
" all_coverage |= cov.coverage()\n",
"\n",
" discoveries = 0\n",
" for _ in range(repeats):\n",
" inp = fuzzer.fuzz()\n",
" with Coverage() as cov:\n",
" try:\n",
" my_parser(inp)\n",
" except BaseException:\n",
" pass\n",
" # If intersection not empty, a new stmt was (dis)covered\n",
" if cov.coverage() - all_coverage:\n",
" discoveries += 1\n",
" emp_timeseries.append(discoveries / repeats)"
]
},
{
"cell_type": "code",
"execution_count": 96,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:51.543439Z",
"iopub.status.busy": "2025-10-26T18:04:51.542800Z",
"iopub.status.idle": "2025-10-26T18:04:51.879590Z",
"shell.execute_reply": "2025-10-26T18:04:51.878150Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAHHCAYAAABTMjf2AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAbPpJREFUeJzt3Qd4U2XbB/B/9wDaUgqUQtkIsjeiIKAgICKCCCIq4Cv6CSqKk9dX8HWhvoKgIjhAcCPKUEFkyBKRvfcoUKBAGW1pS3e+635OT5qOdCY5afL/XdchyclJcnIacu7cz/08j4fJZDKBiIiIyA15Gr0DREREREZhIERERERui4EQERERuS0GQkREROS2GAgRERGR22IgRERERG6LgRARERG5LQZCRERE5LYYCBEREZHbYiBEVITXXnsNHh4eRu8GWZg7d676m2zbts1mz9m9e3c0b968yO1OnjypXlv2obDPSN26dTFy5Eib7Z87kuMnx5HInhgIkVueQPXF398fERER6N27Nz788ENcu3bN6F0s1ySYsDy+oaGh6NChA+bMmYOsrCy4swMHDqiASQIpe/jtt9/Qp08fVKlSRX2ub7jhBjz//PO4fPkynInl56OwZe3atUbvKrkJb6N3gMgIr7/+OurVq4f09HScP39efek+88wzmDp1Kn755Re0bNnSvO1//vMfvPzyy4bub3lSq1YtTJ48WV2PjY3FV199hX/96184cuQI3nnnHZR3derUwfXr1+Hj41PodocPH4anp2euQOi///2vChZtneWQgGfKlClo1aoVXnrpJRWA7tixAx9//DF++OEHrF69Go0bN4Yz+Prrr3Pdls/HypUr862/8cYb8fnnn7t9AE32x0CI3FLfvn3Rvn178+0JEybgzz//xF133YW7774bBw8eREBAgLrP29tbLa5M5l5OSUkxv+eyCA4OxoMPPmi+/fjjj6uTsJyU33jjjQIDCDnZpaWlqUyGs9MziUXx8/NzyP58//33KggaOnQovv32W3h5eeVqWurRowfuu+8+FRg58nOclJSEChUq5Ftv+dkQ//zzjwqE8q4nchQ2jRFlu+222/Dqq6/i1KlT+Oabbwqt/5Av7i5duiAkJAQVK1ZUJ/p///vfubaRwEIeK00UcuKsUaMGBg0ahOPHj+c6WTz33HOIjIxUJ055nvfff18FJjqp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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"line_emp, = plt.semilogy(emp_timeseries, label=\"Empirical\")\n",
"line_gt, = plt.semilogy(gt_timeseries, label=\"Good-Turing\")\n",
"plt.legend(handles=[line_emp, line_gt])\n",
"plt.xticks(range(0, measurements + 1, int(measurements / 5)),\n",
" range(0, trials + 1, int(trials / 5))) # type: ignore\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('discovery probability')\n",
"plt.title('Discovery Probability Over Time');"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "subslide"
},
"solution": "hidden",
"solution2": "shown",
"solution2_first": true,
"solution_first": true
},
"source": [
"### Exercise 2: Extrapolate and Evaluate Statement Coverage\n",
"\n",
"In this exercise, we use Chao's extrapolation method to estimate the success of fuzzing."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "subslide"
},
"solution": "hidden",
"solution2": "hidden",
"solution2_first": true,
"solution_first": true
},
"source": [
"#### Part 1: Create Population\n",
"\n",
"Use the random `fuzzer(min_length=1, max_length=1000, char_start=0, char_range=255)` to generate a population of $n=400000$ fuzz inputs."
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "skip"
},
"solution": "hidden",
"solution2": "hidden"
},
"source": [
"**Solution.** Here we go:"
]
},
{
"cell_type": "code",
"execution_count": 97,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:51.884480Z",
"iopub.status.busy": "2025-10-26T18:04:51.884171Z",
"iopub.status.idle": "2025-10-26T18:04:51.886568Z",
"shell.execute_reply": "2025-10-26T18:04:51.886049Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"trials = 400 # Use 400000 for actual solution. This takes a while!"
]
},
{
"cell_type": "code",
"execution_count": 98,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:51.888702Z",
"iopub.status.busy": "2025-10-26T18:04:51.888572Z",
"iopub.status.idle": "2025-10-26T18:04:52.081064Z",
"shell.execute_reply": "2025-10-26T18:04:52.079515Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"population = []\n",
"for i in range(trials):\n",
" population.append(fuzzer.fuzz())\n",
"\n",
"_, stmt_ts, Q1_ts, Q2_ts = population_stmt_coverage(population, my_parser)"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "subslide"
},
"solution": "hidden",
"solution2": "hidden",
"solution2_first": true,
"solution_first": true
},
"source": [
"#### Part 2: Compute Estimate\n",
"\n",
"Compute an estimate of the total number of statements $\\hat S$ after $n/4=100000$ fuzz inputs were generated. In the extended model, $\\hat S$ is computed as\n",
"\\begin{align}\n",
"\\hat S_\\text{Chao1} = \\begin{cases}\n",
"S(n) + \\frac{Q_1^2}{2Q_2} & \\text{if $Q_2>0$}\\\\\n",
"S(n) + \\frac{Q_1(Q_1-1)}{2} & \\text{otherwise}\n",
"\\end{cases}\n",
"\\end{align}\n",
" * where $Q_1$ and $Q_2$ is the number of singleton and doubleton statements, respectively (i.e., statements that have been exercised by exactly one or two fuzz inputs, resp.), and \n",
" * where $S(n)$ is the number of statements that have been (dis)covered after generating $n$ fuzz inputs."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"**Solution.** Here we go:"
]
},
{
"cell_type": "code",
"execution_count": 99,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:52.090638Z",
"iopub.status.busy": "2025-10-26T18:04:52.090217Z",
"iopub.status.idle": "2025-10-26T18:04:52.109615Z",
"shell.execute_reply": "2025-10-26T18:04:52.103249Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"After executing 100 fuzz inputs, we have covered 131 **(66.5 %)** statements.\n",
"After executing 100 fuzz inputs, we estimate there are 197 statements in total.\n",
"After executing 400 fuzz inputs, we have covered 158 statements.\n"
]
}
],
"source": [
"time = int(trials / 4)\n",
"Q1 = Q1_ts[time]\n",
"Q2 = Q2_ts[time]\n",
"Sn = stmt_ts[time]\n",
"\n",
"if Q2 > 0:\n",
" hat_S = Sn + Q1 * Q1 / (2 * Q2)\n",
"else:\n",
" hat_S = Sn + Q1 * (Q1 - 1) / 2\n",
"\n",
"print(\"After executing %d fuzz inputs, we have covered %d **(%.1f %%)** statements.\\n\" % (time, Sn, 100 * Sn / hat_S) +\n",
" \"After executing %d fuzz inputs, we estimate there are %d statements in total.\\n\" % (time, hat_S) +\n",
" \"After executing %d fuzz inputs, we have covered %d statements.\" % (trials, stmt_ts[trials - 1]))"
]
},
{
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "subslide"
},
"solution": "hidden",
"solution2": "hidden",
"solution2_first": true,
"solution_first": true,
"toc-hr-collapsed": false
},
"source": [
"#### Part 3: Compute and Evaluate Extrapolator\n",
"\n",
"Compute and evaluate Chao's extrapolator by comparing the predicted number of statements to the empirical number of statements."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"source": [
"**Solution.** Here's our solution:"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:52.118684Z",
"iopub.status.busy": "2025-10-26T18:04:52.118440Z",
"iopub.status.idle": "2025-10-26T18:04:52.148966Z",
"shell.execute_reply": "2025-10-26T18:04:52.146594Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [],
"source": [
"prediction_ts: List[float] = [None] * time # type: ignore\n",
"Q0 = hat_S - Sn\n",
"\n",
"for m in range(trials - time):\n",
" prediction_ts.append(Sn + Q0 * (1 - (1 - Q1 / (time * Q0 + Q1)) ** m))"
]
},
{
"cell_type": "code",
"execution_count": 101,
"metadata": {
"execution": {
"iopub.execute_input": "2025-10-26T18:04:52.153406Z",
"iopub.status.busy": "2025-10-26T18:04:52.153240Z",
"iopub.status.idle": "2025-10-26T18:04:52.330266Z",
"shell.execute_reply": "2025-10-26T18:04:52.328607Z"
},
"slideshow": {
"slide_type": "skip"
},
"solution2": "hidden"
},
"outputs": [
{
"data": {
"image/png": "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JcSA2mAu1AViRagLoacNIZXUXrRoUTly5IjExsbq/whZg9UGK9Tu47fysQ0fPlymT58uv/32m2TLlk3y5s2rXoCjR4+6H7N3714da0r3WYXu3bur16NIkSK2Oh9LlizR9xKJZvBYrFixQnr27ClTp0619fnwFyueq1DQBUBtMP+cUBeSx2rnKlS0gbogljgfaa4NrhADMXCeSUN33nmny8pcn6CW0viteGwfffSRq3r16q7Tp08n2t69e/dESU+FChVyJz2ldJ9ZyWmHDh1y/48YSiRpIcbTbufDE894UDudj2Bg9XPlNF0A1AbrnRNAXUiMlc+VE7WBujA+yftCQRtCziDZunWrVgooU6aMnuwNGza4rEjPnj31A5whQwZX/vz5XaVKlbrp+K12bKj4AZu3ZMmSmtCFS61atfS+o0ePupo1a+YqXbq0q2LFiq758+e7n5fSfWawd+9eTcqqVKmSVspAgpch+HY6HymJi53ORzCw+rlyki4AaoP1zokBdSExVj5XTtMG6sJWS52PtNaGdPgTrOUeQgghhBBCCEmJkMohIYQQQgghhFgLGiSEEEIIIYQQ06BBQgghhBBCCDENGiSEEEIIIYQQ06BBQgghhBBCCDENGiQOZ/fu3dKkSRO93aFDB/nnn3982s8TTzwhFStWlAcffPCG+9Asp3LlynLHHXfI77//LsFizJgx8uGHHwZt/2fPnpX33nsvaPsnxCpQF7yHukBCCWqD91AbAgvL/jqcsWPHyunTp6V///5Srlw52b59u6RPnzo79NixY1KyZEk5f/68ZMiQ4Yb7e/furV04X331VbEz6CZarVo1FRlCnAx1wXuoCySUoDZ4D7UhwASpfwoxmTFjxrjuuusuV548ebQ5Dy64jW0TJ05M8jnYXrlyZb20atXKdfDgQe04WqFCBVf69Om1SdG7776b6Dn4/5ZbbtFOnLgfj7++Uywa/CxYsMB17Ngxd7MjXPLmzevq0aOHPtZze44cOVyDBg26YXzo/Pn888/rbXQzRbOhjh076rHhNXbt2qX34bVuv/12V9euXfUaXV+N8eA+vIbBxo0bdbygRYsW7uM0OqQOGTLEVb58effY0PCIELtCXaAuEJIU1AZqg9nQIHE46NYaExPjGjVqlGvkyJHJPg5fsgIFCqiggKFDh7patmypt/fs2ePKlStXss/t3r17on0nJy6ebNq0SR+H1/UEHT0xZmMcKYlLzpw5Xbt379b/BwwYoJ1qAV4Ltva8efP0/ylTprjKlSvnio+PT1Fcrj/O06dP6/+XL1/W/y9duuSKjIxM9n0gxC5QF6gLhCQFtYHaYBbMIXEwBw8elPz580tYWJisXbtW7rzzzmQfu2DBAmnZsqUULlxY/+/Tp4/Mnz9f4uLiAj6uw4cPS9u2beXrr7+WSpUqubdv2rRJHnvsMZk5c6Z7HClRp04dKVGihPv2rl273PcVL17cHQf78MMPy9GjR+XAgQOpGmfOnDmlTJky0qVLF/cydpYsWVK1D0KsBnWBukBIUlAbqA1mEmbqq5OggC9R69at5dy5c3Lp0iWNcUQc6Lp166R06dIyY8aMm+4jXbp0Pr8+xMxTlKKioty3L1y4IPfff78MGjRIGjdunEhwHnjgARk/fnwiwUkJzy864lRjY2NTPB5cUhrb9WCfSL77+++/ZeHChVK7dm2ZPHmy1KtXz6vxEWIlqAs3Ql0ghNqQFNSGtIcrJA6kaNGisn79ern33ntl0qRJKib4YmzcuDFZYWnUqJHMnTtXv+RGdQp4C5JKSLsZELCVK1fq7VWrVsm2bdv0Nr787du31ws8CJ6Cc99998ngwYN1HIFKNoMHB/z4449SoEABKVKkiCba7du3T06cOKH3ffvtt4m8G5GRkRIdHe0eF5LzICYDBw6Ue+65RwWaEDtCXaAuEJIU1AZqgxXgComDWbRokXz00Uf6BWratGmKj4WHAeXxsARrCNS4ceN8et2hQ4dK9+7ddckSy6K33367bl+2bJnMmzdPv7BTp07VbW3atJFSpUrJ1q1b9fWNEn29evXSi6/gNSdMmCB9+/aVTJkyqZcC3o5ChQpp9ZBatWqp4ECADfLkySPdunWTKlWqSPbs2XUZGEIIjxGei6VYHBchdoa6QF0gJCmoDdQGM2HZX+I4sFT6wgsvqMeHEEIAdYEQkhTUBmvAkC1CCCGEEEKIaXCFhBBCCCGEEGIaXCEhhBBCCCGEmAYNEkIIIYQQQohp0CAhhBBCCCGEmAYNEkIIIYQQQohp0CAhhBBCCCGEmAYNEkIIIYQQQohp0CAhhBBCCCGEiFn8P8RXW0KnEO8tAAAAAElFTkSuQmCC",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(num=None, figsize=(12, 3), dpi=80, facecolor='w', edgecolor='k')\n",
"plt.subplot(1, 3, 1)\n",
"plt.plot(stmt_ts, color='white')\n",
"plt.plot(stmt_ts[:time])\n",
"plt.xticks(range(0, trials + 1, int(time)))\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of statements exercised')\n",
"\n",
"plt.subplot(1, 3, 2)\n",
"line_cur, = plt.plot(stmt_ts[:time], label=\"Ongoing fuzzing campaign\")\n",
"line_pred, = plt.plot(prediction_ts, linestyle='--',\n",
" color='black', label=\"Predicted progress\")\n",
"plt.legend(handles=[line_cur, line_pred])\n",
"plt.xticks(range(0, trials + 1, int(time)))\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of statements exercised')\n",
"\n",
"plt.subplot(1, 3, 3)\n",
"line_emp, = plt.plot(stmt_ts, color='grey', label=\"Actual progress\")\n",
"line_cur, = plt.plot(stmt_ts[:time], label=\"Ongoing fuzzing campaign\")\n",
"line_pred, = plt.plot(prediction_ts, linestyle='--',\n",
" color='black', label=\"Predicted progress\")\n",
"plt.legend(handles=[line_emp, line_cur, line_pred])\n",
"plt.xticks(range(0, trials + 1, int(time)))\n",
"plt.xlabel('# of fuzz inputs')\n",
"plt.ylabel('# of statements exercised');"
]
}
],
"metadata": {
"ipub": {
"bibliography": "fuzzingbook.bib",
"toc": true
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
},
"toc-autonumbering": false,
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}