We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
wpantund benchmark can initiate network connections
The wpantund benchmark can initiate networking connections to remote networks under some conditions. Attaching a testcase for that:

[1788a8b166e1fe4e854bdbb1572e2bb6.00000080.honggfuzz.cov.txt](https://github.com/google/fuzzbench/files/4391761/1788a8b166e1fe4e854bdbb1572e2bb6.00000080.honggfuzz.cov.txt)

```shell
$ strace -f ~/fuzz/wpantund/wpantund-fuzz ~/fuzz/wpantund/corpus/1788a8b166e1fe4e854bdbb1572e2bb6.00000080.honggfuzz.cov
...
openat(AT_FDCWD, "/tmp", O_RDWR|O_EXCL|O_TMPFILE, 0600) = 6
fcntl(6, F_GETFL)                       = 0x418002 (flags O_RDWR|O_LARGEFILE|O_TMPFILE)
fstat(6, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
write(6, "\235mfProxy:EnabiG:NNN\305SocketPath \""..., 127) = 127
lseek(6, 0, SEEK_SET)                   = 0
read(6, "\235mfProxy:EnabiG:NNN\305SocketPath \""..., 4096) = 127
read(6, "", 4096)                       = 0
close(6)                                = 0
brk(0xb518000)                          = 0xb518000
socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 6
connect(6, {sa_family=AF_INET6, sin6_port=htons(4951), inet_pton(AF_INET6, "::ffff:0.0.3.122", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28^C) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
..
```

I know nothing about wpantund internals, so maybe this can be fixed (if you want to fix it) in the fuzzer harness code (maybe some API option needs to be set).

If not on API level, a quick hack could be to add something like

```C
unshare(CLONE_NEWUSER|CLONE_NEWNET);
```

at the beginning of the file.

I'm not sure if we want to leave current behavior as-is. On one hand it might be a useful case to test fuzzing timeouts, on the other, benchmarks initiating connections over non-loopback sound somehow wrong (and they also add unnecessary timeouts).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `.github/workflows/build.py`
Content:
```
1 #!/usr/bin/env python3
2 # Copyright 2020 Google LLC
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Script for building fuzzer,benchmark pairs in CI."""
16 import sys
17 import subprocess
18 
19 # Don't build php benchmark since it fills up disk in GH actions.
20 OSS_FUZZ_BENCHMARKS = [
21     'bloaty_fuzz_target',
22     'curl_curl_fuzzer_http',
23     'irssi_server-fuzz',
24     'jsoncpp_jsoncpp_fuzzer',
25     'libpcap_fuzz_both',
26     'mbedtls_fuzz_dtlsclient',
27     'openssl_x509',
28     'proxygen_ProxygenHTTP1xFuzzer',
29     'sqlite3_ossfuzz',
30     'systemd_fuzz-link-parser',
31     'zlib_zlib_uncompress_fuzzer',
32 ]
33 
34 STANDARD_BENCHMARKS = [
35     'freetype2-2017',
36     'harfbuzz-1.3.2',
37     'lcms-2017-03-21',
38     'libjpeg-turbo-07-2017',
39     'libpng-1.2.56',
40     'libxml2-v2.9.2',
41     'openthread-2019-12-23',
42     'proj4-2017-08-14',
43     're2-2014-12-09',
44     'vorbis-2017-12-11',
45     'woff2-2016-05-06',
46     'wpantund-2018-02-27',
47 ]
48 
49 
50 def get_make_targets(benchmarks, fuzzer):
51     """Return pull and build targets for |fuzzer| and each benchmark
52     in |benchmarks| to pass to make."""
53     return [('pull-%s-%s' % (fuzzer, benchmark),
54              'build-%s-%s' % (fuzzer, benchmark)) for benchmark in benchmarks]
55 
56 
57 def delete_docker_images():
58     """Delete docker images."""
59     # TODO(metzman): Don't delete base-runner/base-builder so it
60     # doesn't need to be pulled for every target.
61     result = subprocess.run(['docker', 'images', '-q'],
62                             stdout=subprocess.PIPE,
63                             check=True)
64     image_names = result.stdout.splitlines()
65     subprocess.run(['docker', 'rmi', '-f'] + image_names, check=False)
66 
67 
68 def make_builds(benchmarks, fuzzer):
69     """Use make to build each target in |build_targets|."""
70     make_targets = get_make_targets(benchmarks, fuzzer)
71     for pull_target, build_target in make_targets:
72         # Pull target first.
73         subprocess.run(['make', '-j', pull_target], check=False)
74 
75         # Then build.
76         print('Building', build_target)
77         build_command = ['make', '-j', build_target]
78         result = subprocess.run(build_command, check=False)
79         if not result.returncode == 0:
80             return False
81         # Delete docker images so disk doesn't fill up.
82         delete_docker_images()
83     return True
84 
85 
86 def do_build(build_type, fuzzer):
87     """Build fuzzer,benchmark pairs for CI."""
88     if build_type == 'oss-fuzz':
89         benchmarks = OSS_FUZZ_BENCHMARKS
90     elif build_type == 'standard':
91         benchmarks = STANDARD_BENCHMARKS
92     else:
93         raise Exception('Invalid build_type: %s' % build_type)
94 
95     return make_builds(benchmarks, fuzzer)
96 
97 
98 def main():
99     """Build OSS-Fuzz or standard benchmarks with a fuzzer."""
100     if len(sys.argv) != 3:
101         print('Usage: %s <build_type> <fuzzer>' % sys.argv[0])
102         return 1
103     build_type = sys.argv[1]
104     fuzzer = sys.argv[2]
105     result = do_build(build_type, fuzzer)
106     return 0 if result else 1
107 
108 
109 if __name__ == '__main__':
110     sys.exit(main())
111
```

Path: `fuzzers/afl/fuzzer.py`
Content:
```
1 # Copyright 2020 Google LLC
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Integration code for AFL fuzzer."""
15 
16 import shutil
17 import subprocess
18 import os
19 
20 from fuzzers import utils
21 
22 # OUT environment variable is the location of build directory (default is /out).
23 
24 
25 def prepare_build_environment():
26     """Set environment variables used to build targets for AFL-based
27     fuzzers."""
28     cflags = ['-fsanitize-coverage=trace-pc-guard']
29     utils.append_flags('CFLAGS', cflags)
30     utils.append_flags('CXXFLAGS', cflags)
31 
32     os.environ['CC'] = 'clang'
33     os.environ['CXX'] = 'clang++'
34     os.environ['FUZZER_LIB'] = '/libAFL.a'
35 
36 
37 def build():
38     """Build benchmark."""
39     prepare_build_environment()
40 
41     utils.build_benchmark()
42 
43     print('[post_build] Copying afl-fuzz to $OUT directory')
44     # Copy out the afl-fuzz binary as a build artifact.
45     shutil.copy('/afl/afl-fuzz', os.environ['OUT'])
46 
47 
48 def prepare_fuzz_environment(input_corpus):
49     """Prepare to fuzz with AFL or another AFL-based fuzzer."""
50     # Tell AFL to not use its terminal UI so we get usable logs.
51     os.environ['AFL_NO_UI'] = '1'
52     # Skip AFL's CPU frequency check (fails on Docker).
53     os.environ['AFL_SKIP_CPUFREQ'] = '1'
54     # No need to bind affinity to one core, Docker enforces 1 core usage.
55     os.environ['AFL_NO_AFFINITY'] = '1'
56     # AFL will abort on startup if the core pattern sends notifications to
57     # external programs. We don't care about this.
58     os.environ['AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES'] = '1'
59 
60     # AFL needs at least one non-empty seed to start.
61     if len(os.listdir(input_corpus)) == 0:
62         with open(os.path.join(input_corpus, 'default_seed'),
63                   'w') as file_handle:
64             file_handle.write('hi')
65 
66 
67 def run_afl_fuzz(input_corpus,
68                  output_corpus,
69                  target_binary,
70                  additional_flags=None,
71                  hide_output=False):
72     """Run afl-fuzz."""
73     # Spawn the afl fuzzing process.
74     # FIXME: Currently AFL will exit if it encounters a crashing input in seed
75     # corpus (usually timeouts). Add a way to skip/delete such inputs and
76     # re-run AFL. This currently happens with a seed in wpantund benchmark.
77     print('[run_fuzzer] Running target with afl-fuzz')
78     command = [
79         './afl-fuzz',
80         '-i',
81         input_corpus,
82         '-o',
83         output_corpus,
84         # Use deterministic mode as it does best when we don't have
85         # seeds which is often the case.
86         '-d',
87         # Use no memory limit as ASAN doesn't play nicely with one.
88         '-m',
89         'none'
90     ]
91     if additional_flags:
92         command.extend(additional_flags)
93     dictionary_path = utils.get_dictionary_path(target_binary)
94     if dictionary_path:
95         command.extend(['-x', dictionary_path])
96     command += [
97         '--',
98         target_binary,
99         # Pass INT_MAX to afl the maximize the number of persistent loops it
100         # performs.
101         '2147483647'
102     ]
103     print('[run_fuzzer] Running command: ' + ' '.join(command))
104     output_stream = subprocess.DEVNULL if hide_output else None
105     subprocess.call(command, stdout=output_stream, stderr=output_stream)
106 
107 
108 def fuzz(input_corpus, output_corpus, target_binary):
109     """Run afl-fuzz on target."""
110     prepare_fuzz_environment(input_corpus)
111 
112     run_afl_fuzz(input_corpus, output_corpus, target_binary)
113
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/.github/workflows/build.py b/.github/workflows/build.py
--- a/.github/workflows/build.py
+++ b/.github/workflows/build.py
@@ -42,7 +42,6 @@
     're2-2014-12-09',
     'vorbis-2017-12-11',
     'woff2-2016-05-06',
-    'wpantund-2018-02-27',
 ]
 
 
diff --git a/fuzzers/afl/fuzzer.py b/fuzzers/afl/fuzzer.py
--- a/fuzzers/afl/fuzzer.py
+++ b/fuzzers/afl/fuzzer.py
@@ -73,7 +73,7 @@
     # Spawn the afl fuzzing process.
     # FIXME: Currently AFL will exit if it encounters a crashing input in seed
     # corpus (usually timeouts). Add a way to skip/delete such inputs and
-    # re-run AFL. This currently happens with a seed in wpantund benchmark.
+    # re-run AFL.
     print('[run_fuzzer] Running target with afl-fuzz')
     command = [
         './afl-fuzz',

{"golden_diff": "diff --git a/.github/workflows/build.py b/.github/workflows/build.py\n--- a/.github/workflows/build.py\n+++ b/.github/workflows/build.py\n@@ -42,7 +42,6 @@\n     're2-2014-12-09',\n     'vorbis-2017-12-11',\n     'woff2-2016-05-06',\n-    'wpantund-2018-02-27',\n ]\n \n \ndiff --git a/fuzzers/afl/fuzzer.py b/fuzzers/afl/fuzzer.py\n--- a/fuzzers/afl/fuzzer.py\n+++ b/fuzzers/afl/fuzzer.py\n@@ -73,7 +73,7 @@\n     # Spawn the afl fuzzing process.\n     # FIXME: Currently AFL will exit if it encounters a crashing input in seed\n     # corpus (usually timeouts). Add a way to skip/delete such inputs and\n-    # re-run AFL. This currently happens with a seed in wpantund benchmark.\n+    # re-run AFL.\n     print('[run_fuzzer] Running target with afl-fuzz')\n     command = [\n         './afl-fuzz',\n", "issue": "wpantund benchmark can initiate network connections\nThe wpantund benchmark can initiate networking connections to remote networks under some conditions. Attaching a testcase for that:\r\n\r\n[1788a8b166e1fe4e854bdbb1572e2bb6.00000080.honggfuzz.cov.txt](https://github.com/google/fuzzbench/files/4391761/1788a8b166e1fe4e854bdbb1572e2bb6.00000080.honggfuzz.cov.txt)\r\n\r\n```shell\r\n$ strace -f ~/fuzz/wpantund/wpantund-fuzz ~/fuzz/wpantund/corpus/1788a8b166e1fe4e854bdbb1572e2bb6.00000080.honggfuzz.cov\r\n...\r\nopenat(AT_FDCWD, \"/tmp\", O_RDWR|O_EXCL|O_TMPFILE, 0600) = 6\r\nfcntl(6, F_GETFL)                       = 0x418002 (flags O_RDWR|O_LARGEFILE|O_TMPFILE)\r\nfstat(6, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0\r\nwrite(6, \"\\235mfProxy:EnabiG:NNN\\305SocketPath \\\"\"..., 127) = 127\r\nlseek(6, 0, SEEK_SET)                   = 0\r\nread(6, \"\\235mfProxy:EnabiG:NNN\\305SocketPath \\\"\"..., 4096) = 127\r\nread(6, \"\", 4096)                       = 0\r\nclose(6)                                = 0\r\nbrk(0xb518000)                          = 0xb518000\r\nsocket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 6\r\nconnect(6, {sa_family=AF_INET6, sin6_port=htons(4951), inet_pton(AF_INET6, \"::ffff:0.0.3.122\", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28^C) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)\r\n..\r\n```\r\n\r\nI know nothing about wpantund internals, so maybe this can be fixed (if you want to fix it) in the fuzzer harness code (maybe some API option needs to be set).\r\n\r\nIf not on API level, a quick hack could be to add something like\r\n\r\n```C\r\nunshare(CLONE_NEWUSER|CLONE_NEWNET);\r\n```\r\n\r\nat the beginning of the file.\r\n\r\nI'm not sure if we want to leave current behavior as-is. On one hand it might be a useful case to test fuzzing timeouts, on the other, benchmarks initiating connections over non-loopback sound somehow wrong (and they also add unnecessary timeouts).\n", "before_files": [{"content": "#!/usr/bin/env python3\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Script for building fuzzer,benchmark pairs in CI.\"\"\"\nimport sys\nimport subprocess\n\n# Don't build php benchmark since it fills up disk in GH actions.\nOSS_FUZZ_BENCHMARKS = [\n    'bloaty_fuzz_target',\n    'curl_curl_fuzzer_http',\n    'irssi_server-fuzz',\n    'jsoncpp_jsoncpp_fuzzer',\n    'libpcap_fuzz_both',\n    'mbedtls_fuzz_dtlsclient',\n    'openssl_x509',\n    'proxygen_ProxygenHTTP1xFuzzer',\n    'sqlite3_ossfuzz',\n    'systemd_fuzz-link-parser',\n    'zlib_zlib_uncompress_fuzzer',\n]\n\nSTANDARD_BENCHMARKS = [\n    'freetype2-2017',\n    'harfbuzz-1.3.2',\n    'lcms-2017-03-21',\n    'libjpeg-turbo-07-2017',\n    'libpng-1.2.56',\n    'libxml2-v2.9.2',\n    'openthread-2019-12-23',\n    'proj4-2017-08-14',\n    're2-2014-12-09',\n    'vorbis-2017-12-11',\n    'woff2-2016-05-06',\n    'wpantund-2018-02-27',\n]\n\n\ndef get_make_targets(benchmarks, fuzzer):\n    \"\"\"Return pull and build targets for |fuzzer| and each benchmark\n    in |benchmarks| to pass to make.\"\"\"\n    return [('pull-%s-%s' % (fuzzer, benchmark),\n             'build-%s-%s' % (fuzzer, benchmark)) for benchmark in benchmarks]\n\n\ndef delete_docker_images():\n    \"\"\"Delete docker images.\"\"\"\n    # TODO(metzman): Don't delete base-runner/base-builder so it\n    # doesn't need to be pulled for every target.\n    result = subprocess.run(['docker', 'images', '-q'],\n                            stdout=subprocess.PIPE,\n                            check=True)\n    image_names = result.stdout.splitlines()\n    subprocess.run(['docker', 'rmi', '-f'] + image_names, check=False)\n\n\ndef make_builds(benchmarks, fuzzer):\n    \"\"\"Use make to build each target in |build_targets|.\"\"\"\n    make_targets = get_make_targets(benchmarks, fuzzer)\n    for pull_target, build_target in make_targets:\n        # Pull target first.\n        subprocess.run(['make', '-j', pull_target], check=False)\n\n        # Then build.\n        print('Building', build_target)\n        build_command = ['make', '-j', build_target]\n        result = subprocess.run(build_command, check=False)\n        if not result.returncode == 0:\n            return False\n        # Delete docker images so disk doesn't fill up.\n        delete_docker_images()\n    return True\n\n\ndef do_build(build_type, fuzzer):\n    \"\"\"Build fuzzer,benchmark pairs for CI.\"\"\"\n    if build_type == 'oss-fuzz':\n        benchmarks = OSS_FUZZ_BENCHMARKS\n    elif build_type == 'standard':\n        benchmarks = STANDARD_BENCHMARKS\n    else:\n        raise Exception('Invalid build_type: %s' % build_type)\n\n    return make_builds(benchmarks, fuzzer)\n\n\ndef main():\n    \"\"\"Build OSS-Fuzz or standard benchmarks with a fuzzer.\"\"\"\n    if len(sys.argv) != 3:\n        print('Usage: %s <build_type> <fuzzer>' % sys.argv[0])\n        return 1\n    build_type = sys.argv[1]\n    fuzzer = sys.argv[2]\n    result = do_build(build_type, fuzzer)\n    return 0 if result else 1\n\n\nif __name__ == '__main__':\n    sys.exit(main())\n", "path": ".github/workflows/build.py"}, {"content": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Integration code for AFL fuzzer.\"\"\"\n\nimport shutil\nimport subprocess\nimport os\n\nfrom fuzzers import utils\n\n# OUT environment variable is the location of build directory (default is /out).\n\n\ndef prepare_build_environment():\n    \"\"\"Set environment variables used to build targets for AFL-based\n    fuzzers.\"\"\"\n    cflags = ['-fsanitize-coverage=trace-pc-guard']\n    utils.append_flags('CFLAGS', cflags)\n    utils.append_flags('CXXFLAGS', cflags)\n\n    os.environ['CC'] = 'clang'\n    os.environ['CXX'] = 'clang++'\n    os.environ['FUZZER_LIB'] = '/libAFL.a'\n\n\ndef build():\n    \"\"\"Build benchmark.\"\"\"\n    prepare_build_environment()\n\n    utils.build_benchmark()\n\n    print('[post_build] Copying afl-fuzz to $OUT directory')\n    # Copy out the afl-fuzz binary as a build artifact.\n    shutil.copy('/afl/afl-fuzz', os.environ['OUT'])\n\n\ndef prepare_fuzz_environment(input_corpus):\n    \"\"\"Prepare to fuzz with AFL or another AFL-based fuzzer.\"\"\"\n    # Tell AFL to not use its terminal UI so we get usable logs.\n    os.environ['AFL_NO_UI'] = '1'\n    # Skip AFL's CPU frequency check (fails on Docker).\n    os.environ['AFL_SKIP_CPUFREQ'] = '1'\n    # No need to bind affinity to one core, Docker enforces 1 core usage.\n    os.environ['AFL_NO_AFFINITY'] = '1'\n    # AFL will abort on startup if the core pattern sends notifications to\n    # external programs. We don't care about this.\n    os.environ['AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES'] = '1'\n\n    # AFL needs at least one non-empty seed to start.\n    if len(os.listdir(input_corpus)) == 0:\n        with open(os.path.join(input_corpus, 'default_seed'),\n                  'w') as file_handle:\n            file_handle.write('hi')\n\n\ndef run_afl_fuzz(input_corpus,\n                 output_corpus,\n                 target_binary,\n                 additional_flags=None,\n                 hide_output=False):\n    \"\"\"Run afl-fuzz.\"\"\"\n    # Spawn the afl fuzzing process.\n    # FIXME: Currently AFL will exit if it encounters a crashing input in seed\n    # corpus (usually timeouts). Add a way to skip/delete such inputs and\n    # re-run AFL. This currently happens with a seed in wpantund benchmark.\n    print('[run_fuzzer] Running target with afl-fuzz')\n    command = [\n        './afl-fuzz',\n        '-i',\n        input_corpus,\n        '-o',\n        output_corpus,\n        # Use deterministic mode as it does best when we don't have\n        # seeds which is often the case.\n        '-d',\n        # Use no memory limit as ASAN doesn't play nicely with one.\n        '-m',\n        'none'\n    ]\n    if additional_flags:\n        command.extend(additional_flags)\n    dictionary_path = utils.get_dictionary_path(target_binary)\n    if dictionary_path:\n        command.extend(['-x', dictionary_path])\n    command += [\n        '--',\n        target_binary,\n        # Pass INT_MAX to afl the maximize the number of persistent loops it\n        # performs.\n        '2147483647'\n    ]\n    print('[run_fuzzer] Running command: ' + ' '.join(command))\n    output_stream = subprocess.DEVNULL if hide_output else None\n    subprocess.call(command, stdout=output_stream, stderr=output_stream)\n\n\ndef fuzz(input_corpus, output_corpus, target_binary):\n    \"\"\"Run afl-fuzz on target.\"\"\"\n    prepare_fuzz_environment(input_corpus)\n\n    run_afl_fuzz(input_corpus, output_corpus, target_binary)\n", "path": "fuzzers/afl/fuzzer.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Script for building fuzzer,benchmark pairs in CI.\"\"\"\nimport sys\nimport subprocess\n\n# Don't build php benchmark since it fills up disk in GH actions.\nOSS_FUZZ_BENCHMARKS = [\n    'bloaty_fuzz_target',\n    'curl_curl_fuzzer_http',\n    'irssi_server-fuzz',\n    'jsoncpp_jsoncpp_fuzzer',\n    'libpcap_fuzz_both',\n    'mbedtls_fuzz_dtlsclient',\n    'openssl_x509',\n    'sqlite3_ossfuzz',\n    'systemd_fuzz-link-parser',\n    'zlib_zlib_uncompress_fuzzer',\n]\n\nSTANDARD_BENCHMARKS = [\n    'freetype2-2017',\n    'harfbuzz-1.3.2',\n    'lcms-2017-03-21',\n    'libjpeg-turbo-07-2017',\n    'libpng-1.2.56',\n    'libxml2-v2.9.2',\n    'openthread-2019-12-23',\n    'proj4-2017-08-14',\n    're2-2014-12-09',\n    'vorbis-2017-12-11',\n    'woff2-2016-05-06',\n]\n\n\ndef get_make_targets(benchmarks, fuzzer):\n    \"\"\"Return pull and build targets for |fuzzer| and each benchmark\n    in |benchmarks| to pass to make.\"\"\"\n    return [('pull-%s-%s' % (fuzzer, benchmark),\n             'build-%s-%s' % (fuzzer, benchmark)) for benchmark in benchmarks]\n\n\ndef delete_docker_images():\n    \"\"\"Delete docker images.\"\"\"\n    # TODO(metzman): Don't delete base-runner/base-builder so it\n    # doesn't need to be pulled for every target.\n    result = subprocess.run(['docker', 'images', '-q'],\n                            stdout=subprocess.PIPE,\n                            check=True)\n    image_names = result.stdout.splitlines()\n    subprocess.run(['docker', 'rmi', '-f'] + image_names, check=False)\n\n\ndef make_builds(benchmarks, fuzzer):\n    \"\"\"Use make to build each target in |build_targets|.\"\"\"\n    make_targets = get_make_targets(benchmarks, fuzzer)\n    for pull_target, build_target in make_targets:\n        # Pull target first.\n        subprocess.run(['make', '-j', pull_target], check=False)\n\n        # Then build.\n        print('Building', build_target)\n        build_command = ['make', '-j', build_target]\n        result = subprocess.run(build_command, check=False)\n        if not result.returncode == 0:\n            return False\n        # Delete docker images so disk doesn't fill up.\n        delete_docker_images()\n    return True\n\n\ndef do_build(build_type, fuzzer):\n    \"\"\"Build fuzzer,benchmark pairs for CI.\"\"\"\n    if build_type == 'oss-fuzz':\n        benchmarks = OSS_FUZZ_BENCHMARKS\n    elif build_type == 'standard':\n        benchmarks = STANDARD_BENCHMARKS\n    else:\n        raise Exception('Invalid build_type: %s' % build_type)\n\n    return make_builds(benchmarks, fuzzer)\n\n\ndef main():\n    \"\"\"Build OSS-Fuzz or standard benchmarks with a fuzzer.\"\"\"\n    if len(sys.argv) != 3:\n        print('Usage: %s <build_type> <fuzzer>' % sys.argv[0])\n        return 1\n    build_type = sys.argv[1]\n    fuzzer = sys.argv[2]\n    result = do_build(build_type, fuzzer)\n    return 0 if result else 1\n\n\nif __name__ == '__main__':\n    sys.exit(main())\n", "path": ".github/workflows/build.py"}, {"content": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Integration code for AFL fuzzer.\"\"\"\n\nimport shutil\nimport subprocess\nimport os\n\nfrom fuzzers import utils\n\n# OUT environment variable is the location of build directory (default is /out).\n\n\ndef prepare_build_environment():\n    \"\"\"Set environment variables used to build targets for AFL-based\n    fuzzers.\"\"\"\n    cflags = ['-fsanitize-coverage=trace-pc-guard']\n    utils.append_flags('CFLAGS', cflags)\n    utils.append_flags('CXXFLAGS', cflags)\n\n    os.environ['CC'] = 'clang'\n    os.environ['CXX'] = 'clang++'\n    os.environ['FUZZER_LIB'] = '/libAFL.a'\n\n\ndef build():\n    \"\"\"Build benchmark.\"\"\"\n    prepare_build_environment()\n\n    utils.build_benchmark()\n\n    print('[post_build] Copying afl-fuzz to $OUT directory')\n    # Copy out the afl-fuzz binary as a build artifact.\n    shutil.copy('/afl/afl-fuzz', os.environ['OUT'])\n\n\ndef prepare_fuzz_environment(input_corpus):\n    \"\"\"Prepare to fuzz with AFL or another AFL-based fuzzer.\"\"\"\n    # Tell AFL to not use its terminal UI so we get usable logs.\n    os.environ['AFL_NO_UI'] = '1'\n    # Skip AFL's CPU frequency check (fails on Docker).\n    os.environ['AFL_SKIP_CPUFREQ'] = '1'\n    # No need to bind affinity to one core, Docker enforces 1 core usage.\n    os.environ['AFL_NO_AFFINITY'] = '1'\n    # AFL will abort on startup if the core pattern sends notifications to\n    # external programs. We don't care about this.\n    os.environ['AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES'] = '1'\n\n    # AFL needs at least one non-empty seed to start.\n    if len(os.listdir(input_corpus)) == 0:\n        with open(os.path.join(input_corpus, 'default_seed'),\n                  'w') as file_handle:\n            file_handle.write('hi')\n\n\ndef run_afl_fuzz(input_corpus,\n                 output_corpus,\n                 target_binary,\n                 additional_flags=None,\n                 hide_output=False):\n    \"\"\"Run afl-fuzz.\"\"\"\n    # Spawn the afl fuzzing process.\n    # FIXME: Currently AFL will exit if it encounters a crashing input in seed\n    # corpus (usually timeouts). Add a way to skip/delete such inputs and\n    # re-run AFL.\n    print('[run_fuzzer] Running target with afl-fuzz')\n    command = [\n        './afl-fuzz',\n        '-i',\n        input_corpus,\n        '-o',\n        output_corpus,\n        # Use deterministic mode as it does best when we don't have\n        # seeds which is often the case.\n        '-d',\n        # Use no memory limit as ASAN doesn't play nicely with one.\n        '-m',\n        'none'\n    ]\n    if additional_flags:\n        command.extend(additional_flags)\n    dictionary_path = utils.get_dictionary_path(target_binary)\n    if dictionary_path:\n        command.extend(['-x', dictionary_path])\n    command += [\n        '--',\n        target_binary,\n        # Pass INT_MAX to afl the maximize the number of persistent loops it\n        # performs.\n        '2147483647'\n    ]\n    print('[run_fuzzer] Running command: ' + ' '.join(command))\n    output_stream = subprocess.DEVNULL if hide_output else None\n    subprocess.call(command, stdout=output_stream, stderr=output_stream)\n\n\ndef fuzz(input_corpus, output_corpus, target_binary):\n    \"\"\"Run afl-fuzz on target.\"\"\"\n    prepare_fuzz_environment(input_corpus)\n\n    run_afl_fuzz(input_corpus, output_corpus, target_binary)\n", "path": "fuzzers/afl/fuzzer.py"}]}