Upgrade oss-fuzz to fd15c6d57aa13667af2521daf6167a2d8cd2ecb7 am: ebda00b748 am: 83853d5c3c am: c85b7e55ec am: 771bcd4878

Original change: https://android-review.googlesource.com/c/platform/external/oss-fuzz/+/1854493

Change-Id: I19b73b74ac475ff8cb9f4be6a260564d97fac5bc
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..50dc55e
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+/projects/librawspeed/ @LebedevRI
diff --git a/.github/workflows/infra_tests.yml b/.github/workflows/infra_tests.yml
index 5273adc..53c1ad5 100644
--- a/.github/workflows/infra_tests.yml
+++ b/.github/workflows/infra_tests.yml
@@ -3,6 +3,7 @@
   pull_request:
     paths:
       - 'infra/**'
+      - '.github/workflows/**'
 
 jobs:
   build:
@@ -15,8 +16,9 @@
           access_token: ${{ github.token }}
 
       - uses: actions/checkout@v2
-      - run: |  # Needed for git diff to work.
-          git fetch origin master --depth 1
+        with:  # Needed for git diff to work. (get_changed_files)
+          fetch-depth: 0
+      - run: |
           git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master
 
       - name: Setup python environment
@@ -29,12 +31,13 @@
           sudo env "PATH=$PATH" python -m pip install --upgrade pip
           sudo env "PATH=$PATH" pip install -r infra/ci/requirements.txt
           sudo env "PATH=$PATH" pip install -r infra/build/functions/requirements.txt
+          sudo env "PATH=$PATH" pip install -r infra/cifuzz/requirements.txt
 
-      - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
+      - uses: google-github-actions/setup-gcloud@master
         with:
           version: '298.0.0'
       - run: |
           sudo env "PATH=$PATH" gcloud components install beta cloud-datastore-emulator
 
       - name: Run infra tests
-        run: sudo env "PATH=$PATH" INTEGRATION_TESTS=1 python infra/presubmit.py infra-tests -p
+        run: sudo env "PATH=$PATH" END_TO_END_TESTS=1 INTEGRATION_TESTS=1 python infra/presubmit.py infra-tests -p
diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml
index 9a4b8d6..1e80301 100644
--- a/.github/workflows/presubmit.yml
+++ b/.github/workflows/presubmit.yml
@@ -16,8 +16,9 @@
           access_token: ${{ github.token }}
 
       - uses: actions/checkout@v2
-      - run: |  # Needed for git diff to work.
-          git fetch origin master --depth 1
+        with:  # Needed for git diff to work. (get_changed_files)
+          fetch-depth: 0
+      - run: |
           git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master
 
       - name: Setup python environment
diff --git a/.github/workflows/project_tests.yml b/.github/workflows/project_tests.yml
index 55dfb7f..4d5e4f0 100644
--- a/.github/workflows/project_tests.yml
+++ b/.github/workflows/project_tests.yml
@@ -48,8 +48,9 @@
           access_token: ${{ github.token }}
 
       - uses: actions/checkout@v2
-      - run: |  # Needed for git diff to work.
-          git fetch origin master --depth 1
+        with:  # Needed for git diff to work. (get_changed_files)
+          fetch-depth: 0
+      - run: |
           git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master
 
       - name: Clear unnecessary files
diff --git a/METADATA b/METADATA
index dfba61b..9380fa5 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
     type: GIT
     value: "https://github.com/google/oss-fuzz.git"
   }
-  version: "947169dc86572e121c3e138f366a9f39ac6266ae"
+  version: "fd15c6d57aa13667af2521daf6167a2d8cd2ecb7"
   license_type: RESTRICTED
   last_upgrade_date {
     year: 2021
-    month: 4
-    day: 1
+    month: 10
+    day: 12
   }
 }
diff --git a/README.md b/README.md
index 4e5474a..0baf34b 100644
--- a/README.md
+++ b/README.md
@@ -44,11 +44,11 @@
 [detailed documentation]: https://google.github.io/oss-fuzz
 
 ## Trophies
-As of January 2021, OSS-Fuzz has found over [25,000] bugs in [375] open source
+As of June 2021, OSS-Fuzz has found over [30,000] bugs in [500] open source
 projects.
 
-[25,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
-[375]: https://github.com/google/oss-fuzz/tree/master/projects
+[30,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
+[500]: https://github.com/google/oss-fuzz/tree/master/projects
 
 ## Blog posts
 * 2016-12-01 - [Announcing OSS-Fuzz: Continuous fuzzing for open source software]
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index a6807df..b67c3bc 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -1,13 +1,13 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    activesupport (6.0.3.4)
+    activesupport (6.0.4)
       concurrent-ruby (~> 1.0, >= 1.0.2)
       i18n (>= 0.7, < 2)
       minitest (~> 5.1)
       tzinfo (~> 1.1)
       zeitwerk (~> 2.2, >= 2.2.2)
-    addressable (2.7.0)
+    addressable (2.8.0)
       public_suffix (>= 2.0.2, < 5.0)
     coffee-script (2.4.1)
       coffee-script-source
@@ -16,26 +16,40 @@
     colorator (1.1.0)
     commonmarker (0.17.13)
       ruby-enum (~> 0.5)
-    concurrent-ruby (1.1.7)
-    dnsruby (1.61.5)
+    concurrent-ruby (1.1.9)
+    dnsruby (1.61.7)
       simpleidn (~> 0.1)
     em-websocket (0.5.2)
       eventmachine (>= 0.12.9)
       http_parser.rb (~> 0.6.0)
-    ethon (0.12.0)
-      ffi (>= 1.3.0)
+    ethon (0.14.0)
+      ffi (>= 1.15.0)
     eventmachine (1.2.7)
-    execjs (2.7.0)
-    faraday (1.3.0)
+    execjs (2.8.1)
+    faraday (1.6.0)
+      faraday-em_http (~> 1.0)
+      faraday-em_synchrony (~> 1.0)
+      faraday-excon (~> 1.1)
+      faraday-httpclient (~> 1.0.1)
       faraday-net_http (~> 1.0)
+      faraday-net_http_persistent (~> 1.1)
+      faraday-patron (~> 1.0)
+      faraday-rack (~> 1.0)
       multipart-post (>= 1.2, < 3)
-      ruby2_keywords
-    faraday-net_http (1.0.0)
-    ffi (1.14.2)
+      ruby2_keywords (>= 0.0.4)
+    faraday-em_http (1.0.0)
+    faraday-em_synchrony (1.0.0)
+    faraday-excon (1.1.0)
+    faraday-httpclient (1.0.1)
+    faraday-net_http (1.0.1)
+    faraday-net_http_persistent (1.2.0)
+    faraday-patron (1.0.0)
+    faraday-rack (1.0.0)
+    ffi (1.15.3)
     forwardable-extended (2.6.0)
     gemoji (3.0.1)
-    github-pages (209)
-      github-pages-health-check (= 1.16.1)
+    github-pages (218)
+      github-pages-health-check (= 1.17.2)
       jekyll (= 3.9.0)
       jekyll-avatar (= 0.7.0)
       jekyll-coffeescript (= 1.1.1)
@@ -50,39 +64,39 @@
       jekyll-readme-index (= 0.3.0)
       jekyll-redirect-from (= 0.16.0)
       jekyll-relative-links (= 0.6.1)
-      jekyll-remote-theme (= 0.4.2)
+      jekyll-remote-theme (= 0.4.3)
       jekyll-sass-converter (= 1.5.2)
-      jekyll-seo-tag (= 2.6.1)
+      jekyll-seo-tag (= 2.7.1)
       jekyll-sitemap (= 1.4.0)
       jekyll-swiss (= 1.0.0)
-      jekyll-theme-architect (= 0.1.1)
-      jekyll-theme-cayman (= 0.1.1)
-      jekyll-theme-dinky (= 0.1.1)
-      jekyll-theme-hacker (= 0.1.2)
-      jekyll-theme-leap-day (= 0.1.1)
-      jekyll-theme-merlot (= 0.1.1)
-      jekyll-theme-midnight (= 0.1.1)
-      jekyll-theme-minimal (= 0.1.1)
-      jekyll-theme-modernist (= 0.1.1)
-      jekyll-theme-primer (= 0.5.4)
-      jekyll-theme-slate (= 0.1.1)
-      jekyll-theme-tactile (= 0.1.1)
-      jekyll-theme-time-machine (= 0.1.1)
+      jekyll-theme-architect (= 0.2.0)
+      jekyll-theme-cayman (= 0.2.0)
+      jekyll-theme-dinky (= 0.2.0)
+      jekyll-theme-hacker (= 0.2.0)
+      jekyll-theme-leap-day (= 0.2.0)
+      jekyll-theme-merlot (= 0.2.0)
+      jekyll-theme-midnight (= 0.2.0)
+      jekyll-theme-minimal (= 0.2.0)
+      jekyll-theme-modernist (= 0.2.0)
+      jekyll-theme-primer (= 0.6.0)
+      jekyll-theme-slate (= 0.2.0)
+      jekyll-theme-tactile (= 0.2.0)
+      jekyll-theme-time-machine (= 0.2.0)
       jekyll-titles-from-headings (= 0.5.3)
       jemoji (= 0.12.0)
-      kramdown (= 2.3.0)
+      kramdown (= 2.3.1)
       kramdown-parser-gfm (= 1.1.0)
       liquid (= 4.0.3)
       mercenary (~> 0.3)
       minima (= 2.5.1)
       nokogiri (>= 1.10.4, < 2.0)
-      rouge (= 3.23.0)
+      rouge (= 3.26.0)
       terminal-table (~> 1.4)
-    github-pages-health-check (1.16.1)
+    github-pages-health-check (1.17.2)
       addressable (~> 2.3)
       dnsruby (~> 1.60)
       octokit (~> 4.0)
-      public_suffix (~> 3.0)
+      public_suffix (>= 2.0.2, < 5.0)
       typhoeus (~> 1.3)
     html-pipeline (2.14.0)
       activesupport (>= 2)
@@ -136,57 +150,57 @@
       jekyll (>= 3.3, < 5.0)
     jekyll-relative-links (0.6.1)
       jekyll (>= 3.3, < 5.0)
-    jekyll-remote-theme (0.4.2)
+    jekyll-remote-theme (0.4.3)
       addressable (~> 2.0)
       jekyll (>= 3.5, < 5.0)
       jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
       rubyzip (>= 1.3.0, < 3.0)
     jekyll-sass-converter (1.5.2)
       sass (~> 3.4)
-    jekyll-seo-tag (2.6.1)
-      jekyll (>= 3.3, < 5.0)
+    jekyll-seo-tag (2.7.1)
+      jekyll (>= 3.8, < 5.0)
     jekyll-sitemap (1.4.0)
       jekyll (>= 3.7, < 5.0)
     jekyll-swiss (1.0.0)
-    jekyll-theme-architect (0.1.1)
-      jekyll (~> 3.5)
-      jekyll-seo-tag (~> 2.0)
-    jekyll-theme-cayman (0.1.1)
-      jekyll (~> 3.5)
-      jekyll-seo-tag (~> 2.0)
-    jekyll-theme-dinky (0.1.1)
-      jekyll (~> 3.5)
-      jekyll-seo-tag (~> 2.0)
-    jekyll-theme-hacker (0.1.2)
+    jekyll-theme-architect (0.2.0)
       jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-leap-day (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-cayman (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-merlot (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-dinky (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-midnight (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-hacker (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-minimal (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-leap-day (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-modernist (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-merlot (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-primer (0.5.4)
+    jekyll-theme-midnight (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-minimal (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-modernist (0.2.0)
+      jekyll (> 3.5, < 5.0)
+      jekyll-seo-tag (~> 2.0)
+    jekyll-theme-primer (0.6.0)
       jekyll (> 3.5, < 5.0)
       jekyll-github-metadata (~> 2.9)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-slate (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-slate (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-tactile (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-tactile (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
-    jekyll-theme-time-machine (0.1.1)
-      jekyll (~> 3.5)
+    jekyll-theme-time-machine (0.2.0)
+      jekyll (> 3.5, < 5.0)
       jekyll-seo-tag (~> 2.0)
     jekyll-titles-from-headings (0.5.3)
       jekyll (>= 3.3, < 5.0)
@@ -196,41 +210,39 @@
       gemoji (~> 3.0)
       html-pipeline (~> 2.2)
       jekyll (>= 3.0, < 5.0)
-    kramdown (2.3.0)
+    kramdown (2.3.1)
       rexml
     kramdown-parser-gfm (1.1.0)
       kramdown (~> 2.0)
     liquid (4.0.3)
-    listen (3.4.0)
+    listen (3.6.0)
       rb-fsevent (~> 0.10, >= 0.10.3)
       rb-inotify (~> 0.9, >= 0.9.10)
     mercenary (0.3.6)
-    mini_portile2 (2.5.0)
     minima (2.5.1)
       jekyll (>= 3.5, < 5.0)
       jekyll-feed (~> 0.9)
       jekyll-seo-tag (~> 2.1)
-    minitest (5.14.3)
+    minitest (5.14.4)
     multipart-post (2.1.1)
-    nokogiri (1.11.1)
-      mini_portile2 (~> 2.5.0)
+    nokogiri (1.12.5-x86_64-linux)
       racc (~> 1.4)
-    octokit (4.20.0)
+    octokit (4.21.0)
       faraday (>= 0.9)
       sawyer (~> 0.8.0, >= 0.5.3)
     pathutil (0.16.2)
       forwardable-extended (~> 2.6)
-    public_suffix (3.1.1)
+    public_suffix (4.0.6)
     racc (1.5.2)
-    rb-fsevent (0.10.4)
+    rb-fsevent (0.11.0)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
-    rexml (3.2.4)
-    rouge (3.23.0)
-    ruby-enum (0.8.0)
+    rexml (3.2.5)
+    rouge (3.26.0)
+    ruby-enum (0.9.0)
       i18n
-    ruby2_keywords (0.0.2)
-    rubyzip (2.3.0)
+    ruby2_keywords (0.0.5)
+    rubyzip (2.3.2)
     safe_yaml (1.0.5)
     sass (3.7.4)
       sass-listen (~> 4.0.0)
@@ -240,7 +252,7 @@
     sawyer (0.8.2)
       addressable (>= 2.3.5)
       faraday (> 0.8, < 2.0)
-    simpleidn (0.1.1)
+    simpleidn (0.2.1)
       unf (~> 0.1.4)
     terminal-table (1.8.0)
       unicode-display_width (~> 1.1, >= 1.1.1)
@@ -256,10 +268,10 @@
     zeitwerk (2.4.2)
 
 PLATFORMS
-  ruby
+  x86_64-linux
 
 DEPENDENCIES
   github-pages
 
 BUNDLED WITH
-   2.1.4
+   2.2.16
diff --git a/docs/README.md b/docs/README.md
index db0358f..af2bc4b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -5,7 +5,8 @@
 ## Prerequisites
 ```bash
 $ sudo apt install ruby bundler
-$ bundle install --path vendor/bundle
+$ bundle config set path 'vendor/bundle'
+$ bundle install
 ```
 
 ## Serving locally
diff --git a/docs/advanced-topics/bug_fixing_guidance.md b/docs/advanced-topics/bug_fixing_guidance.md
new file mode 100644
index 0000000..1ba0bd5
--- /dev/null
+++ b/docs/advanced-topics/bug_fixing_guidance.md
@@ -0,0 +1,94 @@
+---
+layout: default
+title: Bug fixing guidance
+nav_order: 6
+permalink: /advanced-topics/bug-fixing-guidance
+---
+
+# Bug fixing guidance
+{: .no_toc}
+
+This page provides brief guidance on how to prioritise and fix bugs reported by
+OSS-Fuzz.
+
+- TOC
+{:toc}
+
+## Threat modelling
+In general the severity of an issue reported by OSS-Fuzz must be determined
+relative to the threat model of the project under analysis. Therefore, although
+the fuzzers OSS-Fuzz makes an effort into determining the severity of the bug
+the true severity of the bug depends on the threat model of the project.
+
+## Bug prioritisation
+
+### Security issues
+These are the top priority of solving. A label is attached to these on
+the OSS-Fuzz testcase page and you can also search up all of these on monorail
+using the search pattern `-Bug=security`.
+
+Issues of this kind include issues reported by Address Sanitizer, e.g.
+heap-based buffer overflows, stack-based buffer overflows and use-after-frees.
+
+### Functional issues and memory leaks
+These are issues that in general can tamper with the functionality of the
+application. The bugs that have highest priority in this case are those that
+can be easily triggered by an untrusted user of the project.
+
+### Timeouts and out-of-memory
+These are in general the least prioritised issues to solve.
+
+### Bug prioritisation of non C/C++ projects
+Currently there is no prioritisation of bugs in non C/C++ projects. As such, in
+this scenario it is crucial you do the analysis yourself relative to the threat
+model of your project.
+
+## Non-reproducible bugs
+OSS-Fuzz will report some bugs that are labeled `Reliably reproduces: NO` and
+these can be tricky to deal with. A non-reproducible bug is an issue that
+OSS-Fuzz did indeed discover, however, OSS-Fuzz is unable to reproduce the bug
+with `python infra/helper.py reproduce`. In general, our suggestion is to do
+analysis of the bug and determine whether there in fact is an issue.
+
+The non-reproducible bugs can be of varying nature. Some of these bugs will be
+due to some internal state of the target application being manipulated over the
+cause of several executions of the fuzzer function. This could be several
+hundreds or even thousands of executions and the bug may not be reproducible by
+a single fuzzer test-case, however, there is indeed a bug in the application.
+There are other reasons why bugs may be non-reproducible and in general any
+non-determinism introduced into the application can have an effect on this.
+
+In the case of non-reproducible bugs our advice is to put effort into analysing
+the potential bug and also assess whether this is due to some internal state
+that persists between each fuzz run. If that is indeed the case then we also
+suggest investigating whether the fuzzer can be written such that the internal
+state in the code will be reset between each fuzz run.
+
+## Should all reported issues be solved?
+It is reported by some project maintainers that fixing timeout issues reported
+by OSS-Fuzz can increase the complexity of the project’s source code. The
+result of this is that maintainers put effort into solving a timeout issue and
+the fix results in additional complexity of the project. The question is
+whether in a scenario like this if the overall result actually improves the
+state of the application.
+
+In order to answer this question we must assess the issue relative to the
+threat model. Following the timeout anecdote then some timing issues can have
+severe security implications. For example, if the timeout issue can cause
+manipulation of control-flow then the timing issue may be of high security
+severity. As such, it is difficult to say in the general case whether or not
+some bugs should not be solved, as it should be analysed and determined on a
+project-by-project basis.
+
+In the event that a bug is reported by OSS-Fuzz that is not relevant to
+security or reliability of the application then there may still be a point to
+fixing the bug. For example, if the issue is often run into by the fuzzer then
+the fuzzer may have difficulty exploring further code in the target, and thus
+fixing the bug will allow the fuzzer to explore further code. In this case some
+suggested examples of resolving the issue could be:
+* Perform a hot-patch that is only applied during fuzzer executions and does
+not overcomplicate the project’s code.
+* Patch the code of the fuzzer to avoid the timeout. For example, some fuzzers
+restrict the size of the input to avoid certain deep recursions or
+time-intensive loops.
+* Patch the code in the target despite complicating things.
diff --git a/docs/advanced-topics/code_coverage.md b/docs/advanced-topics/code_coverage.md
index 3b0acc2..f307ad0 100644
--- a/docs/advanced-topics/code_coverage.md
+++ b/docs/advanced-topics/code_coverage.md
@@ -9,9 +9,10 @@
 # Code Coverage
 {: .no_toc}
 
-For projects written in C/C++, you can generate code coverage reports using
-Clang source-based code coverage. This page walks you through the basic steps.
-For more details, see [Clang's documentation].
+For projects written in C/C++, Rust, Go, Swift or Java and other JVM-based languages,
+you can generate code coverage reports using Clang source-based code coverage.
+This page walks you through the basic steps.
+For more details on C/C++ coverage, see [Clang's documentation].
 
 Code coverage reports generation for other languages is not supported yet.
 
@@ -98,7 +99,7 @@
     --corpus-dir=<my_local_corpus_dir> $PROJECT_NAME
 ```
 
-### Additional arguments for `llvm-cov`
+### Additional arguments for `llvm-cov` (C/C++ only)
 
 You may want to use some of the options provided by the [llvm-cov tool], like
 `-ignore-filename-regex=`. You can pass these to the helper script after `--`:
diff --git a/docs/advanced-topics/reproducing.md b/docs/advanced-topics/reproducing.md
index 95bb09c..c2ed147 100644
--- a/docs/advanced-topics/reproducing.md
+++ b/docs/advanced-topics/reproducing.md
@@ -38,7 +38,7 @@
 $ ./fuzz_target_binary <testcase_path>
 ```
 
-For timeout bugs, add the `-timeout=25` argument. For OOM bugs, add the
+For timeout bugs, add the `-timeout=65` argument. For OOM bugs, add the
 `-rss_limit_mb=2560` argument. Read more on [how timeouts and OOMs are
 handled]({{ site.baseurl }}/faq/#how-do-you-handle-timeouts-and-ooms).
 
@@ -82,8 +82,11 @@
   * **memory** for MemorySanitizer.
   * **undefined** for UndefinedBehaviorSanitizer.
 
-**Note**: The `architecture` argument is only necessary if you want to specify
+**Notes**:
+   * The `architecture` argument is only necessary if you want to specify
 `i386` configuration.
+   * Some bugs (specially ones related to pointer and integer overflows) are reproducible only in 32 bit mode or only in 64 bit mode.
+If you can't reproduce a particular bug building for x86_64, try building for i386.
 
 ## Reproducing bugs
 
diff --git a/docs/clusterfuzzlite/advanced/adding_ci_support.md b/docs/clusterfuzzlite/advanced/adding_ci_support.md
new file mode 100644
index 0000000..2e855ed
--- /dev/null
+++ b/docs/clusterfuzzlite/advanced/adding_ci_support.md
@@ -0,0 +1,12 @@
+---
+layout: default
+parent: Advanced Topics
+grand_parent: ClusterFuzzLite
+title: Adding Support for a New CI
+nav_order: 1
+permalink: /clusterfuzzlite/advanced-topics/adding-ci-support/
+---
+
+# Adding Support for a New CI
+
+TODO
diff --git a/docs/clusterfuzzlite/advanced/architecture.md b/docs/clusterfuzzlite/advanced/architecture.md
new file mode 100644
index 0000000..a564f37
--- /dev/null
+++ b/docs/clusterfuzzlite/advanced/architecture.md
@@ -0,0 +1,12 @@
+---
+layout: default
+parent: Advanced Topics
+grand_parent: ClusterFuzzLite
+title: Architecture
+nav_order: 1
+permalink: /clusterfuzzlite/advanced-topics/architecture/
+---
+
+# Architecture
+
+TODO
diff --git a/docs/clusterfuzzlite/advanced_topics.md b/docs/clusterfuzzlite/advanced_topics.md
new file mode 100644
index 0000000..c5b49e1
--- /dev/null
+++ b/docs/clusterfuzzlite/advanced_topics.md
@@ -0,0 +1,10 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Advanced Topics
+has_children: true
+nav_order: 4
+permalink: /clusterfuzzlite/advanced-topics/
+---
+
+# Advanced topics
diff --git a/docs/clusterfuzzlite/build_integration.md b/docs/clusterfuzzlite/build_integration.md
new file mode 100644
index 0000000..7310f7f
--- /dev/null
+++ b/docs/clusterfuzzlite/build_integration.md
@@ -0,0 +1,269 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Build Integration
+has_children: true
+nav_order: 2
+permalink: /clusterfuzzlite/build-integration/
+---
+# Build integration
+{: .no_toc}
+
+- TOC
+{:toc}
+---
+
+## Prerequisites
+ClusterFuzzLite supports statically linked
+[libFuzzer targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) on
+Linux.
+
+We re-use the [OSS-Fuzz](https://github.com/google/oss-fuzz) toolchain to make
+building easier. If you are familiar with this, most of the concepts here are
+exactly the same, with one key difference. Rather than checking out the source
+code in the [`Dockerfile`](#dockerfile) using `git clone`, the `Dockerfile`
+copies in the source code directly during `docker build`.
+
+Before you can start setting up your new project for fuzzing, you must do the following:
+- [Integrate]({{ site.baseurl }}/advanced-topics/ideal-integration/) one or more [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
+  with the project you want to fuzz. For examples, see TODO.
+- [Install Docker](https://docs.docker.com/engine/installation)
+  [Why Docker?]({{ site.baseurl }}/faq/#why-do-you-use-docker)
+
+  If you want to run `docker` without `sudo`, you can
+  [create a docker group](https://docs.docker.com/engine/installation/linux/ubuntulinux/#/create-a-docker-group).
+
+  **Note:** Docker images can consume significant disk space. Run
+  [docker-cleanup](https://gist.github.com/mikea/d23a839cba68778d94e0302e8a2c200f)
+  periodically to garbage-collect unused images.
+
+- Clone the OSS-Fuzz repo: `git clone https://github.com/google/oss-fuzz.git`
+
+## Generating an empty build integration
+
+Build integrations consist of three configuration files:
+* [./clusterfuzzlite/project.yaml](#projectyaml) - provides metadata about the project.
+* [./clusterfuzzlite/Dockerfile](#dockerfile) - defines the container environment with information
+on dependencies needed to build the project and its [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
+* [./clusterfuzzlite/build.sh](#buildsh) - defines the build script that executes inside the Docker container and
+generates the project build.
+
+These must live in the `.clusterfuzzlite` directory in the root of your
+project's source code checkout.
+
+You can generate empty versions of these files with the following command:
+
+```bash
+$ cd /path/to/oss-fuzz
+$ export PATH_TO_PROJECT=<path_to_your_project>
+$ python infra/helper.py generate $PATH_TO_PROJECT --external
+```
+
+Once the configuration files are generated, you should modify them to fit your
+project.
+
+## project.yaml {#projectyaml}
+
+This configuration file stores project metadata. The following attributes are
+supported:
+
+- [language](#language)
+
+### language
+
+Programming language the project is written in. Values you can specify include:
+
+* `c`
+* `c++`
+* [`go`]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/)
+* [`rust`]({{ site.baseurl }}//getting-started/new-project-guide/rust-lang/)
+* [`python`]({{ site.baseurl }}//getting-started/new-project-guide/python-lang/)
+* [`jvm` (Java, Kotlin, Scala and other JVM-based languages)]({{ site.baseurl }}//getting-started/new-project-guide/jvm-lang/)
+
+## Dockerfile {#dockerfile}
+
+This integration file defines the Docker image for your project.
+Your [build.sh](#buildsh) script will be executed in inside the container you
+define.
+For most projects, the image is simple:
+```docker
+FROM gcr.io/oss-fuzz-base/base-builder          # base image with clang toolchain
+RUN apt-get update && apt-get install -y ...    # install required packages to build your project
+COPY . $SRC/<project_name>                      # checkout all sources needed to build your project
+WORKDIR $SRC/<project_name>                     # current directory for the build script
+COPY ./clusterfuzzlite/build.sh fuzzer.cc $SRC/ # copy build script into src dir
+```
+TODO: Provide examples.
+
+## build.sh {#buildsh}
+
+This file defines how to build binaries for [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your project.
+The script is executed within the image built from your [Dockerfile](#Dockerfile).
+
+In general, this script should do the following:
+
+- Build the project using your build system with OSS-Fuzz's compiler.
+- Provide OSS-Fuzz's compiler flags (defined as [environment variables](#Requirements)) to the build system.
+- Build your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
+  and link your project's build with `$LIB_FUZZING_ENGINE` (libFuzzer).
+
+Resulting binaries should be placed in `$OUT`.
+
+Here's an example from Expat
+([source](https://github.com/google/oss-fuzz/blob/master/projects/expat/build.sh)):
+
+```bash
+#!/bin/bash -eu
+
+./buildconf.sh
+# configure scripts usually use correct environment variables.
+./configure
+
+make clean
+make -j$(nproc) all
+
+$CXX $CXXFLAGS -std=c++11 -Ilib/ \
+    $SRC/parse_fuzzer.cc -o $OUT/parse_fuzzer \
+    $LIB_FUZZING_ENGINE .libs/libexpat.a
+
+cp $SRC/*.dict $SRC/*.options $OUT/
+```
+
+If your project is written in Go, check out the [Integrating a Go project]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/) page.
+
+**Note:**
+1. Make sure that the binary names for your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) contain only
+alphanumeric characters, underscore(_) or dash(-). Otherwise, they won't run.
+1. Don't remove source code files. They are needed for code coverage.
+
+
+### Temporarily disabling code instrumentation during builds
+
+In some cases, it's not necessary to instrument every 3rd party library or tool that supports the build target. Use the following snippet to build tools or libraries without instrumentation:
+
+```
+CFLAGS_SAVE="$CFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS"
+unset CFLAGS
+unset CXXFLAGS
+export AFL_NOOPT=1
+
+#
+# build commands here that should not result in instrumented code.
+#
+
+export CFLAGS="${CFLAGS_SAVE}"
+export CXXFLAGS="${CXXFLAGS_SAVE}"
+unset AFL_NOOPT
+```
+TODO: Figure out if we should include this AFL code.
+
+### build.sh script environment
+
+When your build.sh script is executed, the following locations are available within the image:
+
+| Location| Env Variable | Description |
+|---------| ------------ | ----------  |
+| `/out/` | `$OUT`         | Directory to store build artifacts (fuzz targets, dictionaries, options files, seed corpus archives). |
+| `/src/` | `$SRC`         | Directory to checkout source files. |
+| `/work/`| `$WORK`        | Directory to store intermediate files. |
+
+Although the files layout is fixed within a container, environment variables are
+provided so you can write retargetable scripts.
+
+In case your fuzz target uses the [FuzzedDataProvider] class, make sure it is
+included via `#include <fuzzer/FuzzedDataProvider.h>` directive.
+
+[FuzzedDataProvider]: https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider
+
+### build.sh requirements {#Requirements}
+
+Only binaries without an extension are accepted as targets. Extensions are reserved for other artifacts, like .dict.
+
+You *must* use the special compiler flags needed to build your project and fuzz targets.
+These flags are provided in the following environment variables:
+
+| Env Variable           | Description
+| -------------          | --------
+| `$CC`, `$CXX`, `$CCC`  | The C and C++ compiler binaries.
+| `$CFLAGS`, `$CXXFLAGS` | C and C++ compiler flags.
+| `$LIB_FUZZING_ENGINE`  | C++ compiler argument to link fuzz target against the prebuilt engine library (e.g. libFuzzer).
+
+You *must* use `$CXX` as a linker, even if your project is written in pure C.
+
+Most well-crafted build scripts will automatically use these variables. If not,
+pass them manually to the build tool.
+
+See the [Provided Environment Variables](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/README.md#provided-environment-variables) section in
+`base-builder` image documentation for more details.
+
+## Fuzzer execution environment
+
+For more on the environment that
+your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) run in, and the assumptions you can make, see the [fuzzer environment]({{ site.baseurl }}/further-reading/fuzzer-environment/) page.
+
+## Testing locally
+
+You can build your docker image and fuzz targets locally, so you can test them
+before running ClusterFuzzLite.
+1. Run the same helper script you used to create your directory structure, this time using it to build your docker image and [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target):
+
+    ```bash
+    $ cd /path/to/oss-fuzz
+    $ python infra/helper.py build_image $PATH_TO_PROJECT --external
+    $ python infra/helper.py build_fuzzers $PATH_TO_PROJECT --sanitizer <address/undefined/coverage> --external
+    ```
+
+    The built binaries appear in the `/path/to/oss-fuzz/build/out/$PROJECT_NAME`
+    directory on your machine (and `$OUT` in the container). Note that
+    `$PROJECT_NAME` is the name of the directory of your project (e.g. if
+    `$PATH_TO_PROJECT` is `/path/to/systemd`, `$PROJECT_NAME` is systemd.
+
+    **Note:** You *must* run your fuzz target binaries inside the base-runner docker
+    container to make sure that they work properly.
+
+2. Find failures to fix by running the `check_build` command:
+
+    ```bash
+    $ python infra/helper.py check_build $PATH_TO_PROJECT --external
+    ```
+
+3. If you want to test changes against a particular fuzz target, run the following command:
+
+    ```bash
+    $ python infra/helper.py run_fuzzer --external --corpus-dir=<path-to-temp-corpus-dir> $PATH_TO_PROJECT <fuzz_target>
+    ```
+
+4. We recommend taking a look at your code coverage as a test to ensure that
+your fuzz targets get to the code you expect. This would use the corpus
+generated from the previous `run_fuzzer` step in your local corpus directory.
+
+    ```bash
+    $ python infra/helper.py build_fuzzers --sanitizer coverage $PATH_TO_PROJECT
+    $ python infra/helper.py coverage $PATH_TO_PROJECT --fuzz-target=<fuzz_target> --corpus-dir=<path-to-temp-corpus-dir> --external
+    ```
+
+You may need to run `python infra/helper.py pull_images` to use the latest
+coverage tools. Please refer to
+[code coverage]({{ site.baseurl }}/advanced-topics/code-coverage/) for detailed
+information on code coverage generation.
+
+**Note:** Currently, ClusterFuzzLite only supports AddressSanitizer (address)
+and UndefinedBehaviorSanitizer (undefined) configurations.
+<b>Make sure to test each
+of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage).</b>
+
+If everything works locally, it should also work on ClusterFuzzLite. If you
+check in your files and experience failures, review your [dependencies]({{site.baseurl }}/further-reading/fuzzer-environment/#dependencies).
+
+## Debugging Problems
+
+If you run into problems, the [Debugging page]({{ site.baseurl }}/advanced-topics/debugging/) lists ways to debug your build scripts and
+[fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
+
+## Efficient fuzzing
+
+To improve your fuzz target ability to find bugs faster, please read [this section](
+{{ site.baseurl }}/getting-started/new-project-guide/#efficient-fuzzing).
+
+TODO(metzman): We probably want a TOC for lang-specific guides (which we still need to add).
diff --git a/docs/clusterfuzzlite/clusterfuzzlite.md b/docs/clusterfuzzlite/clusterfuzzlite.md
new file mode 100644
index 0000000..9dfd30a
--- /dev/null
+++ b/docs/clusterfuzzlite/clusterfuzzlite.md
@@ -0,0 +1,27 @@
+---
+layout: default
+title: ClusterFuzzLite
+has_children: true
+nav_order: 8
+permalink: /clusterfuzzlite/
+<!-- Hide for now by setting "published: false" -->
+published: false
+---
+
+# ClusterFuzzLite
+ClusterFuzzLite is a lightweight, easy-to-use, fuzzing infrastructure that is
+based off [ClusterFuzz]. ClusterFuzzLite is designed to run on [continuous integration] (CI)
+systems, which means it is easy to set up and provides a familiar interface for
+users.
+Currently CIFuzz fully supports [GitHub Actions]. However ClusterFuzzLite is
+designed so that supporting new CI systems is trivial and core features can be
+used on any CI system without any additional effort.
+
+See [Overview] for a more detailed description of how ClusterFuzzLite works and
+how you can use it.
+
+[continous integration]: https://en.wikipedia.org/wiki/Continuous_integration
+[fuzzing]: https://en.wikipedia.org/wiki/Fuzzing
+[ClusterFuzz]: https://google.github.io/clusterfuzz/
+[GitHub Actions]: https://docs.github.com/en/actions
+[Overview]: {{ site.baseurl }}/clusterfuzzlite/overview/
diff --git a/docs/clusterfuzzlite/overview.md b/docs/clusterfuzzlite/overview.md
new file mode 100644
index 0000000..5e1e249
--- /dev/null
+++ b/docs/clusterfuzzlite/overview.md
@@ -0,0 +1,29 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Overview
+nav_order: 1
+permalink: /clusterfuzzlite/overview/
+---
+
+# Overview
+
+ClusterFuzzLite makes fuzzing more valuable by:
+* Fuzzing continuously.
+* Catching bugs before they land in your codebase by fuzzing pull
+  requests/commits.
+* Providing coverage reports on which code is fuzzed.
+* Managing your corpus, pruning it daily or a specified-interval.
+
+ClusterFuzzLite supports [libFuzzer], [AddressSanitizer], and
+[UndefinedBehavior].
+ClusterFuzzLite is modular, so you can decide which features you want to use.
+Using ClusterFuzzLite entails two major steps:
+1. [Integrating with ClusterFuzzLite's build system] so ClusterFuzzLite can
+   build your project's fuzzers.
+2. [Running ClusterFuzzLite].
+[libFuzzer]: https://libfuzzer.info
+[AddressSanitizer]: https://clang.llvm.org/docs/AddressSanitizer.html
+[UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
+[Integrating with ClusterFuzzLite's build system]: {{ site.baseurl }}/clusterfuzzlite/build-integration/
+[Running ClusterFuzzLite]: {{ site.baseurl }}/clusterfuzzlite/running-clusterfuzzlite/
diff --git a/docs/clusterfuzzlite/running-clusterfuzzlite/generic.md b/docs/clusterfuzzlite/running-clusterfuzzlite/generic.md
new file mode 100644
index 0000000..045cd24
--- /dev/null
+++ b/docs/clusterfuzzlite/running-clusterfuzzlite/generic.md
@@ -0,0 +1,17 @@
+---
+layout: default
+parent: Running ClusterFuzzLite
+grand_parent: ClusterFuzzLite
+title: Running ClusterFuzzLite in a Generic Environment
+nav_order: 2
+permalink: /clusterfuzzlite/running-clusterfuzzlite/generic/
+---
+
+# Running ClusterFuzzLite in a Generic Environment
+TODO: Rename run_cifuzz.py to run_clusterfuzzlite.py
+
+This page describes how to run clusterfuzzlite using the run_clusterfuzzlite.py
+script, a low level script that is used by CI systems to run ClusterFuzzLite.
+This guide is useful if you want to run ClusterFuzzLite outside of CI or if you
+want to run it on a CI system that isn't supported yet.
+TODO
diff --git a/docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md b/docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md
new file mode 100644
index 0000000..430f675
--- /dev/null
+++ b/docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md
@@ -0,0 +1,12 @@
+---
+layout: default
+parent: Running ClusterFuzzLite
+grand_parent: ClusterFuzzLite
+title: GitHub Actions
+nav_order: 1
+permalink: /clusterfuzzlite/running-clusterfuzzlite/github-actions/
+---
+
+# GitHub Actions
+
+TODO
diff --git a/docs/clusterfuzzlite/running_clusterfuzzlite.md b/docs/clusterfuzzlite/running_clusterfuzzlite.md
new file mode 100644
index 0000000..068fc03
--- /dev/null
+++ b/docs/clusterfuzzlite/running_clusterfuzzlite.md
@@ -0,0 +1,101 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Running ClusterFuzzLite
+has_children: true
+nav_order: 3
+permalink: /clusterfuzzlite/running-clusterfuzzlite/
+---
+# Running ClusterFuzzLite
+{: .no_toc}
+
+- TOC
+{:toc}
+---
+
+## Overview
+TODO: add a diagram.
+
+Once your project's fuzzers can be built and run by the helper script, it is
+ready to be fuzzed by ClusterFuzzLite.
+The exact method for doing this will depend on the how you are running
+ClusterFuzzLite. For guides on how to run ClusterFuzzLite in your particular
+environment (e.g. GitHub Actions) see the subguides.
+The rest of this page will explain concepts configuration options and that are
+agnostic to how ClusterFuzzLite is being run.
+
+## ClusterFuzzLite Tasks
+
+ClusterFuzzLite has the concept of tasks which instruct ClusterFuzzLite what to
+do when running.
+
+### Code Review Fuzzing
+
+TODO(metzman): Work on a generic name for CIFuzz/PR fuzzing.
+
+One of the core ways for ClusterFuzzLite to be used is for fuzzing code that is
+in review that was just commited.
+This use-case is important because it allows ClusterFuzzLite to find bugs before
+they are commited into your code and while they are easiest to fix.
+To use Code Review Fuzzing, set the configuration option `clusterfuzzlite-task`
+to `code-review`.
+If you are familiar with OSS-Fuzz's CIFuzz, this task is similar to CIFuzz.
+Running other ClusterFuzzLite tasks enhances ClusterFuzzLite's ability to do
+Code Review Fuzzing.
+
+If [Batch Fuzzing] is enabled, Code Review Fuzzing will report only newly
+introduced bugs and use the corpus developed during batch fuzzing.
+If [Code Coverage Reporting] is enabled, Code Review Fuzzing will try to only
+run the fuzzers affected by the code change.
+
+### Batch Fuzzing
+
+ClusterFuzzLite can also run in a batch fuzzing mode where all fuzzers are run
+for a long amount of time. Unlike Code Review Fuzzing, this task is not meant to
+be interactive, it is meant to be long-lasting and generally is more similar to
+fuzzing in ClusterFuzz than Code Review Fuzzing. Batch Fuzzing allows
+ClusterFuzzLite to build up a corpus for each of your fuzz targets. This corpus
+will be used in Code Coverage Reporting as well as Code Review Fuzzing.
+
+### Corpus Prune
+
+If multiple Batch Fuzzing tasks are run concurrently then we strongly recommend
+running a pruning task as well. This task is run according to some set schedule
+(once a day is probably sufficient) to prune the corpus of redundant testcases,
+which can happen if multiple Batch Fuzzing jobs are done concurrently.
+
+### Code Coverage Report
+
+The last task ClusterFuzzLite offers is Code Coverage Reports. This task will
+run your fuzzers on the corpus developed during Batch Fuzzing and will generate
+an HTML report that shows you which part of your code is covered by batch
+fuzzing.
+
+## Configuration Options
+
+Below are some configuration options that you can set when running
+ClusterFuzzLite.
+We will explain how to set these in each of the subguides.
+
+`language`: (optional) The language your target program is written in. Defaults
+to `c++`. This should be the same as the value you set in `project.yaml`. See
+[this explanation]({{ site.baseurl }}//getting-started/new-project-guide/#language)
+for more details.
+
+`fuzz-time`: Determines how long ClusterFuzzLite spends fuzzing your project in
+seconds. The default is 600 seconds.
+
+`sanitizer`: Determines a sanitizer to build and run fuzz targets with. The
+choices are `'address'`, and `'undefined'`. The default is `'address'`.
+
+`task`: The task for ClusterFuzzLite to execute. `code-review`
+by default. See [ClusterFuzzLite Tasks] for more details on how to run different
+tasks.
+TODO(metzman): change run_fuzzers_mode to this.
+
+`dry-run`: Determines if ClusterFuzzLite surfaces bugs/crashes. The default
+value is `false`. When set to `true`, ClusterFuzzLite will never report a
+failure even if it finds a crash in your project. This requires the user to
+manually check the logs for detected bugs.
+
+TODO(metzman): We probably want a TOC on this page for subguides.
diff --git a/docs/further-reading/clusterfuzz.md b/docs/further-reading/clusterfuzz.md
index 92d85ff..308882c 100644
--- a/docs/further-reading/clusterfuzz.md
+++ b/docs/further-reading/clusterfuzz.md
@@ -46,7 +46,7 @@
 
 We provide coverage reports, where we highlight the parts of source code that
 are being reached by your fuzz target. Make sure to look at the uncovered code
-marked in red and add appropriate fuzz targets to cover those usecases.
+marked in red and add appropriate fuzz targets to cover those use cases.
 
 ![coverage_1]({{ site.baseurl }}/images/freetype_coverage_1.png?raw=true)
 ![coverage_2]({{ site.baseurl }}/images/freetype_coverage_2.png?raw=true)
diff --git a/docs/further-reading/fuzzer_environment.md b/docs/further-reading/fuzzer_environment.md
index 7c527ec..c42bf45 100644
--- a/docs/further-reading/fuzzer_environment.md
+++ b/docs/further-reading/fuzzer_environment.md
@@ -9,8 +9,7 @@
 # Fuzzer environment on ClusterFuzz
 
 Your fuzz targets will be run on a
-[Google Compute Engine](https://cloud.google.com/compute/) VM (Linux) with some
-[security restrictions](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-runner/run_minijail).
+[Google Compute Engine](https://cloud.google.com/compute/) VM (Linux).
 
 - TOC
 {:toc}
@@ -43,7 +42,7 @@
 However dynamic linking can work if shared objects are included in the `$OUT` directory and are loaded relative
 to `'$ORIGIN'`, the path of the binary (see the discussion of `'$ORIGIN'` [here](http://man7.org/linux/man-pages/man8/ld.so.8.html)).
 A fuzzer can be instructed to load libraries relative to `'$ORIGIN'` during compilation (i.e. `-Wl,-rpath,'$ORIGIN/lib'` )
-or afterwards using `chrpath -r '$ORIGIN/lib' $OUT/$fuzzerName` ([example](https://github.com/google/oss-fuzz/blob/09aa9ac556f97bd4e31928747eca0c8fed42509f/projects/php/build.sh#L40)). Note that `'$ORIGIN'` should be surronded
+or afterwards using `chrpath -r '$ORIGIN/lib' $OUT/$fuzzerName` ([example](https://github.com/google/oss-fuzz/blob/09aa9ac556f97bd4e31928747eca0c8fed42509f/projects/php/build.sh#L40)). Note that `'$ORIGIN'` should be surrounded
 by single quotes because it is not an environment variable like `$OUT` that can be retrieved during execution of `build.sh`.
 Its value is retrieved during execution of the binary. You can verify that you did this correctly using `ldd <fuzz_target_name>` and the `check_build` command in `infra/helper.py`.
 
diff --git a/docs/getting-started/accepting_new_projects.md b/docs/getting-started/accepting_new_projects.md
index b0ae1f9..898d68b 100644
--- a/docs/getting-started/accepting_new_projects.md
+++ b/docs/getting-started/accepting_new_projects.md
@@ -19,12 +19,12 @@
     **Note:** `project_name` can only contain alphanumeric characters,
     underscores(_) or dashes(-).
 2. In the file, provide the following information:
-  - Your project's homepage.
-  - An email address for the engineering contact to be CCed on new issues, satisfying the following:
-        - The address belongs to an established project committer (according to VCS logs).
+  * Your project's homepage.
+  * An email address for the engineering contact to be CCed on new issues, satisfying the following:
+       * The address belongs to an established project committer (according to VCS logs).
         If the address isn't you, or if the address differs from VCS, we'll require an informal
         email verification.
-        - The address is associated with a Google account
+       * The address is associated with a Google account
         ([why?]({{ site.baseurl }}/faq/#why-do-you-require-a-google-account-for-authentication)).
         If you use an alternate email address
         [linked to a Google Account](https://support.google.com/accounts/answer/176347?hl=en),
diff --git a/docs/getting-started/continuous_integration.md b/docs/getting-started/continuous_integration.md
index 88e6e4b..7a6a305 100644
--- a/docs/getting-started/continuous_integration.md
+++ b/docs/getting-started/continuous_integration.md
@@ -21,11 +21,11 @@
 input available for download and the CI test fails (red X).
 
 If CIFuzz doesn't find a crash during the allotted time, the CI test passes
-(green check). If CIFuzz finds a crash, it reports the crash only:
-* If the crash is reproducible (on the PR/commit build).
-* If the crash does not occur on older OSS-Fuzz builds. Because if it does occur
-  on older builds that means the crash was not introduced by the PR/commit
-  CIFuzz is testing.
+(green check). If CIFuzz finds a crash, it reports the crash only if both of following are true:
+* The crash is reproducible (on the PR/commit build).
+* The crash does not occur on older OSS-Fuzz builds. (If the crash does occur
+  on older builds, then it was not introduced by the PR/commit
+  being tested.)
 
 If your project supports [OSS-Fuzz's code coverage]({{ site.baseurl }}/advanced-topics/code-coverage),
 CIFuzz only runs the fuzzers affected by a pull request/commit.
@@ -39,6 +39,7 @@
 
 1. Your project must be integrated with OSS-Fuzz.
 1. Your project is hosted on GitHub.
+1. Your repository needs to be cloned with `git` in oss-fuzz Dockerfile (do not use `go get` or other methods)
 
 ## Integrating into your repository
 
diff --git a/docs/getting-started/new-project-guide/bazel.md b/docs/getting-started/new-project-guide/bazel.md
index 45b942f..4af640e 100644
--- a/docs/getting-started/new-project-guide/bazel.md
+++ b/docs/getting-started/new-project-guide/bazel.md
@@ -28,7 +28,7 @@
 for defining fuzz tests. `rules_fuzzing` provides support for building and running
 fuzz tests under
 [multiple sanitizer and fuzzing engine configurations][rules-fuzzing-usage].
-It also supports specifying corpora and dictionaires as part of the fuzz test
+It also supports specifying corpora and dictionaries as part of the fuzz test
 definition.
 
 The fuzzing rules provide out-of-the-box support for building and packaging fuzz
@@ -84,12 +84,12 @@
 tool that implements these steps in a standard way, so in most cases your
 build script only needs to invoke this command with no arguments.
 
-If necessary, the behavior of the tool can be customized though a set of
+If necessary, the behavior of the tool can be customized through a set of
 environment variables. The most common are:
 
 * `BAZEL_EXTRA_BUILD_FLAGS` are extra build flags passed on the Bazel command
    line.
-* `BAZEL_FUZZ_TEST_TAG` and `BAZEL_FUZZ_TEST_EXCLUDE_TAG` can be overriden to
+* `BAZEL_FUZZ_TEST_TAG` and `BAZEL_FUZZ_TEST_EXCLUDE_TAG` can be overridden to
   specify which target tags to use when determining what fuzz tests to include.
   By default, the tool selects all the fuzz tests except for those tagged as
   `"no-oss-fuzz"`.
diff --git a/docs/getting-started/new-project-guide/go_lang.md b/docs/getting-started/new-project-guide/go_lang.md
index 600a666..f64e691 100644
--- a/docs/getting-started/new-project-guide/go_lang.md
+++ b/docs/getting-started/new-project-guide/go_lang.md
@@ -59,6 +59,8 @@
 
 ### Dockerfile
 
+The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-go`
+
 The OSS-Fuzz builder image has the latest stable release of Golang installed. In
 order to install dependencies of your project, add `RUN git clone ...` command to
 your Dockerfile.
diff --git a/docs/getting-started/new-project-guide/jvm_lang.md b/docs/getting-started/new-project-guide/jvm_lang.md
index 19e4ecb..5d25d3c 100644
--- a/docs/getting-started/new-project-guide/jvm_lang.md
+++ b/docs/getting-started/new-project-guide/jvm_lang.md
@@ -50,8 +50,9 @@
 ```
 
 The only supported fuzzing engine is libFuzzer (`libfuzzer`). So far the only
-supported sanitizer is AddressSanitizer (`address`), which needs to be
-specified explicitly even for pure Java projects.
+supported sanitizers are AddressSanitizer (`address`) and
+UndefinedBehaviorSanitizer (`undefined`). For pure Java projects, specify
+just `address`:
 
 ```yaml
 fuzzing_engines:
@@ -62,6 +63,8 @@
 
 ### Dockerfile
 
+The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-jvm`
+
 The OSS-Fuzz base Docker images already come with OpenJDK 15 pre-installed. If
 you need Maven to build your project, you can install it by adding the following
 line to your Dockerfile:
@@ -135,12 +138,16 @@
 \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
 --cp=$RUNTIME_CLASSPATH \
 --target_class=$fuzzer_basename \
---jvm_args=\"-Xmx2048m\" \
+--jvm_args=\"-Xmx2048m;-Djava.awt.headless=true\" \
 \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
 ```
 
+The [java-example](https://github.com/google/oss-fuzz/blob/master/projects/java-example/build.sh)
+project contains an example of a `build.sh` for Java projects with native
+libraries.
+
 ## FuzzedDataProvider
 
 Jazzer provides a `FuzzedDataProvider` that can simplify the task of creating a
diff --git a/docs/getting-started/new-project-guide/python_lang.md b/docs/getting-started/new-project-guide/python_lang.md
index da14780..1174410 100644
--- a/docs/getting-started/new-project-guide/python_lang.md
+++ b/docs/getting-started/new-project-guide/python_lang.md
@@ -57,6 +57,8 @@
 
 ### Dockerfile
 
+The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-python`
+
 Because most dependencies are already pre-installed on the images, no
 significant changes are needed in the Dockerfile for Python fuzzing projects.
 You should simply clone the project, set a `WORKDIR`, and copy any necessary
@@ -97,7 +99,7 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
 ```
 
diff --git a/docs/getting-started/new-project-guide/rust_lang.md b/docs/getting-started/new-project-guide/rust_lang.md
index c28dd76..11a3b51 100644
--- a/docs/getting-started/new-project-guide/rust_lang.md
+++ b/docs/getting-started/new-project-guide/rust_lang.md
@@ -61,6 +61,8 @@
 
 ### Dockerfile
 
+The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-rust`
+
 The OSS-Fuzz builder image has the latest nightly release of Rust as well as
 `cargo fuzz` pre-installed and in `PATH`. In the `Dockerfile` for your project
 all you'll need to do is fetch the latest copy of your code and install any
@@ -100,3 +102,47 @@
     cp $FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME $OUT/
 done
 ```
+
+## Writing fuzzers using a test-style strategy
+
+In Rust you will often have tests written in a way so they are only 
+compiled into the final binary when build in test-mode. This is, achieved by
+wrapping your test code in `cfg(test)`, e.g.
+```rust
+#[cfg(test)]
+mod tests {
+    use super::*;
+    
+    ...
+```
+
+Cargo-fuzz automatically enables the `fuzzing` feature, which means you can
+follow a similar strategy to writing fuzzers as you do when writing tests.
+Specifically, you can create modules wrapped in the `fuzzing` feature:
+```rust
+#[cfg(fuzzing)]
+pub mod fuzz_logic {
+    use super::*;
+
+    ...
+```
+and then call the logic within `fuzz_logic` from your fuzzer. 
+
+Furthermore, within your `.toml` files, you can then specify fuzzing-specific
+depedencies by wrapping them as follows:
+```
+[target.'cfg(fuzzing)'.dependencies]
+```
+similar to how you wrap test-dependencies as follows:
+```
+[dev-dependencies]
+```
+
+Finally, you can also combine the testing logic you have and the fuzz logic. This
+can be achieved simply by using 
+```rust
+#[cfg(any(test, fuzzing))]
+```
+
+A project that follows this structure is Linkerd2-proxy and the project files can be
+seen [here](https://github.com/google/oss-fuzz/tree/master/projects/linkerd2-proxy).
diff --git a/docs/getting-started/new-project-guide/swift.md b/docs/getting-started/new-project-guide/swift.md
new file mode 100644
index 0000000..dbb127b
--- /dev/null
+++ b/docs/getting-started/new-project-guide/swift.md
@@ -0,0 +1,78 @@
+---
+layout: default
+title: Integrating a Swift project
+parent: Setting up a new project
+grand_parent: Getting started
+nav_order: 1
+permalink: /getting-started/new-project-guide/swift/
+---
+
+# Integrating a Swift project
+{: .no_toc}
+
+- TOC
+{:toc}
+---
+
+The process of integrating a project written in Swift with OSS-Fuzz is very similar
+to the general
+[Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/)
+process. The key specifics of integrating a Swift project are outlined below.
+
+## Project files
+
+First, you need to write a Swift fuzz target that accepts a stream of bytes and
+calls the program API with that. This fuzz target should reside in your project
+repository.
+
+The structure of the project directory in OSS-Fuzz repository doesn't differ for
+projects written in Swift. The project files have the following Swift specific
+aspects.
+
+### project.yaml
+
+The `language` attribute must be specified.
+
+```yaml
+language: swift
+```
+
+The only supported fuzzing engine is `libfuzzer`
+
+The supported sanitizers are and `address`, `thread`
+
+[Example](https://github.com/google/oss-fuzz/blob/2a15c3c88b21f4f1be2a7ff115f72bd7a08e34ac/projects/swift-nio/project.yaml#L9):
+
+```yaml
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+  - thread
+```
+
+### Dockerfile
+
+The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-swift`
+instead of using the simple base-builder
+
+### build.sh
+
+A `precompile_swift` generates an environment variable `SWIFTFLAGS`
+This can then be used in the building command such as `swift build -c release $SWIFTFLAGS`
+
+
+A usage example from swift-protobuf project is
+
+```sh
+. precompile_swift
+# build project
+cd FuzzTesting
+swift build -c debug $SWIFTFLAGS
+
+(
+cd .build/debug/
+find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-debug; done
+)
+
+```
diff --git a/docs/getting-started/new_project_guide.md b/docs/getting-started/new_project_guide.md
index d2a7d80..7ac0d2a 100644
--- a/docs/getting-started/new_project_guide.md
+++ b/docs/getting-started/new_project_guide.md
@@ -50,10 +50,10 @@
 
 Each project directory also contains the following three configuration files:
 
-* [project.yaml](#project.yaml) - provides metadata about the project.
-* [Dockerfile](#Dockerfile) - defines the container environment with information
+* [project.yaml](#projectyaml) - provides metadata about the project.
+* [Dockerfile](#dockerfile) - defines the container environment with information
 on dependencies needed to build the project and its [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target).
-* [build.sh](#build.sh) - defines the build script that executes inside the Docker container and
+* [build.sh](#buildsh) - defines the build script that executes inside the Docker container and
 generates the project build.
 
 You can automatically create a new directory for your project in OSS-Fuzz and
@@ -63,14 +63,15 @@
 ```bash
 $ cd /path/to/oss-fuzz
 $ export PROJECT_NAME=<project_name>
-$ python infra/helper.py generate $PROJECT_NAME
+$ export LANGUAGE=<project_language>
+$ python infra/helper.py generate $PROJECT_NAME --language=$LANGUAGE
 ```
 
 Once the template configuration files are created, you can modify them to fit your project.
 
 **Note:** We prefer that you keep and maintain [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your own source code repository. If this isn't possible, you can store them inside the OSS-Fuzz project directory you created.
 
-## project.yaml
+## project.yaml {#projectyaml}
 
 This configuration file stores project metadata. The following attributes are supported:
 
@@ -98,6 +99,7 @@
 * [`rust`]({{ site.baseurl }}//getting-started/new-project-guide/rust-lang/)
 * [`python`]({{ site.baseurl }}//getting-started/new-project-guide/python-lang/)
 * [`jvm` (Java, Kotlin, Scala and other JVM-based languages)]({{ site.baseurl }}//getting-started/new-project-guide/jvm-lang/)
+* [`swift`]({{ site.baseurl }}//getting-started/new-project-guide/swift/)
 
 ### primary_contact, auto_ccs {#primary}
 The primary contact and list of other contacts to be CCed. Each person listed gets access to ClusterFuzz, including crash reports and fuzzer statistics, and are auto-cced on new bugs filed in the OSS-Fuzz
@@ -121,9 +123,11 @@
 
 [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) ("memory") is also supported
 and recommended, but is not enabled by default due to the likelihood of false positives from
-un-instrumented system dependencies. If you want to use "memory," first make sure your project's
-runtime dependencies are listed in the OSS-Fuzz
-[msan-libs-builder Dockerfile](https://github.com/google/oss-fuzz/blob/master/infra/base-images/msan-libs-builder/Dockerfile#L20).
+un-instrumented system dependencies.
+If you want to use "memory," please build all libraries your project needs using
+MemorySanitizer.
+This can be done by building them with the compiler flags provided during
+MemorySanitizer builds.
 Then, you can opt in by adding "memory" to your list of sanitizers.
 
 If your project does not build with a particular sanitizer configuration and you need some time to fix
@@ -169,6 +173,11 @@
 Fuzzing on i386 is not enabled by default because many projects won't build for i386 without some modification to their OSS-Fuzz build process.
 For example, you will need to link against `$LIB_FUZZING_ENGINE` and possibly install i386 dependencies within the x86_64 docker image ([for example](https://github.com/google/oss-fuzz/blob/5b8dcb5d942b3b8bc173b823fb9ddbdca7ec6c99/projects/gdal/build.sh#L18)) to get things working.
 
+### fuzzing_engines (optional) {#fuzzing_engines}
+The list of fuzzing engines to use.
+By default, `libfuzzer`, `afl`, and `honggfuzz` are used. It is recommended to
+use all of them if possible. `libfuzzer` is required by OSS-Fuzz.
+
 ### help_url (optional) {#help_url}
 A link to a custom help URL that appears in bug reports instead of the default
 [OSS-Fuzz guide to reproducing crashes]({{ site.baseurl }}/advanced-topics/reproducing/). This can be useful if you assign
@@ -187,9 +196,9 @@
 
 Will build the project twice per day.
 
-## Dockerfile
+## Dockerfile {#dockerfile}
 
-This configuration file defines the Docker image for your project. Your [build.sh](#build.sh) script will be executed in inside the container you define.
+This configuration file defines the Docker image for your project. Your [build.sh](#buildsh) script will be executed in inside the container you define.
 For most projects, the image is simple:
 ```docker
 FROM gcr.io/oss-fuzz-base/base-builder       # base image with clang toolchain
@@ -200,12 +209,22 @@
 ```
 In the above example, the git clone will check out the source to `$SRC/<checkout_dir>`.
 
+Depending on your project's language, you will use a different base image,
+for instance `FROM gcr.io/oss-fuzz-base/base-builder-go` for golang.
+
 For an example, see
 [expat/Dockerfile](https://github.com/google/oss-fuzz/tree/master/projects/expat/Dockerfile)
 or
 [syzkaller/Dockerfile](https://github.com/google/oss-fuzz/blob/master/projects/syzkaller/Dockerfile).
 
-## build.sh
+In the case of a project with multiple languages/toolchains needed,
+you can run installation scripts `install_lang.sh` where lang is the language needed.
+You also need to setup environment variables needed by this toolchain, for example `GOPATH` is needed by golang.
+For an example, see
+[ecc-diff-fuzzer/Dockerfile](https://github.com/google/oss-fuzz/blob/master/projects/ecc-diff-fuzzer/Dockerfile).
+where we use `base-builder-rust`and install golang
+
+## build.sh {#buildsh}
 
 This file defines how to build binaries for [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your project.
 The script is executed within the image built from your [Dockerfile](#Dockerfile).
@@ -248,11 +267,8 @@
 
 ### Temporarily disabling code instrumentation during builds
 
-Sometimes not every 3rd party library might be needed to be instrumented or
-tools are being compiled that just support the target built.
+In some cases, it's not necessary to instrument every 3rd party library or tool that supports the build target. Use the following snippet to build tools or libraries without instrumentation:
 
-If for any reasons part of the build process should not be instrumented
-then the following code snippit can be used for this:
 
 ```
 CFLAGS_SAVE="$CFLAGS"
@@ -309,6 +325,14 @@
 See the [Provided Environment Variables](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/README.md#provided-environment-variables) section in
 `base-builder` image documentation for more details.
 
+### Static and dynamic linking of libraries
+The `build.sh` should produce fuzzers that are statically linked. This is because the
+fuzzer build environment is different to the fuzzer runtime environment and if your
+project depends on third party libraries then it is likely they will not be present
+in the execution environment. Thus, any shared libraries you may install or compile in
+`build.sh` or `Dockerfile` will not be present in the fuzzer runtime environment. There
+are exceptions to this rule, and for further information on this please see the [fuzzer environment]({{ site.baseurl }}/further-reading/fuzzer-environment/) page.
+
 ## Disk space restrictions
 
 Our builders have a disk size of 250GB (this includes space taken up by the OS). Builds must keep peak disk usage below this.
@@ -366,9 +390,8 @@
 
 
 **Note:** Currently, we only support AddressSanitizer (address) and UndefinedBehaviorSanitizer (undefined)
-configurations. MemorySanitizer is recommended, but needs to be enabled manually once you verify
-that all system dependencies are
-[instrumented](https://github.com/google/oss-fuzz/blob/master/infra/base-images/msan-libs-builder/Dockerfile#L20).
+configurations by default.
+MemorySanitizer is recommended, but needs to be enabled manually since you must build all runtime dependencies with MemorySanitizer.
 <b>Make sure to test each
 of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage).</b>
 
@@ -387,12 +410,13 @@
 
 ### Seed Corpus
 
-OSS-Fuzz uses evolutionary fuzzing algorithms. Supplying seed corpus consisting
-of good sample inputs is one of the best ways to improve [fuzz target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s coverage.
+Most fuzzing engines use evolutionary fuzzing algorithms. Supplying a seed
+corpus consisting of good sample inputs is one of the best ways to improve [fuzz
+target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s coverage.
 
 To provide a corpus for `my_fuzzer`, put `my_fuzzer_seed_corpus.zip` file next
 to the [fuzz target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s binary in `$OUT` during the build. Individual files in this
-archive will be used as starting inputs for mutations. The name of each file in the corpus is the sha1 checksum (which you can get using the `sha1sum` or `shasum` comand) of its contents. You can store the corpus
+archive will be used as starting inputs for mutations. The name of each file in the corpus is the sha1 checksum (which you can get using the `sha1sum` or `shasum` command) of its contents. You can store the corpus
 next to source files, generate during build or fetch it using curl or any other
 tool of your choice.
 (example: [boringssl](https://github.com/google/oss-fuzz/blob/master/projects/boringssl/build.sh#L41)).
@@ -401,7 +425,7 @@
 in bug reports or be used for further security research. It is important that corpus
 has an appropriate and consistent license.
 
-See also [Accessing Corpora]({{ site.baseurl }}/advanced-topics/corpora/) for information about getting access to the corpus we are currently using for your fuzz targets.
+OSS-Fuzz only: See also [Accessing Corpora]({{ site.baseurl }}/advanced-topics/corpora/) for information about getting access to the corpus we are currently using for your fuzz targets.
 
 ### Dictionaries
 
diff --git a/docs/index.md b/docs/index.md
index c372e77..989836c 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -56,9 +56,9 @@
 [useful links]: {{ site.baseurl }}/reference/useful-links/#tutorials
 
 ## Trophies
-As of January 2021, OSS-Fuzz has found over [25,000] bugs in [375] open source
+As of June 2021, OSS-Fuzz has found over [30,000] bugs in [500] open source
 projects.
 
-[25,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
-[375]: https://github.com/google/oss-fuzz/tree/master/projects
+[30,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
+[500]: https://github.com/google/oss-fuzz/tree/master/projects
 
diff --git a/docs/oss-fuzz/architecture.md b/docs/oss-fuzz/architecture.md
index 56ff296..c4b13fb 100644
--- a/docs/oss-fuzz/architecture.md
+++ b/docs/oss-fuzz/architecture.md
@@ -16,7 +16,7 @@
 and [integrates]({{ site.baseurl }}/advanced-topics/ideal-integration/) them
 with the project's build and test system.
 1. The project is [accepted to OSS-Fuzz]({{ site.baseurl }}/getting-started/accepting-new-projects/) and the developer commits their build configurations.
-1. The OSS-Fuzz [builder](jenkins.io) builds the project from the committed configs.
+1. The OSS-Fuzz [builder](https://github.com/google/oss-fuzz/tree/master/infra/build) builds the project from the committed configs.
 1. The builder uploads the fuzz targets to the OSS-Fuzz GCS bucket.
 1. [ClusterFuzz]({{ site.baseurl }}/further-reading/clusterfuzz) downloads the fuzz targets and begins to fuzz the projects.
 1. When Clusterfuzz finds a
diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md
index 7b12995..da6da5a 100644
--- a/docs/reference/glossary.md
+++ b/docs/reference/glossary.md
@@ -92,7 +92,7 @@
 You can choose which configurations to automatically run your fuzzers with in `project.yaml` file (e.g. [sqlite3](https://github.com/google/oss-fuzz/tree/master/projects/sqlite3/project.yaml)).
 
 ### Architectures
-ClusterFuzz supports fuzzing on x86_64 (aka x64) by default. However you can also fuzz using AddressSanitizer and libFuzzer on i386 (aka x86, or 32 bit) by specifiying the `$ARCHITECTURE` build environment variable using the `--architecture` option:
+ClusterFuzz supports fuzzing on x86_64 (aka x64) by default. However you can also fuzz using AddressSanitizer and libFuzzer on i386 (aka x86, or 32 bit) by specifying the `$ARCHITECTURE` build environment variable using the `--architecture` option:
 
 ```bash
 python infra/helper.py build_fuzzers --architecture i386 json
diff --git a/infra/base-images/all.sh b/infra/base-images/all.sh
index 6d012d5..8b35710 100755
--- a/infra/base-images/all.sh
+++ b/infra/base-images/all.sh
@@ -17,6 +17,11 @@
 
 docker build --pull -t gcr.io/oss-fuzz-base/base-image "$@" infra/base-images/base-image
 docker build -t gcr.io/oss-fuzz-base/base-clang "$@" infra/base-images/base-clang
-docker build -t gcr.io/oss-fuzz-base/base-builder -t gcr.io/oss-fuzz/base-libfuzzer "$@" infra/base-images/base-builder
+docker build -t gcr.io/oss-fuzz-base/base-builder "$@" infra/base-images/base-builder
+docker build -t gcr.io/oss-fuzz-base/base-builder-go "$@" infra/base-images/base-builder-go
+docker build -t gcr.io/oss-fuzz-base/base-builder-jvm "$@" infra/base-images/base-builder-jvm
+docker build -t gcr.io/oss-fuzz-base/base-builder-python "$@" infra/base-images/base-builder-python
+docker build -t gcr.io/oss-fuzz-base/base-builder-rust "$@" infra/base-images/base-builder-rust
+docker build -t gcr.io/oss-fuzz-base/base-builder-swift "$@" infra/base-images/base-builder-swift
 docker build -t gcr.io/oss-fuzz-base/base-runner "$@" infra/base-images/base-runner
 docker build -t gcr.io/oss-fuzz-base/base-runner-debug "$@" infra/base-images/base-runner-debug
diff --git a/infra/base-images/base-builder-go/Dockerfile b/infra/base-images/base-builder-go/Dockerfile
new file mode 100644
index 0000000..9d2c615
--- /dev/null
+++ b/infra/base-images/base-builder-go/Dockerfile
@@ -0,0 +1,30 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+# Set up Golang environment variables (copied from /root/.bash_profile).
+ENV GOPATH /root/go
+
+# /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc).
+# $GOPATH/bin is for the binaries from the dependencies installed via "go get".
+ENV PATH $PATH:/root/.go/bin:$GOPATH/bin
+
+RUN install_go.sh
+
+# TODO(jonathanmetzman): Install this file using install_go.sh.
+COPY ossfuzz_coverage_runner.go $GOPATH
+
diff --git a/infra/base-images/base-builder-go/ossfuzz_coverage_runner.go b/infra/base-images/base-builder-go/ossfuzz_coverage_runner.go
new file mode 100644
index 0000000..d433da2
--- /dev/null
+++ b/infra/base-images/base-builder-go/ossfuzz_coverage_runner.go
@@ -0,0 +1,69 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package mypackagebeingfuzzed
+
+import (
+	"io/ioutil"
+	"os"
+	"runtime/pprof"
+	"testing"
+)
+
+func TestFuzzCorpus(t *testing.T) {
+	dir := os.Getenv("FUZZ_CORPUS_DIR")
+	if dir == "" {
+		t.Logf("No fuzzing corpus directory set")
+		return
+	}
+	infos, err := ioutil.ReadDir(dir)
+	if err != nil {
+		t.Logf("Not fuzzing corpus directory %s", err)
+		return
+	}
+	filename := ""
+	defer func() {
+		if r := recover(); r != nil {
+			t.Error("Fuzz panicked in "+filename, r)
+		}
+	}()
+	profname := os.Getenv("FUZZ_PROFILE_NAME")
+	if profname != "" {
+		f, err := os.Create(profname + ".cpu.prof")
+		if err != nil {
+			t.Logf("error creating profile file %s\n", err)
+		} else {
+			_ = pprof.StartCPUProfile(f)
+		}
+	}
+	for i := range infos {
+		filename = dir + infos[i].Name()
+		data, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Error("Failed to read corpus file", err)
+		}
+		FuzzFunction(data)
+	}
+	if profname != "" {
+		pprof.StopCPUProfile()
+		f, err := os.Create(profname + ".heap.prof")
+		if err != nil {
+			t.Logf("error creating heap profile file %s\n", err)
+		}
+		if err = pprof.WriteHeapProfile(f); err != nil {
+			t.Logf("error writing heap profile file %s\n", err)
+		}
+		f.Close()
+	}
+}
diff --git a/infra/base-images/base-builder-jvm/Dockerfile b/infra/base-images/base-builder-jvm/Dockerfile
new file mode 100644
index 0000000..f27478b
--- /dev/null
+++ b/infra/base-images/base-builder-jvm/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+ENV JAVA_HOME /usr/lib/jvm/java-15-openjdk-amd64
+ENV JVM_LD_LIBRARY_PATH $JAVA_HOME/lib/server
+ENV PATH $PATH:$JAVA_HOME/bin
+ENV JAZZER_API_PATH "/usr/local/lib/jazzer_api_deploy.jar"
+
+RUN install_java.sh
\ No newline at end of file
diff --git a/infra/base-images/base-builder-python/Dockerfile b/infra/base-images/base-builder-python/Dockerfile
new file mode 100644
index 0000000..749b4d5
--- /dev/null
+++ b/infra/base-images/base-builder-python/Dockerfile
@@ -0,0 +1,19 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN install_python.sh
diff --git a/infra/base-images/base-builder-rust/Dockerfile b/infra/base-images/base-builder-rust/Dockerfile
new file mode 100644
index 0000000..a4ec327
--- /dev/null
+++ b/infra/base-images/base-builder-rust/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+ENV CARGO_HOME=/rust
+ENV RUSTUP_HOME=/rust/rustup
+ENV PATH=$PATH:/rust/bin
+# Set up custom environment variable for source code copy for coverage reports
+ENV OSSFUZZ_RUSTPATH /rust
+
+RUN install_rust.sh
diff --git a/infra/base-images/base-builder-swift/Dockerfile b/infra/base-images/base-builder-swift/Dockerfile
new file mode 100644
index 0000000..2b063bb
--- /dev/null
+++ b/infra/base-images/base-builder-swift/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN install_swift.sh
+
+COPY precompile_swift /usr/local/bin/
diff --git a/infra/base-images/base-builder-swift/precompile_swift b/infra/base-images/base-builder-swift/precompile_swift
new file mode 100755
index 0000000..ab855a6
--- /dev/null
+++ b/infra/base-images/base-builder-swift/precompile_swift
@@ -0,0 +1,33 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cp /usr/local/bin/llvm-symbolizer-swift $OUT/llvm-symbolizer
+
+export SWIFTFLAGS="-Xswiftc -parse-as-library -Xswiftc -static-stdlib --static-swift-stdlib"
+if [ "$SANITIZER" = "coverage" ]
+then
+    export SWIFTFLAGS="$SWIFTFLAGS -Xswiftc -profile-generate -Xswiftc -profile-coverage-mapping -Xswiftc -sanitize=fuzzer"
+else
+    export SWIFTFLAGS="$SWIFTFLAGS -Xswiftc -sanitize=fuzzer,$SANITIZER --sanitize=$SANITIZER"
+    for f in $CFLAGS; do
+        export SWIFTFLAGS="$SWIFTFLAGS -Xcc=$f"
+    done
+
+    for f in $CXXFLAGS; do
+        export SWIFTFLAGS="$SWIFTFLAGS -Xcxx=$f"
+    done
+fi
diff --git a/infra/base-images/base-builder/Dockerfile b/infra/base-images/base-builder/Dockerfile
index d802f24..256e7be 100644
--- a/infra/base-images/base-builder/Dockerfile
+++ b/infra/base-images/base-builder/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2016 Google Inc.
+# Copyright 2021 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -61,71 +61,15 @@
     rm -rf /usr/local/lib/python3.8/test && \
     apt-get remove -y $PYTHON_DEPS # https://github.com/google/oss-fuzz/issues/3888
 
-# Install latest atheris for python fuzzing, pyinstaller for fuzzer packaging,
-# six for Bazel rules.
+# Install six for Bazel rules.
 RUN unset CFLAGS CXXFLAGS && pip3 install -v --no-cache-dir \
-    atheris pyinstaller==4.1 six==1.15.0 && \
-    rm -rf /tmp/*
-
-# Download and install the latest stable Go.
-RUN cd /tmp && \
-    curl -O https://storage.googleapis.com/golang/getgo/installer_linux && \
-    chmod +x ./installer_linux && \
-    SHELL="bash" ./installer_linux && \
-    rm -rf ./installer_linux
-
-# Set up Golang environment variables (copied from /root/.bash_profile).
-ENV GOPATH /root/go
-
-# /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc).
-# $GOPATH/bin is for the binaries from the dependencies installed via "go get".
-ENV PATH $PATH:/root/.go/bin:$GOPATH/bin
-
-# Uses golang 1.14+ cmd/compile's native libfuzzer instrumentation.
-RUN go get -u github.com/mdempsky/go114-fuzz-build && \
-    ln -s $GOPATH/bin/go114-fuzz-build $GOPATH/bin/go-fuzz
-
-# Install Rust and cargo-fuzz for libFuzzer instrumentation.
-ENV CARGO_HOME=/rust
-ENV RUSTUP_HOME=/rust/rustup
-ENV PATH=$PATH:/rust/bin
-RUN curl https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly --profile=minimal
-RUN cargo install cargo-fuzz && rm -rf /rust/registry
-# Needed to recompile rust std library for MSAN
-RUN rustup component add rust-src --toolchain nightly
-# Set up custom environment variable for source code copy for coverage reports
-ENV OSSFUZZ_RUSTPATH /rust
+    six==1.15.0 && rm -rf /tmp/*
 
 # Install Bazel through Bazelisk, which automatically fetches the latest Bazel version.
-ENV BAZELISK_VERSION 1.7.4
+ENV BAZELISK_VERSION 1.9.0
 RUN curl -L https://github.com/bazelbuild/bazelisk/releases/download/v$BAZELISK_VERSION/bazelisk-linux-amd64 -o /usr/local/bin/bazel && \
     chmod +x /usr/local/bin/bazel
 
-# Install OpenJDK 15 and trim its size by removing unused components.
-ENV JAVA_HOME=/usr/lib/jvm/java-15-openjdk-amd64
-ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server
-ENV PATH=$PATH:$JAVA_HOME/bin
-RUN cd /tmp && \
-    curl -L -O https://download.java.net/java/GA/jdk15.0.2/0d1cfde4252546c6931946de8db48ee2/7/GPL/openjdk-15.0.2_linux-x64_bin.tar.gz && \
-    mkdir -p $JAVA_HOME && \
-    tar -xzv --strip-components=1 -f openjdk-15.0.2_linux-x64_bin.tar.gz --directory $JAVA_HOME && \
-    rm -f openjdk-15.0.2_linux-x64_bin.tar.gz && \
-    rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip
-
-# Install the latest Jazzer in $OUT.
-# jazzer_api_deploy.jar is required only at build-time, the agent and the
-# drivers are copied to $OUT as they need to be present on the runners.
-ENV JAZZER_API_PATH "/usr/local/lib/jazzer_api_deploy.jar"
-RUN cd $SRC/ && \
-    git clone --depth=1 https://github.com/CodeIntelligenceTesting/jazzer && \
-    cd jazzer && \
-    bazel build --java_runtime_version=localjdk_15 -c opt --cxxopt="-stdlib=libc++" --linkopt=-lc++ \
-        //agent:jazzer_agent_deploy.jar //driver:jazzer_driver //driver:jazzer_driver_asan //agent:jazzer_api_deploy.jar && \
-    cp bazel-bin/agent/jazzer_agent_deploy.jar bazel-bin/driver/jazzer_driver bazel-bin/driver/jazzer_driver_asan /usr/local/bin/ && \
-    cp bazel-bin/agent/jazzer_api_deploy.jar $JAZZER_API_PATH && \
-    rm -rf ~/.cache/bazel ~/.cache/bazelisk && \
-    rm -rf $SRC/jazzer
-
 # Default build flags for various sanitizers.
 ENV SANITIZER_FLAGS_address "-fsanitize=address -fsanitize-address-use-after-scope"
 
@@ -181,7 +125,7 @@
 # TODO: switch to -b stable once we can.
 RUN git clone https://github.com/AFLplusplus/AFLplusplus.git aflplusplus && \
     cd aflplusplus && \
-    git checkout 2102264acf5c271b7560a82771b3af8136af9354
+    git checkout 4fe572b80f76ff0b0e916b639d1e04d5af48b157
 
 RUN cd $SRC && \
     curl -L -O https://github.com/google/honggfuzz/archive/oss-fuzz.tar.gz && \
@@ -190,14 +134,25 @@
     tar -xzv --strip-components=1 -f $SRC/oss-fuzz.tar.gz && \
     rm -rf examples $SRC/oss-fuzz.tar.gz
 
-COPY cargo compile compile_afl compile_dataflow compile_libfuzzer compile_honggfuzz \
-    compile_go_fuzzer precompile_honggfuzz precompile_afl debug_afl srcmap \
-    write_labels.py bazel_build_fuzz_tests /usr/local/bin/
-
-COPY detect_repo.py /opt/cifuzz/
-COPY ossfuzz_coverage_runner.go $GOPATH
-
-RUN precompile_honggfuzz
+# Do precompiles before copying other scripts for better cache efficiency.
+COPY precompile_afl /usr/local/bin/
 RUN precompile_afl
 
+COPY precompile_honggfuzz /usr/local/bin/
+RUN precompile_honggfuzz
+
+COPY cargo compile compile_afl compile_dataflow compile_libfuzzer compile_honggfuzz \
+    compile_go_fuzzer debug_afl srcmap \
+    write_labels.py bazel_build_fuzz_tests \
+    # Go, java, and swift installation scripts.
+    install_go.sh \
+    install_java.sh \
+    install_python.sh \
+    install_rust.sh \
+    install_swift.sh \
+    /usr/local/bin/
+
+COPY llvmsymbol.diff $SRC
+COPY detect_repo.py /opt/cifuzz/
+
 CMD ["compile"]
diff --git a/infra/base-images/base-builder/bazel_build_fuzz_tests b/infra/base-images/base-builder/bazel_build_fuzz_tests
index 86740ee..dca79f3 100755
--- a/infra/base-images/base-builder/bazel_build_fuzz_tests
+++ b/infra/base-images/base-builder/bazel_build_fuzz_tests
@@ -22,10 +22,17 @@
 : "${BAZEL_TOOL:=bazel}"
 : "${BAZEL_EXTRA_BUILD_FLAGS:=}"
 
+if [ "$FUZZING_LANGUAGE" = "jvm" ]; then
+    BAZEL_LANGUAGE=java
+else
+    BAZEL_LANGUAGE=cc
+fi
+
 if [[ -z "${BAZEL_FUZZ_TEST_QUERY:-}" ]]; then
     BAZEL_FUZZ_TEST_QUERY="
         let all_fuzz_tests = attr(tags, \"${BAZEL_FUZZ_TEST_TAG}\", \"//...\") in
-        \$all_fuzz_tests - attr(tags, \"${BAZEL_FUZZ_TEST_EXCLUDE_TAG}\", \$all_fuzz_tests)
+        let lang_fuzz_tests = attr(generator_function, \"^${BAZEL_LANGUAGE}_fuzz_test\$\", \$all_fuzz_tests) in
+        \$lang_fuzz_tests - attr(tags, \"${BAZEL_FUZZ_TEST_EXCLUDE_TAG}\", \$lang_fuzz_tests)
     "
 fi
 
@@ -42,9 +49,10 @@
 
 declare -r BAZEL_BUILD_FLAGS=(
     "-c" "opt"
-    "--//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine" \
+    "--@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine" \
     "--@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz" \
     "--@rules_fuzzing//fuzzing:cc_engine_sanitizer=none" \
+    "--cxxopt=-stdlib=libc++" \
     "--linkopt=-lc++" \
     "--action_env=CC=${CC}" "--action_env=CXX=${CXX}" \
     ${BAZEL_EXTRA_BUILD_FLAGS[*]}
diff --git a/infra/base-images/base-builder/bisect_clang_test.py b/infra/base-images/base-builder/bisect_clang_test.py
index edf13e7..a11bf86 100644
--- a/infra/base-images/base-builder/bisect_clang_test.py
+++ b/infra/base-images/base-builder/bisect_clang_test.py
@@ -127,7 +127,7 @@
   return MockPopen
 
 
-def mock_prepare_build(llvm_project_path):  # pylint: disable=unused-argument
+def mock_prepare_build_impl(llvm_project_path):  # pylint: disable=unused-argument
   """Mocked prepare_build function."""
   return '/work/llvm-build'
 
@@ -138,7 +138,7 @@
   def test_build_clang_test(self):
     """Tests that build_clang works as intended."""
     with mock.patch('subprocess.Popen', create_mock_popen()) as mock_popen:
-      with mock.patch('bisect_clang.prepare_build', mock_prepare_build):
+      with mock.patch('bisect_clang.prepare_build', mock_prepare_build_impl):
         llvm_src_dir = '/src/llvm-project'
         bisect_clang.build_clang(llvm_src_dir)
         self.assertEqual([['ninja', '-C', '/work/llvm-build', 'install']],
@@ -170,13 +170,13 @@
     """Tests test_start_commit works as intended when the test returns an
     unexpected value."""
 
-    def mock_execute(command, *args, **kwargs):  # pylint: disable=unused-argument
+    def mock_execute_impl(command, *args, **kwargs):  # pylint: disable=unused-argument
       if command == self.test_command:
         return returncode, '', ''
       return 0, '', ''
 
-    with mock.patch('bisect_clang.execute', mock_execute):
-      with mock.patch('bisect_clang.prepare_build', mock_prepare_build):
+    with mock.patch('bisect_clang.execute', mock_execute_impl):
+      with mock.patch('bisect_clang.prepare_build', mock_prepare_build_impl):
         with self.assertRaises(bisect_clang.BisectError):
           self.git.test_start_commit(commit, label, self.test_command)
 
@@ -202,13 +202,13 @@
     expected value."""
     command_args = []
 
-    def mock_execute(command, *args, **kwargs):  # pylint: disable=unused-argument
+    def mock_execute_impl(command, *args, **kwargs):  # pylint: disable=unused-argument
       command_args.append(command)
       if command == self.test_command:
         return returncode, '', ''
       return 0, '', ''
 
-    with mock.patch('bisect_clang.execute', mock_execute):
+    with mock.patch('bisect_clang.execute', mock_execute_impl):
       self.git.test_start_commit(commit, label, self.test_command)
       self.assertEqual([
           get_git_command('checkout', commit), self.test_command,
@@ -247,13 +247,13 @@
     """Test test_commit works as intended."""
     command_args = []
 
-    def mock_execute(command, *args, **kwargs):  # pylint: disable=unused-argument
+    def mock_execute_impl(command, *args, **kwargs):  # pylint: disable=unused-argument
       command_args.append(command)
       if command == self.test_command:
         return returncode, output, ''
       return 0, output, ''
 
-    with mock.patch('bisect_clang.execute', mock_execute):
+    with mock.patch('bisect_clang.execute', mock_execute_impl):
       result = self.git.test_commit(self.test_command)
       self.assertEqual([self.test_command,
                         get_git_command('bisect', label)], command_args)
diff --git a/infra/base-images/base-builder/cargo b/infra/base-images/base-builder/cargo
index bed8e76..c60c761 100755
--- a/infra/base-images/base-builder/cargo
+++ b/infra/base-images/base-builder/cargo
@@ -27,7 +27,7 @@
     export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix src=$crate_src_abspath/src"
 fi
 
-if [ "$SANITIZER" = "coverage" ] && [ $1 = "fuzz" ]
+if [ "$SANITIZER" = "coverage" ] && [ $1 = "fuzz" ] && [ $2 = "build" ]
 then
     # hack to turn cargo fuzz build into cargo build so as to get coverage
     # cargo fuzz adds "--target" "x86_64-unknown-linux-gnu"
@@ -35,7 +35,11 @@
     # go into fuzz directory if not already the case
     cd fuzz || true
     fuzz_src_abspath=`pwd`
-    export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix fuzz_targets=$fuzz_src_abspath/fuzz_targets"
+    # Default directory is fuzz_targets, but some projects like image-rs use fuzzers.
+    while read i; do
+        export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix $i=$fuzz_src_abspath/$i"
+        # Bash while syntax so that we modify RUSTFLAGS in main shell instead of a subshell.
+    done <<< "$(ls */*.rs | cut -d/ -f1 | uniq)"
     # we do not want to trigger debug assertions and stops
     export RUSTFLAGS="$RUSTFLAGS -C debug-assertions=no"
     # do not optimize with --release, leading to Malformed instrumentation profile data
diff --git a/infra/base-images/base-builder/compile b/infra/base-images/base-builder/compile
index 78453c9..c934d3b 100755
--- a/infra/base-images/base-builder/compile
+++ b/infra/base-images/base-builder/compile
@@ -27,8 +27,8 @@
     echo "ERROR: JVM projects can be fuzzed with libFuzzer engine only."
     exit 1
   fi
-  if [ "$SANITIZER" != "address" ]; then
-    echo "ERROR: JVM projects can be fuzzed with AddressSanitizer only."
+  if [ "$SANITIZER" != "address" ] && [ "$SANITIZER" != "coverage" ] && [ "$SANITIZER" != "undefined" ]; then
+    echo "ERROR: JVM projects can be fuzzed with AddressSanitizer or UndefinedBehaviorSanitizer only."
     exit 1
   fi
   if [ "$ARCHITECTURE" != "x86_64" ]; then
@@ -43,7 +43,7 @@
     exit 1
   fi
   if [ "$SANITIZER" != "address" ] && [ "$SANITIZER" != "undefined" ]; then
-    echo "ERROR: Python projects can be fuzzed with AddressSanitizer and UndefinedBehaviorSanitizer only."
+    echo "ERROR: Python projects can be fuzzed with AddressSanitizer or UndefinedBehaviorSanitizer only."
     exit 1
   fi
   if [ "$ARCHITECTURE" != "x86_64" ]; then
@@ -59,7 +59,7 @@
 
 if [[ $ARCHITECTURE == "i386" ]]; then
     export CFLAGS="-m32 $CFLAGS"
-    cp -R /usr/i386/lib/* /usr/lib
+    cp -R /usr/i386/lib/* /usr/local/lib
 fi
 # JVM projects are fuzzed with Jazzer, which has libFuzzer built in.
 if [[ $FUZZING_ENGINE != "none" ]] && [[ $FUZZING_LANGUAGE != "jvm" ]]; then
@@ -71,15 +71,9 @@
 then
   # Take all libraries from lib/msan and MSAN_LIBS_PATH
   # export CXXFLAGS_EXTRA="-L/usr/msan/lib $CXXFLAGS_EXTRA"
-  cp -R /usr/msan/lib/* /usr/lib/
+  cp -R /usr/msan/lib/* /usr/local/lib/
 
-  if [[ -z "${MSAN_LIBS_PATH-}" ]]; then
-    echo 'WARNING: Building without MSan instrumented libraries.'
-  else
-    # Copy all static libraries only. Don't include .so files because they can
-    # break non MSan compiled programs.
-    (cd "$MSAN_LIBS_PATH" && find . -name '*.a' -exec cp --parents '{}' / ';')
-  fi
+  echo 'Building without MSan instrumented libraries.'
 fi
 
 # Coverage flag overrides.
@@ -118,7 +112,7 @@
 export CXXFLAGS="$CFLAGS $CXXFLAGS_EXTRA"
 
 if [ "$FUZZING_LANGUAGE" = "python" ]; then
-  sanitizer_with_fuzzer_lib_dir=`python3 -c "import atheris; import os; print(os.path.dirname(atheris.path()))"`
+  sanitizer_with_fuzzer_lib_dir=`python3 -c "import atheris; import os; print(atheris.path())"`
   sanitizer_with_fuzzer_output_lib=$OUT/sanitizer_with_fuzzer.so
   if [ "$SANITIZER" = "address" ]; then
     cp $sanitizer_with_fuzzer_lib_dir/asan_with_fuzzer.so $sanitizer_with_fuzzer_output_lib
@@ -136,7 +130,20 @@
 
 # Copy Jazzer to $OUT if needed.
 if [ "$FUZZING_LANGUAGE" = "jvm" ]; then
-  cp $(which jazzer_agent_deploy.jar) $(which jazzer_driver) $(which jazzer_driver_asan) $OUT/
+  cp $(which jazzer_agent_deploy.jar) $(which jazzer_driver) $OUT/
+  jazzer_driver_with_sanitizer=$OUT/jazzer_driver_with_sanitizer
+  if [ "$SANITIZER" = "address" ]; then
+    cp $(which jazzer_driver_asan) $jazzer_driver_with_sanitizer
+  elif [ "$SANITIZER" = "undefined" ]; then
+    cp $(which jazzer_driver_ubsan) $jazzer_driver_with_sanitizer
+  elif [ "$SANITIZER" = "coverage" ]; then
+    # Coverage builds require no instrumentation.
+    cp $(which jazzer_driver) $jazzer_driver_with_sanitizer
+  fi
+
+  # Disable leak checking since the JVM triggers too many false positives.
+  export CFLAGS="$CFLAGS -fno-sanitize=leak"
+  export CXXFLAGS="$CXXFLAGS -fno-sanitize=leak"
 fi
 
 echo "---------------------------------------------------------------"
@@ -144,13 +151,24 @@
 echo "CXX=$CXX"
 echo "CFLAGS=$CFLAGS"
 echo "CXXFLAGS=$CXXFLAGS"
+echo "RUSTFLAGS=$RUSTFLAGS"
 echo "---------------------------------------------------------------"
 
 BUILD_CMD="bash -eux $SRC/build.sh"
 
+# Set +u temporarily to continue even if GOPATH and OSSFUZZ_RUSTPATH are undefined.
+set +u
 # We need to preserve source code files for generating a code coverage report.
 # We need exact files that were compiled, so copy both $SRC and $WORK dirs.
-COPY_SOURCES_CMD="cp -rL --parents $SRC $WORK /usr/include /usr/local/include $GOPATH $OSSFUZZ_RUSTPATH $OUT"
+COPY_SOURCES_CMD="cp -rL --parents $SRC $WORK /usr/include /usr/local/include $GOPATH $OSSFUZZ_RUSTPATH /rustc $OUT"
+set -u
+
+if [ "$FUZZING_LANGUAGE" = "rust" ]; then
+  # Copy rust std lib to its path with a hash.
+  export rustch=`rustc --version --verbose | grep commit-hash | cut -d' ' -f2`
+  mkdir -p /rustc/$rustch/
+  cp -r /rust/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/ /rustc/$rustch/
+fi
 
 if [ "${BUILD_UID-0}" -ne "0" ]; then
   adduser -u $BUILD_UID --disabled-password --gecos '' builder
diff --git a/infra/base-images/base-builder/compile_afl b/infra/base-images/base-builder/compile_afl
index dc66244..d6509c7 100644
--- a/infra/base-images/base-builder/compile_afl
+++ b/infra/base-images/base-builder/compile_afl
@@ -22,6 +22,8 @@
 # AFL++ settings.
 export AFL_LLVM_MODE_WORKAROUND=0
 export AFL_ENABLE_DICTIONARY=0
+export AFL_ENABLE_CMPLOG=1
+export AFL_LAF_CHANCE=3
 
 # Start compiling afl++.
 echo "Copying precompiled afl++"
@@ -45,19 +47,32 @@
 
 # AFL compile option roulette. It is OK if they all happen together.
 
-# 40% chance to perform CMPLOG
+# 20% chance for CTX-2 coverage instrumentation (Caller conTeXt sensitive
+# edge coverage).
+test $(($RANDOM % 100)) -lt 20 && {
+  export AFL_LLVM_INSTRUMENT=CLASSIC,CTX-2
+  export AFL_ENABLE_CMPLOG=0
+  export AFL_LAF_CHANCE=30
+}
+
+# 40% chance to create a dictionary.
+test $(($RANDOM % 100)) -lt 40 && {
+  export AFL_ENABLE_DICTIONARY=1
+}
+
+# 60% chance to perform CMPLOG/REDQUEEN.
 rm -f "$OUT/afl_cmplog.txt"
-test $(($RANDOM % 10)) -lt 4 && {
+test "$AFL_ENABLE_CMPLOG" = "1" -a $(($RANDOM % 100)) -lt 60 && {
   export AFL_LLVM_CMPLOG=1
   touch "$OUT/afl_cmplog.txt"
 }
 
-# 10% chance to perform LAF_INTEL
-test $(($RANDOM % 10)) -lt 1 && {
+# 3% chance to perform COMPCOV/LAF_INTEL.
+test $(($RANDOM % 100)) -lt $AFL_LAF_CHANCE && {
   export AFL_LLVM_LAF_ALL=1
 }
 
-# If the targets wants a dictionary - then create one.
+# Create a dictionary if one is wanted.
 test "$AFL_ENABLE_DICTIONARY" = "1" && {
   export AFL_LLVM_DICT2FILE="$OUT/afl++.dict"
 }
diff --git a/infra/base-images/base-builder/compile_go_fuzzer b/infra/base-images/base-builder/compile_go_fuzzer
index 2342800..dd8c9f6 100755
--- a/infra/base-images/base-builder/compile_go_fuzzer
+++ b/infra/base-images/base-builder/compile_go_fuzzer
@@ -29,7 +29,7 @@
 # in the case we are in the right directory, with go.mod but no go.sum
 go mod tidy || true
 # project was downloaded with go get if go list fails
-go list $tags $path || { cd $GOPATH/pkg/mod/ && cd `echo $path | cut -d/ -f1-3 | awk '{print $1"@*"}'`; }
+go list $tags $path || { cd $GOPATH/pkg/mod/ && cd `echo $path | cut -d/ -f1-3 | awk '{print $1"@*"}'`; } || cd -
 # project does not have go.mod if go list fails again
 go list $tags $path || { go mod init $path && go mod tidy ;}
 
@@ -42,7 +42,9 @@
   sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go
   sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go
 
-  fuzzed_repo=`echo $path | cut -d/ -f-3`
+  # The repo is the module path/name, which is already created above in case it doesn't exist,
+  # but not always the same as the module path. This is necessary to handle SIV properly.
+  fuzzed_repo=$(go list $tags -f {{.Module}} "$path")
   abspath_repo=`go list -m $tags -f {{.Dir}} $fuzzed_repo || go list $tags -f {{.Dir}} $fuzzed_repo`
   # give equivalence to absolute paths in another file, as go test -cover uses golangish pkg.Dir
   echo "s=$fuzzed_repo"="$abspath_repo"= > $OUT/$fuzzer.gocovpath
diff --git a/infra/base-images/base-builder/install_go.sh b/infra/base-images/base-builder/install_go.sh
new file mode 100755
index 0000000..2113883
--- /dev/null
+++ b/infra/base-images/base-builder/install_go.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -eux
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd /tmp
+curl -O https://storage.googleapis.com/golang/getgo/installer_linux
+chmod +x ./installer_linux
+SHELL="bash" ./installer_linux
+rm -rf ./installer_linux
+
+echo 'Set "GOPATH=/root/go"'
+echo 'Set "PATH=$PATH:/root/.go/bin:$GOPATH/bin"'
+
+go get -u github.com/mdempsky/go114-fuzz-build
+ln -s $GOPATH/bin/go114-fuzz-build $GOPATH/bin/go-fuzz
diff --git a/infra/base-images/base-builder/install_java.sh b/infra/base-images/base-builder/install_java.sh
new file mode 100755
index 0000000..560c816
--- /dev/null
+++ b/infra/base-images/base-builder/install_java.sh
@@ -0,0 +1,37 @@
+#!/bin/bash -eux
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Install OpenJDK 15 and trim its size by removing unused components.
+cd /tmp
+curl -L -O https://download.java.net/java/GA/jdk15.0.2/0d1cfde4252546c6931946de8db48ee2/7/GPL/openjdk-15.0.2_linux-x64_bin.tar.gz && \
+mkdir -p $JAVA_HOME
+tar -xzv --strip-components=1 -f openjdk-15.0.2_linux-x64_bin.tar.gz --directory $JAVA_HOME && \
+rm -f openjdk-15.0.2_linux-x64_bin.tar.gz
+rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip
+
+# Install the latest Jazzer in $OUT.
+# jazzer_api_deploy.jar is required only at build-time, the agent and the
+# drivers are copied to $OUT as they need to be present on the runners.
+cd $SRC/
+git clone --depth=1 https://github.com/CodeIntelligenceTesting/jazzer && \
+cd jazzer
+bazel build --java_runtime_version=localjdk_15 -c opt --cxxopt="-stdlib=libc++" --linkopt=-lc++ \
+  //agent:jazzer_agent_deploy.jar //driver:jazzer_driver //driver:jazzer_driver_asan //driver:jazzer_driver_ubsan //agent:jazzer_api_deploy.jar
+cp bazel-bin/agent/jazzer_agent_deploy.jar bazel-bin/driver/jazzer_driver bazel-bin/driver/jazzer_driver_asan bazel-bin/driver/jazzer_driver_ubsan /usr/local/bin/
+cp bazel-bin/agent/jazzer_api_deploy.jar $JAZZER_API_PATH
+rm -rf ~/.cache/bazel ~/.cache/bazelisk
+rm -rf $SRC/jazzer
diff --git a/infra/base-images/base-builder/install_python.sh b/infra/base-images/base-builder/install_python.sh
new file mode 100755
index 0000000..b9c9a38
--- /dev/null
+++ b/infra/base-images/base-builder/install_python.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eux
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+echo "ATHERIS INSTALL"
+unset CFLAGS CXXFLAGS
+pip3 install -v --no-cache-dir atheris>=2.0.6 pyinstaller==4.1
+rm -rf /tmp/*
diff --git a/infra/base-images/base-builder/install_rust.sh b/infra/base-images/base-builder/install_rust.sh
new file mode 100755
index 0000000..cbb461f
--- /dev/null
+++ b/infra/base-images/base-builder/install_rust.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eux
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+curl https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly --profile=minimal
+cargo install cargo-fuzz && rm -rf /rust/registry
+# Needed to recompile rust std library for MSAN
+rustup component add rust-src --toolchain nightly
diff --git a/infra/base-images/base-builder/install_swift.sh b/infra/base-images/base-builder/install_swift.sh
new file mode 100755
index 0000000..d88a7b5
--- /dev/null
+++ b/infra/base-images/base-builder/install_swift.sh
@@ -0,0 +1,66 @@
+#!/bin/bash -eux
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+SWIFT_PACKAGES="wget \
+          binutils \
+          git \
+          gnupg2 \
+          libc6-dev \
+          libcurl4 \
+          libedit2 \
+          libgcc-9-dev \
+          libpython2.7 \
+          libsqlite3-0 \
+          libstdc++-9-dev \
+          libxml2 \
+          libz3-dev \
+          pkg-config \
+          tzdata \
+          zlib1g-dev"
+SWIFT_SYMBOLIZER_PACKAGES="build-essential make cmake ninja-build git python3 g++-multilib binutils-dev zlib1g-dev"
+apt-get update && apt install -y $SWIFT_PACKAGES && \
+  apt install -y $SWIFT_SYMBOLIZER_PACKAGES --no-install-recommends  
+
+
+wget https://swift.org/builds/swift-5.4.2-release/ubuntu2004/swift-5.4.2-RELEASE/swift-5.4.2-RELEASE-ubuntu20.04.tar.gz
+tar xzf swift-5.4.2-RELEASE-ubuntu20.04.tar.gz
+cp -r swift-5.4.2-RELEASE-ubuntu20.04/usr/* /usr/
+rm -rf swift-5.4.2-RELEASE-ubuntu20.04.tar.gz
+# TODO: Move to a seperate work dir
+git clone --depth 1 https://github.com/llvm/llvm-project.git
+cd llvm-project
+git apply ../llvmsymbol.diff --verbose
+cmake -G "Ninja" \
+    -DLIBCXX_ENABLE_SHARED=OFF \
+    -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \
+    -DLIBCXXABI_ENABLE_SHARED=OFF \
+    -DCMAKE_BUILD_TYPE=Release \
+    -DLLVM_TARGETS_TO_BUILD=X86 \
+    -DCMAKE_C_COMPILER=clang \
+    -DCMAKE_CXX_COMPILER=clang++ \
+    -DLLVM_BUILD_TESTS=OFF \
+    -DLLVM_INCLUDE_TESTS=OFF llvm
+ninja -j$(nproc) llvm-symbolizer
+cp bin/llvm-symbolizer /usr/local/bin/llvm-symbolizer-swift
+
+cd $SRC
+rm -rf llvm-project llvmsymbol.diff
+
+# TODO: Cleanup packages
+apt-get remove --purge -y wget zlib1g-dev
+apt-get autoremove -y
diff --git a/infra/base-images/base-builder/llvmsymbol.diff b/infra/base-images/base-builder/llvmsymbol.diff
new file mode 100644
index 0000000..70181bf
--- /dev/null
+++ b/infra/base-images/base-builder/llvmsymbol.diff
@@ -0,0 +1,50 @@
+diff --git a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
+index acfb3bd0e..a499ee2e0 100644
+--- a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
++++ b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
+@@ -12,4 +12,11 @@ add_llvm_component_library(LLVMSymbolize
+   Object
+   Support
+   Demangle
+-  )
++
++  LINK_LIBS
++  /usr/lib/swift_static/linux/libswiftCore.a
++  /usr/lib/swift_static/linux/libicui18nswift.a
++  /usr/lib/swift_static/linux/libicuucswift.a
++  /usr/lib/swift_static/linux/libicudataswift.a
++  /usr/lib/x86_64-linux-gnu/libstdc++.so.6
++)
+diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+index fb4875f79..0030769ee 100644
+--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
++++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+@@ -36,6 +36,13 @@
+ #include <cassert>
+ #include <cstring>
+ 
++
++extern "C" char *swift_demangle(const char *mangledName,
++                     size_t mangledNameLength,
++                     char *outputBuffer,
++                     size_t *outputBufferSize,
++                     uint32_t flags);
++
+ namespace llvm {
+ namespace symbolize {
+ 
+@@ -678,6 +685,14 @@ LLVMSymbolizer::DemangleName(const std::string &Name,
+     free(DemangledName);
+     return Result;
+   }
++  if (!Name.empty() && Name.front() == '$') {
++    char *DemangledName = swift_demangle(Name.c_str(), Name.length(), 0, 0, 0);
++    if (DemangledName) {
++      std::string Result = DemangledName;
++      free(DemangledName);
++      return Result;
++    }
++  }
+ 
+   if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module())
+     return std::string(demanglePE32ExternCFunc(Name));
diff --git a/infra/base-images/base-builder/write_labels.py b/infra/base-images/base-builder/write_labels.py
index 6766e37..92a820a 100755
--- a/infra/base-images/base-builder/write_labels.py
+++ b/infra/base-images/base-builder/write_labels.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
 # Copyright 2021 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/infra/base-images/base-clang/Dockerfile b/infra/base-images/base-clang/Dockerfile
index 3c16a8f..4526094 100644
--- a/infra/base-images/base-clang/Dockerfile
+++ b/infra/base-images/base-clang/Dockerfile
@@ -19,7 +19,7 @@
 FROM gcr.io/oss-fuzz-base/base-image
 
 # Install newer cmake.
-ENV CMAKE_VERSION 3.19.2
+ENV CMAKE_VERSION 3.21.1
 RUN apt-get update && apt-get install -y wget sudo && \
     wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.sh && \
     chmod +x cmake-$CMAKE_VERSION-Linux-x86_64.sh && \
diff --git a/infra/base-images/base-clang/checkout_build_install_llvm.sh b/infra/base-images/base-clang/checkout_build_install_llvm.sh
index f6e8ca9..a62b27c 100755
--- a/infra/base-images/base-clang/checkout_build_install_llvm.sh
+++ b/infra/base-images/base-clang/checkout_build_install_llvm.sh
@@ -21,8 +21,8 @@
 NPROC=$(expr $(nproc) / 2)
 
 # zlib1g-dev is needed for llvm-profdata to handle coverage data from rust compiler
-LLVM_DEP_PACKAGES="build-essential make cmake ninja-build git python3 g++-multilib binutils-dev zlib1g-dev"
-apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends
+LLVM_DEP_PACKAGES="build-essential make cmake ninja-build git python3 python3-distutils g++-multilib binutils-dev zlib1g-dev"
+apt-get update && apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends
 
 # Checkout
 CHECKOUT_RETRIES=10
@@ -74,7 +74,7 @@
 
 # To allow for manual downgrades. Set to 0 to use Chrome's clang version (i.e.
 # *not* force a manual downgrade). Set to 1 to force a manual downgrade.
-FORCE_OUR_REVISION=1
+FORCE_OUR_REVISION=0
 LLVM_REVISION=$(grep -Po "CLANG_REVISION = '\K([^']+)" scripts/update.py)
 
 clone_with_retries https://github.com/llvm/llvm-project.git $LLVM_SRC
@@ -124,10 +124,24 @@
 # Use the clang we just built from now on.
 CMAKE_EXTRA_ARGS="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
 
+function cmake_libcxx {
+  extra_args="$@"
+  cmake -G "Ninja" \
+      -DLIBCXX_ENABLE_SHARED=OFF \
+      -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \
+      -DLIBCXXABI_ENABLE_SHARED=OFF \
+      -DCMAKE_BUILD_TYPE=Release \
+      -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \
+      -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \
+      -DLLVM_BINUTILS_INCDIR="/usr/include/" \
+      $extra_args \
+      $LLVM_SRC/llvm
+}
+
 # 32-bit libraries.
 mkdir -p $WORK/i386
 cd $WORK/i386
-cmake_llvm $CMAKE_EXTRA_ARGS \
+cmake_libcxx $CMAKE_EXTRA_ARGS \
     -DCMAKE_INSTALL_PREFIX=/usr/i386/ \
     -DCMAKE_C_FLAGS="-m32" \
     -DCMAKE_CXX_FLAGS="-m32"
@@ -145,7 +159,7 @@
 fun:__gxx_personality_*
 EOF
 
-cmake_llvm $CMAKE_EXTRA_ARGS \
+cmake_libcxx $CMAKE_EXTRA_ARGS \
     -DLLVM_USE_SANITIZER=Memory \
     -DCMAKE_INSTALL_PREFIX=/usr/msan/ \
     -DCMAKE_CXX_FLAGS="-fsanitize-blacklist=$WORK/msan/blocklist.txt"
@@ -158,7 +172,7 @@
 mkdir -p $WORK/dfsan
 cd $WORK/dfsan
 
-cmake_llvm $CMAKE_EXTRA_ARGS \
+cmake_libcxx $CMAKE_EXTRA_ARGS \
     -DLLVM_USE_SANITIZER=DataFlow \
     -DCMAKE_INSTALL_PREFIX=/usr/dfsan/
 
@@ -197,7 +211,7 @@
 mv $LLVM_TOOLS_TMPDIR/* /usr/local/bin/
 rm -rf $LLVM_TOOLS_TMPDIR
 
-# Remove binaries from LLVM buld that we don't need.
+# Remove binaries from LLVM build that we don't need.
 rm -f \
   /usr/local/bin/bugpoint \
   /usr/local/bin/llc \
diff --git a/infra/base-images/base-image/Dockerfile b/infra/base-images/base-image/Dockerfile
index 2099ffd..bc6035b 100644
--- a/infra/base-images/base-image/Dockerfile
+++ b/infra/base-images/base-image/Dockerfile
@@ -16,11 +16,11 @@
 
 # Base image for all other images.
 
-FROM ubuntu:16.04
+FROM ubuntu:20.04
 ENV DEBIAN_FRONTEND noninteractive
 RUN apt-get update && \
     apt-get upgrade -y && \
-    apt-get install -y libc6-dev binutils libgcc-5-dev && \
+    apt-get install -y libc6-dev binutils libgcc-9-dev && \
     apt-get autoremove -y
 
 ENV OUT=/out
diff --git a/infra/base-images/base-runner/Dockerfile b/infra/base-images/base-runner/Dockerfile
index f847de0..fadd00a 100755
--- a/infra/base-images/base-runner/Dockerfile
+++ b/infra/base-images/base-runner/Dockerfile
@@ -45,12 +45,18 @@
     libcap2 \
     python3 \
     python3-pip \
+    python3-setuptools \
     unzip \
     wget \
     zip --no-install-recommends
 
-RUN git clone https://chromium.googlesource.com/chromium/src/tools/code_coverage /opt/code_coverage && \
-    pip3 install -r /opt/code_coverage/requirements.txt
+ENV CODE_COVERAGE_SRC=/opt/code_coverage
+RUN git clone https://chromium.googlesource.com/chromium/src/tools/code_coverage $CODE_COVERAGE_SRC && \
+    cd /opt/code_coverage && \
+    git checkout edba4873b5e8a390e977a64c522db2df18a8b27d && \
+    pip3 install wheel && \
+    pip3 install -r requirements.txt && \
+    pip3 install MarkupSafe==0.23
 
 # Default environment options for various sanitizers.
 # Note that these match the settings used in ClusterFuzz and
@@ -91,6 +97,12 @@
     rm -f openjdk-15.0.2_linux-x64_bin.tar.gz && \
     rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip
 
+# Install JaCoCo for JVM coverage.
+RUN wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.cli/0.8.7/org.jacoco.cli-0.8.7-nodeps.jar -O /opt/jacoco-cli.jar && \
+    wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar -O /opt/jacoco-agent.jar && \
+    echo "37df187b76888101ecd745282e9cd1ad4ea508d6  /opt/jacoco-agent.jar" | shasum --check && \
+    echo "c1814e7bba5fd8786224b09b43c84fd6156db690  /opt/jacoco-cli.jar" | shasum --check
+
 # Do this last to make developing these files easier/faster due to caching.
 COPY bad_build_check \
     collect_dft \
@@ -98,10 +110,12 @@
     coverage_helper \
     dataflow_tracer.py \
     download_corpus \
+    jacoco_report_converter.py \
     rcfilt \
     reproduce \
     run_fuzzer \
     parse_options.py \
+    profraw_update.py \
     targets_list \
     test_all.py \
     test_one.py \
diff --git a/infra/base-images/base-runner/bad_build_check b/infra/base-images/base-runner/bad_build_check
index 01f8fbb..bb328c7 100755
--- a/infra/base-images/base-runner/bad_build_check
+++ b/infra/base-images/base-runner/bad_build_check
@@ -39,7 +39,7 @@
 MSAN_CALLS_THRESHOLD_FOR_MSAN_BUILD=1000
 # Some engines (e.g. honggfuzz) may make a very small number of calls to msan
 # for memory poisoning.
-MSAN_CALLS_THRESHOLD_FOR_NON_MSAN_BUILD=2
+MSAN_CALLS_THRESHOLD_FOR_NON_MSAN_BUILD=3
 
 # Usually, a non UBSan build (e.g. ASan) has 165 calls to UBSan runtime. The
 # majority of targets built with UBSan have 200+ UBSan calls, but there are
@@ -90,10 +90,7 @@
       echo "BAD BUILD: $FUZZER seems to have only partial coverage instrumentation."
     fi
   elif [[ "$FUZZING_ENGINE" == afl ]]; then
-    # TODO(https://github.com/google/oss-fuzz/issues/2470): Dont use
-    # AFL_DRIVER_DONT_DEFER by default, support .options files in
-    # bad_build_check instead.
-    AFL_DRIVER_DONT_DEFER=1 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 20s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT
+    AFL_FORKSRV_INIT_TMOUT=30000 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 35s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT
     CHECK_PASSED=$(egrep "All set and ready to roll" -c $FUZZER_OUTPUT)
     if (( $CHECK_PASSED == 0 )); then
       echo "BAD BUILD: fuzzing $FUZZER with afl-fuzz failed."
@@ -136,10 +133,7 @@
     SKIP_SEED_CORPUS=1 run_fuzzer $FUZZER_NAME -seed=1337 -runs=$MIN_NUMBER_OF_RUNS &>$FUZZER_OUTPUT
     CHECK_PASSED=$(egrep "Done $MIN_NUMBER_OF_RUNS runs" -c $FUZZER_OUTPUT)
   elif [[ "$FUZZING_ENGINE" = afl ]]; then
-    # TODO(https://github.com/google/oss-fuzz/issues/2470): Dont use
-    # AFL_DRIVER_DONT_DEFER by default, support .options files in
-    # bad_build_check instead.
-    AFL_DRIVER_DONT_DEFER=1 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 20s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT
+    AFL_FORKSRV_INIT_TMOUT=30000 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 35s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT
     if [ $(egrep "target binary (crashed|terminated)" -c $FUZZER_OUTPUT) -eq 0 ]; then
       CHECK_PASSED=1
     fi
diff --git a/infra/base-images/base-runner/coverage b/infra/base-images/base-runner/coverage
index a86b00d..3c7b274 100755
--- a/infra/base-images/base-runner/coverage
+++ b/infra/base-images/base-runner/coverage
@@ -19,14 +19,21 @@
 if (( $# > 0 )); then
   FUZZ_TARGETS="$@"
 else
-  FUZZ_TARGETS="$(find . -maxdepth 1 -type f -executable -printf '%P\n')"
+  FUZZ_TARGETS="$(find . -maxdepth 1 -type f -executable -printf '%P\n' | \
+      grep -v -x -F \
+      -e 'llvm-symbolizer' \
+      -e 'jazzer_agent_deploy.jar' \
+      -e 'jazzer_driver' \
+      -e 'jazzer_driver_with_sanitizer')"
 fi
 
-DUMPS_DIR="$OUT/dumps"
-FUZZER_STATS_DIR="$OUT/fuzzer_stats"
-LOGS_DIR="$OUT/logs"
-REPORT_ROOT_DIR="$OUT/report"
-REPORT_PLATFORM_DIR="$OUT/report/linux"
+COVERAGE_OUTPUT_DIR=${COVERAGE_OUTPUT_DIR:-$OUT}
+
+DUMPS_DIR="$COVERAGE_OUTPUT_DIR/dumps"
+FUZZER_STATS_DIR="$COVERAGE_OUTPUT_DIR/fuzzer_stats"
+LOGS_DIR="$COVERAGE_OUTPUT_DIR/logs"
+REPORT_ROOT_DIR="$COVERAGE_OUTPUT_DIR/report"
+REPORT_PLATFORM_DIR="$COVERAGE_OUTPUT_DIR/report/linux"
 
 for directory in $DUMPS_DIR $FUZZER_STATS_DIR $LOGS_DIR $REPORT_ROOT_DIR \
                  $REPORT_PLATFORM_DIR; do
@@ -54,6 +61,8 @@
 # Number of CPUs available, this is needed for running tests in parallel.
 NPROC=$(nproc)
 
+CORPUS_DIR=${CORPUS_DIR:-"/corpus"}
+
 function run_fuzz_target {
   local target=$1
 
@@ -62,7 +71,7 @@
   local profraw_file="$DUMPS_DIR/$target.%1m.profraw"
   local profraw_file_mask="$DUMPS_DIR/$target.*.profraw"
   local profdata_file="$DUMPS_DIR/$target.profdata"
-  local corpus_real="/corpus/${target}"
+  local corpus_real="$CORPUS_DIR/${target}"
 
   # -merge=1 requires an output directory, create a new, empty dir for that.
   local corpus_dummy="$OUT/dummy_corpus_dir_for_${target}"
@@ -74,7 +83,7 @@
   # because (A) corpuses are already minimized; (B) we do not use sancov, and so
   # libFuzzer always finishes merge with an empty output dir.
   # Use 100s timeout instead of 25s as code coverage builds can be very slow.
-  local args="-merge=1 -timeout=100 -close_fd_mask=3 $corpus_dummy $corpus_real"
+  local args="-merge=1 -timeout=100 $corpus_dummy $corpus_real"
 
   export LLVM_PROFILE_FILE=$profraw_file
   timeout $TIMEOUT $OUT/$target $args &> $LOGS_DIR/$target.log
@@ -90,6 +99,9 @@
     return 0
   fi
 
+  # If necessary translate to latest profraw version.
+  profraw_update.py $OUT/$target $profraw_file_mask tmp.profraw
+  mv tmp.profraw $profraw_file_mask
   llvm-profdata merge -j=1 -sparse $profraw_file_mask -o $profdata_file
 
   # Delete unnecessary and (potentially) large .profraw files.
@@ -115,7 +127,7 @@
   local target=$1
 
   echo "Running go target $target"
-  export FUZZ_CORPUS_DIR="/corpus/${target}/"
+  export FUZZ_CORPUS_DIR="$CORPUS_DIR/${target}/"
   export FUZZ_PROFILE_NAME="$DUMPS_DIR/$target.perf"
   $OUT/$target -test.coverprofile $DUMPS_DIR/$target.profdata &> $LOGS_DIR/$target.log
   # translate from golangish paths to current absolute paths
@@ -125,6 +137,47 @@
   $SYSGOPATH/bin/gocovsum $DUMPS_DIR/$target.profdata > $FUZZER_STATS_DIR/$target.json
 }
 
+function run_java_fuzz_target {
+  local target=$1
+
+  local exec_file="$DUMPS_DIR/$target.exec"
+  local class_dump_dir="$DUMPS_DIR/${target}_classes/"
+  mkdir "$class_dump_dir"
+  local corpus_real="$CORPUS_DIR/${target}"
+
+  # -merge=1 requires an output directory, create a new, empty dir for that.
+  local corpus_dummy="$OUT/dummy_corpus_dir_for_${target}"
+  rm -rf $corpus_dummy && mkdir -p $corpus_dummy
+
+  # Use 100s timeout instead of 25s as code coverage builds can be very slow.
+  local jacoco_args="destfile=$exec_file,classdumpdir=$class_dump_dir,excludes=com.code_intelligence.jazzer.*"
+  local args="-merge=1 -timeout=100 --nohooks \
+      --additional_jvm_args=-javaagent:/opt/jacoco-agent.jar=$jacoco_args \
+      $corpus_dummy $corpus_real"
+
+  timeout $TIMEOUT $OUT/$target $args &> $LOGS_DIR/$target.log
+  if (( $? != 0 )); then
+    echo "Error occured while running $target:"
+    cat $LOGS_DIR/$target.log
+  fi
+
+  if (( $(du -c $exec_file | tail -n 1 | cut -f 1) == 0 )); then
+    # Skip fuzz targets that failed to produce .exec files.
+    return 0
+  fi
+
+  # Generate XML report only as input to jacoco_report_converter.
+  # Source files are not needed for the summary.
+  local xml_report="$DUMPS_DIR/${target}.xml"
+  local summary_file="$FUZZER_STATS_DIR/$target.json"
+  java -jar /opt/jacoco-cli.jar report $exec_file \
+      --xml $xml_report \
+      --classfiles $class_dump_dir
+
+  # Write llvm-cov summary file.
+  jacoco_report_converter.py $xml_report $summary_file
+}
+
 export SYSGOPATH=$GOPATH
 export GOPATH=$OUT/$GOPATH
 # Run each fuzz target, generate raw coverage dumps.
@@ -136,6 +189,14 @@
       grep "FUZZ_CORPUS_DIR" $fuzz_target > /dev/null 2>&1 || continue
     fi
     run_go_fuzz_target $fuzz_target &
+  elif [[ $FUZZING_LANGUAGE == "jvm" ]]; then
+    # Continue if not a fuzz target.
+    if [[ $FUZZING_ENGINE != "none" ]]; then
+      grep "LLVMFuzzerTestOneInput" $fuzz_target > /dev/null 2>&1 || continue
+    fi
+
+    echo "Running $fuzz_target"
+    run_java_fuzz_target $fuzz_target &
   else
     # Continue if not a fuzz target.
     if [[ $FUZZING_ENGINE != "none" ]]; then
@@ -175,6 +236,43 @@
   mv merged.data $REPORT_ROOT_DIR/heap.prof
   #TODO some proxy for go tool pprof -http=127.0.0.1:8001 $DUMPS_DIR/cpu.prof
   echo "Finished generating code coverage report for Go fuzz targets."
+elif [[ $FUZZING_LANGUAGE == "jvm" ]]; then
+
+  # From this point on the script does not tolerate any errors.
+  set -e
+
+  # Merge .exec files from the individual targets.
+  jacoco_merged_exec=$DUMPS_DIR/jacoco.merged.exec
+  java -jar /opt/jacoco-cli.jar merge $DUMPS_DIR/*.exec \
+      --destfile $jacoco_merged_exec
+
+  # Merge .class files from the individual targets.
+  classes_dir=$DUMPS_DIR/classes
+  mkdir $classes_dir
+  for fuzz_target in $FUZZ_TARGETS; do
+    cp -r $DUMPS_DIR/${fuzz_target}_classes/* $classes_dir/
+  done
+
+  # Heuristically determine source directories based on Maven structure.
+  # Always include the $SRC root as it likely contains the fuzzer sources.
+  sourcefiles_args=(--sourcefiles $OUT/$SRC)
+  source_dirs=$(find $OUT/$SRC -type d -name 'java')
+  for source_dir in $source_dirs; do
+    sourcefiles_args+=(--sourcefiles "$source_dir")
+  done
+
+  # Generate HTML and XML reports.
+  xml_report=$REPORT_PLATFORM_DIR/index.xml
+  java -jar /opt/jacoco-cli.jar report $jacoco_merged_exec \
+      --html $REPORT_PLATFORM_DIR \
+      --xml $xml_report \
+      --classfiles $classes_dir \
+      "${sourcefiles_args[@]}"
+
+  # Write llvm-cov summary file.
+  jacoco_report_converter.py $xml_report $SUMMARY_FILE
+
+  set +e
 else
 
   # From this point on the script does not tolerate any errors.
@@ -206,6 +304,10 @@
 
 fi
 
+# Make sure report is readable.
+chmod -R +r $REPORT_ROOT_DIR
+find $REPORT_ROOT_DIR -type d -exec chmod +x {} +
+
 if [[ -n $HTTP_PORT ]]; then
   # Serve the report locally.
   echo "Serving the report on http://127.0.0.1:$HTTP_PORT/linux/index.html"
diff --git a/infra/base-images/base-runner/coverage_helper b/infra/base-images/base-runner/coverage_helper
index 22c9cb5..4d29cea 100755
--- a/infra/base-images/base-runner/coverage_helper
+++ b/infra/base-images/base-runner/coverage_helper
@@ -14,4 +14,4 @@
 # limitations under the License.
 #
 ################################################################################
-python3 /opt/code_coverage/coverage_utils.py $@
+python3 $CODE_COVERAGE_SRC/coverage_utils.py $@
diff --git a/infra/base-images/base-runner/jacoco_report_converter.py b/infra/base-images/base-runner/jacoco_report_converter.py
new file mode 100755
index 0000000..3c36065
--- /dev/null
+++ b/infra/base-images/base-runner/jacoco_report_converter.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Helper script for creating an llvm-cov style JSON summary from a JaCoCo XML
+report."""
+import json
+import os
+import sys
+import xml.etree.ElementTree as ET
+
+
+def convert(xml):
+  """Turns a JaCoCo XML report into an llvm-cov JSON summary."""
+  summary = {
+      "type": "oss-fuzz.java.coverage.json.export",
+      "version": "1.0.0",
+      "data": [{
+          "totals": {},
+          "files": [],
+      }],
+  }
+
+  report = ET.fromstring(xml)
+  totals = make_element_summary(report)
+  summary["data"][0]["totals"] = totals
+
+  # Since Java compilation does not track source file location, we match
+  # coverage info to source files via the full class name, e.g. we search for
+  # a path in /out/src ending in foo/bar/Baz.java for the class foo.bar.Baz.
+  # Under the assumptions that a given project only ever contains a single
+  # version of a class and that no class name appears as a suffix of another
+  # class name, we can assign coverage info to every source file matched in that
+  # way.
+  src_files = list_src_files()
+
+  for class_element in report.findall("./package/class"):
+    class_name = class_element.attrib["name"]
+    package_name = os.path.dirname(class_name)
+    if "sourcefilename" not in class_element.attrib:
+      continue
+    basename = class_element.attrib["sourcefilename"]
+    # This path is "foo/Bar.java" for the class element
+    # <class name="foo/Bar" sourcefilename="Bar.java">.
+    canonical_path = os.path.join(package_name, basename)
+
+    class_summary = make_element_summary(class_element)
+    summary["data"][0]["files"].append({
+        "filename": relative_to_src_path(src_files, canonical_path),
+        "summary": class_summary,
+    })
+
+  return json.dumps(summary)
+
+
+def list_src_files():
+  """Returns a map from basename to full path for all files in $OUT/$SRC."""
+  filename_to_paths = {}
+  out_path = os.environ["OUT"] + "/"
+  src_path = os.environ["SRC"]
+  src_in_out = out_path + src_path
+  for dirpath, _, filenames in os.walk(src_in_out):
+    for filename in filenames:
+      full_path = dirpath + "/" + filename
+      # Map /out//src/... to /src/...
+      src_path = full_path[len(out_path):]
+      filename_to_paths.setdefault(filename, []).append(src_path)
+  return filename_to_paths
+
+
+def relative_to_src_path(src_files, canonical_path):
+  """Returns all paths in src_files ending in canonical_path."""
+  basename = os.path.basename(canonical_path)
+  if basename not in src_files:
+    return []
+  candidate_paths = src_files[basename]
+  return [
+      path for path in candidate_paths if path.endswith("/" + canonical_path)
+  ]
+
+
+def make_element_summary(element):
+  """Returns a coverage summary for an element in the XML report."""
+  summary = {}
+
+  function_counter = element.find("./counter[@type='METHOD']")
+  summary["functions"] = make_counter_summary(function_counter)
+
+  line_counter = element.find("./counter[@type='LINE']")
+  summary["lines"] = make_counter_summary(line_counter)
+
+  # JaCoCo tracks branch coverage, which counts the covered control-flow edges
+  # between llvm-cov's regions instead of the covered regions themselves. For
+  # non-trivial code parts, the difference is usually negligible. However, if
+  # all methods of a class consist of a single region only (no branches),
+  # JaCoCo does not report any branch coverage even if there is instruction
+  # coverage. Since this would give incorrect results for CI Fuzz purposes, we
+  # increase the regions counter by 1 if there is any amount of instruction
+  # coverage.
+  instruction_counter = element.find("./counter[@type='INSTRUCTION']")
+  has_some_coverage = instruction_counter is not None and int(
+      instruction_counter.attrib["covered"]) > 0
+  branch_covered_adjustment = 1 if has_some_coverage else 0
+  region_counter = element.find("./counter[@type='BRANCH']")
+  summary["regions"] = make_counter_summary(
+      region_counter, covered_adjustment=branch_covered_adjustment)
+
+  return summary
+
+
+def make_counter_summary(counter_element, covered_adjustment=0):
+  """Turns a JaCoCo <counter> element into an llvm-cov totals entry."""
+  summary = {}
+  covered = covered_adjustment
+  missed = 0
+  if counter_element is not None:
+    covered += int(counter_element.attrib["covered"])
+    missed += int(counter_element.attrib["missed"])
+  summary["covered"] = covered
+  summary["notcovered"] = missed
+  summary["count"] = summary["covered"] + summary["notcovered"]
+  if summary["count"] != 0:
+    summary["percent"] = (100.0 * summary["covered"]) / summary["count"]
+  else:
+    summary["percent"] = 0
+  return summary
+
+
+def main():
+  """Produces an llvm-cov style JSON summary from a JaCoCo XML report."""
+  if len(sys.argv) != 3:
+    sys.stderr.write('Usage: %s <path_to_jacoco_xml> <out_path_json>\n' %
+                     sys.argv[0])
+    return 1
+
+  with open(sys.argv[1], 'r') as xml_file:
+    xml_report = xml_file.read()
+  json_summary = convert(xml_report)
+  with open(sys.argv[2], 'w') as json_file:
+    json_file.write(json_summary)
+
+  return 0
+
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/infra/base-images/base-runner/profraw_update.py b/infra/base-images/base-runner/profraw_update.py
new file mode 100644
index 0000000..408b5fb
--- /dev/null
+++ b/infra/base-images/base-runner/profraw_update.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Helper script for upgrading a profraw file to latest version."""
+
+from collections import namedtuple
+import struct
+import subprocess
+import sys
+
+HeaderGeneric = namedtuple('HeaderGeneric', 'magic version')
+HeaderVersion7 = namedtuple(
+    'HeaderVersion7',
+    'BinaryIdsSize DataSize PaddingBytesBeforeCounters CountersSize \
+    PaddingBytesAfterCounters NamesSize CountersDelta NamesDelta ValueKindLast')
+
+PROFRAW_MAGIC = 0xff6c70726f667281
+
+
+def relativize_address(data, offset, databegin, sect_prf_cnts, sect_prf_data):
+  """Turns an absolute offset into a relative one."""
+  value = struct.unpack('Q', data[offset:offset + 8])[0]
+  if sect_prf_cnts <= value < sect_prf_data:
+    # If the value is an address in the right section, make it relative.
+    value = (value - databegin) & 0xffffffffffffffff
+    value = struct.pack('Q', value)
+    for i in range(8):
+      data[offset + i] = value[i]
+
+
+def upgrade(data, sect_prf_cnts, sect_prf_data):
+  """Upgrades profraw data, knowing the sections addresses."""
+  generic_header = HeaderGeneric._make(struct.unpack('QQ', data[:16]))
+  if generic_header.magic != PROFRAW_MAGIC:
+    raise Exception('Bad magic.')
+  if generic_header.version == 5:
+    generic_header = generic_header._replace(version=7)
+    # Upgrade from version 5 to 7 by adding binaryids field.
+    data = struct.pack('QQ', generic_header) + struct.pack('Q', 0) + data[16:]
+  if generic_header.version < 7:
+    raise Exception('Unhandled version.')
+  v7_header = HeaderVersion7._make(struct.unpack('QQQQQQQQQ', data[16:88]))
+
+  if v7_header.BinaryIdsSize % 8 != 0:
+    # Adds padding for binary ids.
+    # cf commit b9f547e8e51182d32f1912f97a3e53f4899ea6be
+    # cf https://reviews.llvm.org/D110365
+    padlen = 8 - (v7_header.BinaryIdsSize % 8)
+    v7_header = v7_header._replace(BinaryIdsSize=v7_header.BinaryIdsSize +
+                                   padlen)
+    data = data[:16] + struct.pack('Q', v7_header.BinaryIdsSize) + data[24:]
+    data = data[:88 + v7_header.BinaryIdsSize] + bytes(
+        padlen) + data[88 + v7_header.BinaryIdsSize:]
+
+  if v7_header.CountersDelta != sect_prf_cnts - sect_prf_data:
+    # Rust linking seems to add an offset...
+    sect_prf_data = v7_header.CountersDelta - sect_prf_cnts + sect_prf_data
+    sect_prf_cnts = v7_header.CountersDelta
+
+  dataref = sect_prf_data
+  relativize_address(data, 64, dataref, sect_prf_cnts, sect_prf_data)
+
+  offset = 88 + v7_header.BinaryIdsSize
+  # This also works for C+Rust binaries compiled with
+  # clang-14/rust-nightly-clang-13.
+  for _ in range(v7_header.DataSize):
+    # 16 is the offset of CounterPtr in ProfrawData structure.
+    relativize_address(data, offset + 16, dataref, sect_prf_cnts, sect_prf_data)
+    # We need this because of CountersDelta -= sizeof(*SrcData);
+    # seen in __llvm_profile_merge_from_buffer.
+    dataref += 44 + 2 * (v7_header.ValueKindLast + 1)
+    # This is the size of one ProfrawData structure.
+    offset += 44 + 2 * (v7_header.ValueKindLast + 1)
+
+  return data
+
+
+def main():
+  """Helper script for upgrading a profraw file to latest version."""
+  if len(sys.argv) != 4:
+    sys.stderr.write('Usage: %s <binary> <profraw> <output>\n' % sys.argv[0])
+    return 1
+
+  # First find llvm profile sections addresses in the elf, quick and dirty.
+  process = subprocess.Popen(['readelf', '-S', sys.argv[1]],
+                             stdout=subprocess.PIPE)
+  output, err = process.communicate()
+  if err:
+    print('readelf failed')
+    return 2
+  for line in iter(output.split(b'\n')):
+    if b'__llvm_prf_cnts' in line:
+      sect_prf_cnts = int(line.split()[4], 16)
+    elif b'__llvm_prf_data' in line:
+      sect_prf_data = int(line.split()[4], 16)
+
+  # Then open and read the input profraw file.
+  with open(sys.argv[2], 'rb') as input_file:
+    profraw_base = bytearray(input_file.read())
+  # Do the upgrade, returning a bytes object.
+  profraw_latest = upgrade(profraw_base, sect_prf_cnts, sect_prf_data)
+  # Write the output to the file given to the command line.
+  with open(sys.argv[3], 'wb') as output_file:
+    output_file.write(profraw_latest)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/infra/base-images/base-runner/run_fuzzer b/infra/base-images/base-runner/run_fuzzer
index b9bc8d9..426688e 100755
--- a/infra/base-images/base-runner/run_fuzzer
+++ b/infra/base-images/base-runner/run_fuzzer
@@ -26,7 +26,14 @@
 FUZZER=$1
 shift
 
-CORPUS_DIR=${CORPUS_DIR:-"/tmp/${FUZZER}_corpus"}
+# This env var is set by CIFuzz. CIFuzz fills this directory with the corpus
+# from ClusterFuzz.
+CORPUS_DIR=${CORPUS_DIR:-}
+if [ -z "$CORPUS_DIR" ]
+then
+  CORPUS_DIR="/tmp/${FUZZER}_corpus"
+  rm -rf $CORPUS_DIR && mkdir -p $CORPUS_DIR
+fi
 
 SANITIZER=${SANITIZER:-}
 if [ -z $SANITIZER ]; then
@@ -63,14 +70,13 @@
   fi
 }
 
-rm -rf $CORPUS_DIR && mkdir -p $CORPUS_DIR
 rm -rf $FUZZER_OUT && mkdir -p $FUZZER_OUT
 
 SEED_CORPUS="${FUZZER}_seed_corpus.zip"
 
 if [ -f $SEED_CORPUS ] && [ -z ${SKIP_SEED_CORPUS:-} ]; then
   echo "Using seed corpus: $SEED_CORPUS"
-  unzip -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null
+  unzip -o -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null
 fi
 
 OPTIONS_FILE="${FUZZER}.options"
@@ -103,19 +109,18 @@
   export UBSAN_OPTIONS="$UBSAN_OPTIONS:symbolize=0"
   export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
   export AFL_SKIP_CPUFREQ=1
-  export AFL_NO_AFFINITY=1
+  export AFL_TRY_AFFINITY=1
   export AFL_FAST_CAL=1
+  export AFL_CMPLOG_ONLY_NEW=1
+  export AFL_FORKSRV_INIT_TMOUT=30000
   # If $OUT/afl_cmplog.txt is present this means the target was compiled for
-  # CMPLOG. So we have to add the proper parameters to afl-fuzz. `-l 2` is
-  # CMPLOG level 2, which will colorize larger files but not huge files and
-  # not enable transform analysis unless there have been several cycles without
-  # any finds.
-  test -e "$OUT/afl_cmplog.txt" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -l 2 -c $OUT/$FUZZER"
+  # CMPLOG. So we have to add the proper parameters to afl-fuzz.
+  test -e "$OUT/afl_cmplog.txt" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -c $OUT/$FUZZER"
   # If $OUT/afl++.dict we load it as a dictionary for afl-fuzz.
   test -e "$OUT/afl++.dict" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -x $OUT/afl++.dict"
-  # Ensure timeout is a bit large than 1sec as some of the OSS-Fuzz fuzzers
-  # are slower than this. 
-  AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -t 5000+"
+  # Ensure timeout is a bit larger than 1sec as some of the OSS-Fuzz fuzzers
+  # are slower than this.
+  AFL_FUZZER_ARGS="$FUZZER_ARGS $AFL_FUZZER_ARGS -t 5000+"
   # AFL expects at least 1 file in the input dir.
   echo input > ${CORPUS_DIR}/input
   echo afl++ setup:
@@ -135,7 +140,7 @@
   # -P: use persistent mode of fuzzing (i.e. LLVMFuzzerTestOneInput)
   # -f: location of the initial (and destination) file corpus
   # -n: number of fuzzing threads (and processes)
-  CMD_LINE="$OUT/honggfuzz -n 1 --exit_upon_crash -R /tmp/${FUZZER}_honggfuzz.report -W $FUZZER_OUT -v -z -P -f \"$CORPUS_DIR\" $(get_dictionary) $* -- \"$OUT/$FUZZER\""
+  CMD_LINE="$OUT/honggfuzz -n 1 --exit_upon_crash -R /tmp/${FUZZER}_honggfuzz.report -W $FUZZER_OUT -v -z -P -f \"$CORPUS_DIR\" $(get_dictionary) $FUZZER_ARGS $* -- \"$OUT/$FUZZER\""
 
 else
 
diff --git a/infra/base-images/base-runner/targets_list b/infra/base-images/base-runner/targets_list
index d355342..95615c8 100755
--- a/infra/base-images/base-runner/targets_list
+++ b/infra/base-images/base-runner/targets_list
@@ -2,7 +2,8 @@
 
 for binary in $(find $OUT/ -executable -type f); do
   [[ "$binary" != *.so ]] || continue
-  file "$binary" | grep ELF > /dev/null 2>&1 || continue
+  [[ $(basename "$binary") != jazzer_driver* ]] || continue
+  file "$binary" | grep -e ELF -e "shell script" > /dev/null 2>&1 || continue
   grep "LLVMFuzzerTestOneInput" "$binary" > /dev/null 2>&1 || continue
 
   basename "$binary"
diff --git a/infra/base-images/base-runner/test_all.py b/infra/base-images/base-runner/test_all.py
index 925ebde..16dfcbf 100755
--- a/infra/base-images/base-runner/test_all.py
+++ b/infra/base-images/base-runner/test_all.py
@@ -20,12 +20,12 @@
 import multiprocessing
 import os
 import re
-import shutil
 import subprocess
 import stat
 import sys
+import tempfile
 
-TMP_FUZZER_DIR = '/tmp/not-out'
+BASE_TMP_FUZZER_DIR = '/tmp/not-out'
 
 EXECUTABLE = stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH
 
@@ -37,14 +37,6 @@
 IGNORED_TARGETS_RE = re.compile('^' + r'$|^'.join(IGNORED_TARGETS) + '$')
 
 
-def recreate_directory(directory):
-  """Creates |directory|. If it already exists than deletes it first before
-  creating."""
-  if os.path.exists(directory):
-    shutil.rmtree(directory)
-  os.mkdir(directory)
-
-
 def move_directory_contents(src_directory, dst_directory):
   """Moves contents of |src_directory| to |dst_directory|."""
   # Use mv because mv preserves file permissions. If we don't preserve file
@@ -67,7 +59,15 @@
   return b'ELF' in result.stdout
 
 
-def find_fuzz_targets(directory, fuzzing_language):
+def is_shell_script(filepath):
+  """Returns True if |filepath| is a shell script."""
+  result = subprocess.run(['file', filepath],
+                          stdout=subprocess.PIPE,
+                          check=False)
+  return b'shell script' in result.stdout
+
+
+def find_fuzz_targets(directory):
   """Returns paths to fuzz targets in |directory|."""
   # TODO(https://github.com/google/oss-fuzz/issues/4585): Use libClusterFuzz for
   # this.
@@ -84,10 +84,10 @@
       continue
     if not os.stat(path).st_mode & EXECUTABLE:
       continue
-    # Fuzz targets are expected to be ELF binaries for languages other than
-    # Python and Java.
-    if (fuzzing_language != 'python' and fuzzing_language != 'jvm' and
-        not is_elf(path)):
+    # Fuzz targets can either be ELF binaries or shell scripts (e.g. wrapper
+    # scripts for Python and JVM targets or rules_fuzzing builds with runfiles
+    # trees).
+    if not is_elf(path) and not is_shell_script(path):
       continue
     if os.getenv('FUZZING_ENGINE') != 'none':
       with open(path, 'rb') as file_handle:
@@ -132,51 +132,66 @@
 
 @contextlib.contextmanager
 def use_different_out_dir():
-  """Context manager that moves OUT to TMP_FUZZER_DIR. This is useful for
-  catching hardcoding. Note that this sets the environment variable OUT and
-  therefore must be run before multiprocessing.Pool is created. Resets OUT at
-  the end."""
+  """Context manager that moves OUT to subdirectory of BASE_TMP_FUZZER_DIR. This
+  is useful for catching hardcoding. Note that this sets the environment
+  variable OUT and therefore must be run before multiprocessing.Pool is created.
+  Resets OUT at the end."""
   # Use a fake OUT directory to catch path hardcoding that breaks on
   # ClusterFuzz.
-  out = os.getenv('OUT')
-  initial_out = out
-  recreate_directory(TMP_FUZZER_DIR)
-  out = TMP_FUZZER_DIR
-  # Set this so that run_fuzzer which is called by bad_build_check works
-  # properly.
-  os.environ['OUT'] = out
-  # We move the contents of the directory because we can't move the
-  # directory itself because it is a mount.
-  move_directory_contents(initial_out, out)
-  try:
-    yield out
-  finally:
-    move_directory_contents(out, initial_out)
-    shutil.rmtree(out)
-    os.environ['OUT'] = initial_out
+  initial_out = os.getenv('OUT')
+  os.makedirs(BASE_TMP_FUZZER_DIR, exist_ok=True)
+  # Use a random subdirectory of BASE_TMP_FUZZER_DIR to allow running multiple
+  # instances of test_all in parallel (useful for integration testing).
+  with tempfile.TemporaryDirectory(dir=BASE_TMP_FUZZER_DIR) as out:
+    # Set this so that run_fuzzer which is called by bad_build_check works
+    # properly.
+    os.environ['OUT'] = out
+    # We move the contents of the directory because we can't move the
+    # directory itself because it is a mount.
+    move_directory_contents(initial_out, out)
+    try:
+      yield out
+    finally:
+      move_directory_contents(out, initial_out)
+      os.environ['OUT'] = initial_out
 
 
-def test_all_outside_out(fuzzing_language, allowed_broken_targets_percentage):
+def test_all_outside_out(allowed_broken_targets_percentage):
   """Wrapper around test_all that changes OUT and returns the result."""
   with use_different_out_dir() as out:
-    return test_all(out, fuzzing_language, allowed_broken_targets_percentage)
+    return test_all(out, allowed_broken_targets_percentage)
 
 
-def test_all(out, fuzzing_language, allowed_broken_targets_percentage):
+def test_all(out, allowed_broken_targets_percentage):
   """Do bad_build_check on all fuzz targets."""
   # TODO(metzman): Refactor so that we can convert test_one to python.
-  fuzz_targets = find_fuzz_targets(out, fuzzing_language)
+  fuzz_targets = find_fuzz_targets(out)
   if not fuzz_targets:
     print('ERROR: No fuzz targets found.')
     return False
 
   pool = multiprocessing.Pool()
   bad_build_results = pool.map(do_bad_build_check, fuzz_targets)
+  pool.close()
+  pool.join()
   broken_targets = get_broken_fuzz_targets(bad_build_results, fuzz_targets)
   broken_targets_count = len(broken_targets)
   if not broken_targets_count:
     return True
 
+  print('Retrying failed fuzz targets sequentially', broken_targets_count)
+  pool = multiprocessing.Pool(1)
+  retry_targets = []
+  for broken_target, result in broken_targets:
+    retry_targets.append(broken_target)
+  bad_build_results = pool.map(do_bad_build_check, retry_targets)
+  pool.close()
+  pool.join()
+  broken_targets = get_broken_fuzz_targets(bad_build_results, broken_targets)
+  broken_targets_count = len(broken_targets)
+  if not broken_targets_count:
+    return True
+
   print('Broken fuzz targets', broken_targets_count)
   total_targets_count = len(fuzz_targets)
   broken_targets_percentage = 100 * broken_targets_count / total_targets_count
@@ -211,11 +226,8 @@
 def main():
   """Does bad_build_check on all fuzz targets in parallel. Returns 0 on success.
   Returns 1 on failure."""
-  # Set these environment variables here so that stdout
-  fuzzing_language = os.getenv('FUZZING_LANGUAGE')
   allowed_broken_targets_percentage = get_allowed_broken_targets_percentage()
-  if not test_all_outside_out(fuzzing_language,
-                              allowed_broken_targets_percentage):
+  if not test_all_outside_out(allowed_broken_targets_percentage):
     return 1
   return 0
 
diff --git a/infra/base-images/base-runner/test_all_test.py b/infra/base-images/base-runner/test_all_test.py
index 3771ec2..b3077ec 100644
--- a/infra/base-images/base-runner/test_all_test.py
+++ b/infra/base-images/base-runner/test_all_test.py
@@ -25,15 +25,13 @@
 
   @mock.patch('test_all.find_fuzz_targets', return_value=[])
   @mock.patch('builtins.print')
-  def test_test_all_no_fuzz_targets(self, mocked_print, _):
+  def test_test_all_no_fuzz_targets(self, mock_print, _):
     """Tests that test_all returns False when there are no fuzz targets."""
     outdir = '/out'
-    fuzzing_language = 'c++'
     allowed_broken_targets_percentage = 0
     self.assertFalse(
-        test_all.test_all(outdir, fuzzing_language,
-                          allowed_broken_targets_percentage))
-    mocked_print.assert_called_with('ERROR: No fuzz targets found.')
+        test_all.test_all(outdir, allowed_broken_targets_percentage))
+    mock_print.assert_called_with('ERROR: No fuzz targets found.')
 
 
 if __name__ == '__main__':
diff --git a/infra/base-images/base-sanitizer-libs-builder/Dockerfile b/infra/base-images/base-sanitizer-libs-builder/Dockerfile
deleted file mode 100644
index b1a17b9..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-FROM gcr.io/oss-fuzz-base/base-clang
-RUN sed -i -r 's/#\s*deb-src/deb-src/g' /etc/apt/sources.list
-RUN apt-get update && apt-get install -y python dpkg-dev patchelf python-apt zip
-
-COPY compiler_wrapper.py msan_build.py patch_build.py wrapper_utils.py /usr/local/bin/
-COPY packages /usr/local/bin/packages
diff --git a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py b/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py
deleted file mode 100755
index 04aa420..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-from __future__ import print_function
-import os
-import subprocess
-import sys
-
-import msan_build
-
-GCC_ONLY_ARGS = [
-    '-aux-info',
-]
-
-
-def InvokedAsGcc():
-  """Return whether or not we're pretending to be GCC."""
-  return sys.argv[0].endswith('gcc') or sys.argv[0].endswith('g++')
-
-
-def Is32Bit(args):
-  """Return whether or not we're 32-bit."""
-  M32_BIT_ARGS = [
-      '-m32',
-      '-mx32',
-  ]
-
-  return any(arg in M32_BIT_ARGS for arg in args)
-
-
-def FilterWlArg(arg):
-  """Remove -z,defs and equivalents from a single -Wl option."""
-  parts = arg.split(',')[1:]
-
-  filtered = []
-  for part in parts:
-    if part == 'defs':
-      removed = filtered.pop()
-      assert removed == '-z'
-      continue
-
-    if part == '--no-undefined':
-      continue
-      
-    filtered.append(part)
-
-  if filtered:
-    return '-Wl,' + ','.join(filtered)
-
-  # Filtered entire argument.
-  return None
-
-
-def _RemoveLastMatching(l, find):
-  for i in xrange(len(l) - 1, -1, -1):
-    if l[i] == find:
-      del l[i]
-      return
-
-  raise IndexError('Not found')
-
-
-def RemoveZDefs(args):
-  """Remove unsupported -Wl,-z,defs linker option."""
-  filtered = []
-
-  for arg in args:
-    if arg == '-Wl,defs':
-      _RemoveLastMatching(filtered, '-Wl,-z')
-      continue
-
-    if arg == '-Wl,--no-undefined':
-      continue
-
-    if arg.startswith('-Wl,'):
-      arg = FilterWlArg(arg)
-      if not arg:
-        continue
-
-    filtered.append(arg)
-
-  return filtered
-
-
-def GetCompilerArgs(args, is_cxx):
-  """Generate compiler args."""
-  compiler_args = args[1:]
-
-  if Is32Bit(args):
-    # 32 bit builds not supported.
-    compiler_args.extend([
-        '-fno-sanitize=memory',
-        '-fno-sanitize-memory-track-origins',
-    ])
-
-    return compiler_args
-
-  compiler_args = RemoveZDefs(compiler_args)
-  compiler_args.extend([
-      # FORTIFY_SOURCE is not supported by sanitizers.
-      '-U_FORTIFY_SOURCE',
-      '-Wp,-U_FORTIFY_SOURCE',
-      # Reduce binary size.
-      '-gline-tables-only',
-      # Disable all warnings.
-      '-w',
-      # LTO isn't supported.
-      '-fno-lto',
-  ])
-
-  if InvokedAsGcc():
-    compiler_args.extend([
-      # For better compatibility with flags passed via -Wa,...
-      '-fno-integrated-as',
-    ])
-
-  if '-fsanitize=memory' not in args:
-    # If MSan flags weren't added for some reason, add them here.
-    compiler_args.extend(msan_build.GetInjectedFlags())
-
-  if is_cxx:
-    compiler_args.append('-stdlib=libc++')
-
-  return compiler_args
-
-
-def FindRealClang():
-  """Return path to real clang."""
-  return os.environ['REAL_CLANG_PATH']
-
-
-def FallbackToGcc(args):
-  """Check whether if we should fall back to GCC."""
-  if not InvokedAsGcc():
-    return False
-
-  return any(arg in GCC_ONLY_ARGS for arg in args[1:])
-
-
-def main(args):
-  if FallbackToGcc(args):
-    sys.exit(subprocess.call(['/usr/bin/' + os.path.basename(args[0])] +
-                             args[1:]))
-
-  is_cxx = args[0].endswith('++')
-  real_clang = FindRealClang()
-
-  if is_cxx:
-    real_clang += '++'
-
-  args = [real_clang] + GetCompilerArgs(args, is_cxx)
-  debug_log_path = os.getenv('WRAPPER_DEBUG_LOG_PATH')
-  if debug_log_path:
-    with open(debug_log_path, 'a') as f:
-      f.write(str(args) + '\n')
-
-  sys.exit(subprocess.call(args))
-
-
-if __name__ == '__main__':
-  main(sys.argv)
diff --git a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py b/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py
deleted file mode 100644
index a05592d..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""Tests for compiler_wrapper."""
-
-from __future__ import print_function
-
-import unittest
-
-import compiler_wrapper
-
-
-class CompilerWrapperTest(unittest.TestCase):
-
-  def testFilterZDefs(self):
-    self.assertListEqual(
-        ['arg'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,defs']))
-
-    self.assertListEqual(
-        ['arg'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,--no-undefined']))
-
-    self.assertListEqual(
-        ['arg', '-Wl,-z,relro'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,relro']))
-
-    self.assertListEqual(
-        ['arg', '-Wl,-soname,lib.so.1,-z,relro'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-soname,lib.so.1,-z,defs,-z,relro']))
-
-    self.assertListEqual(
-        ['arg', '-Wl,-z,relro'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,relro,-z,defs']))
-
-    self.assertListEqual(
-        ['arg'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z', '-Wl,defs']))
-
-    self.assertListEqual(
-        ['arg', 'arg2'],
-        compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z', 'arg2', '-Wl,--no-undefined']))
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/infra/base-images/base-sanitizer-libs-builder/msan_build.py b/infra/base-images/base-sanitizer-libs-builder/msan_build.py
deleted file mode 100755
index 5ea00ab..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/msan_build.py
+++ /dev/null
@@ -1,460 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-from __future__ import print_function
-import argparse
-import imp
-import os
-import multiprocessing
-import resource
-import shutil
-import subprocess
-import tempfile
-
-import apt
-from apt import debfile
-
-from packages import package
-import wrapper_utils
-
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-PACKAGES_DIR = os.path.join(SCRIPT_DIR, 'packages')
-
-TRACK_ORIGINS_ARG = '-fsanitize-memory-track-origins='
-
-INJECTED_ARGS = [
-    '-fsanitize=memory',
-    '-fsanitize-recover=memory',
-    '-fPIC',
-    '-fno-omit-frame-pointer',
-]
-
-
-class MSanBuildException(Exception):
-  """Base exception."""
-
-
-def GetTrackOriginsFlag():
-  """Get the track origins flag."""
-  if os.getenv('MSAN_NO_TRACK_ORIGINS'):
-    return TRACK_ORIGINS_ARG + '0'
-
-  return TRACK_ORIGINS_ARG + '2'
-
-
-def GetInjectedFlags():
-  return INJECTED_ARGS + [GetTrackOriginsFlag()]
-
-
-def SetUpEnvironment(work_dir):
-  """Set up build environment."""
-  env = {}
-  env['REAL_CLANG_PATH'] = subprocess.check_output(['which', 'clang']).strip()
-  print('Real clang at', env['REAL_CLANG_PATH'])
-  compiler_wrapper_path = os.path.join(SCRIPT_DIR, 'compiler_wrapper.py')
-
-  # Symlink binaries into TMP/bin
-  bin_dir = os.path.join(work_dir, 'bin')
-  os.mkdir(bin_dir)
-
-  dpkg_host_architecture = wrapper_utils.DpkgHostArchitecture()
-  wrapper_utils.CreateSymlinks(
-      compiler_wrapper_path,
-      bin_dir,
-      [
-          'clang',
-          'clang++',
-          # Not all build rules respect $CC/$CXX, so make additional symlinks.
-          'gcc',
-          'g++',
-          'cc',
-          'c++',
-          dpkg_host_architecture + '-gcc',
-          dpkg_host_architecture + '-g++',
-      ])
-
-  env['CC'] = os.path.join(bin_dir, 'clang')
-  env['CXX'] = os.path.join(bin_dir, 'clang++')
-
-  MSAN_OPTIONS = ' '.join(GetInjectedFlags())
-
-  # We don't use nostrip because some build rules incorrectly break when it is
-  # passed. Instead we install our own no-op strip binaries.
-  env['DEB_BUILD_OPTIONS'] = ('nocheck parallel=%d' %
-                              multiprocessing.cpu_count())
-  env['DEB_CFLAGS_APPEND'] = MSAN_OPTIONS
-  env['DEB_CXXFLAGS_APPEND'] = MSAN_OPTIONS + ' -stdlib=libc++'
-  env['DEB_CPPFLAGS_APPEND'] = MSAN_OPTIONS
-  env['DEB_LDFLAGS_APPEND'] = MSAN_OPTIONS
-  env['DPKG_GENSYMBOLS_CHECK_LEVEL'] = '0'
-
-  # debian/rules can set DPKG_GENSYMBOLS_CHECK_LEVEL explicitly, so override it.
-  gen_symbols_wrapper = ('#!/bin/sh\n'
-                         'export DPKG_GENSYMBOLS_CHECK_LEVEL=0\n'
-                         '/usr/bin/dpkg-gensymbols "$@"\n')
-
-  wrapper_utils.InstallWrapper(bin_dir, 'dpkg-gensymbols', gen_symbols_wrapper)
-
-  # Install no-op strip binaries.
-  no_op_strip = ('#!/bin/sh\n' 'exit 0\n')
-  wrapper_utils.InstallWrapper(bin_dir, 'strip', no_op_strip,
-                               [dpkg_host_architecture + '-strip'])
-
-  env['PATH'] = bin_dir + ':' + os.environ['PATH']
-
-  # nocheck doesn't disable override_dh_auto_test. So we have this hack to try
-  # to disable "make check" or "make test" invocations.
-  make_wrapper = ('#!/bin/bash\n'
-                  'if [ "$1" = "test" ] || [ "$1" = "check" ]; then\n'
-                  '  exit 0\n'
-                  'fi\n'
-                  '/usr/bin/make "$@"\n')
-  wrapper_utils.InstallWrapper(bin_dir, 'make', make_wrapper)
-
-  # Prevent entire build from failing because of bugs/uninstrumented in tools
-  # that are part of the build.
-  msan_log_dir = os.path.join(work_dir, 'msan')
-  os.mkdir(msan_log_dir)
-  msan_log_path = os.path.join(msan_log_dir, 'log')
-  env['MSAN_OPTIONS'] = ('halt_on_error=0:exitcode=0:report_umrs=0:log_path=' +
-                         msan_log_path)
-
-  # Increase maximum stack size to prevent tests from failing.
-  limit = 128 * 1024 * 1024
-  resource.setrlimit(resource.RLIMIT_STACK, (limit, limit))
-  return env
-
-
-def FindPackageDebs(package_name, work_directory):
-  """Find package debs."""
-  deb_paths = []
-  cache = apt.Cache()
-
-  for filename in os.listdir(work_directory):
-    file_path = os.path.join(work_directory, filename)
-    if not file_path.endswith('.deb'):
-      continue
-
-    # Matching package name.
-    deb = debfile.DebPackage(file_path)
-    if deb.pkgname == package_name:
-      deb_paths.append(file_path)
-      continue
-
-    # Also include -dev packages that depend on the runtime package.
-    pkg = cache[deb.pkgname]
-    if pkg.section != 'libdevel' and pkg.section != 'universe/libdevel':
-      continue
-
-    # But ignore -dbg packages.
-    if deb.pkgname.endswith('-dbg'):
-      continue
-
-    for dependency in deb.depends:
-      if any(dep[0] == package_name for dep in dependency):
-        deb_paths.append(file_path)
-        break
-
-  return deb_paths
-
-
-def ExtractLibraries(deb_paths, work_directory, output_directory):
-  """Extract libraries from .deb packages."""
-  extract_directory = os.path.join(work_directory, 'extracted')
-  if os.path.exists(extract_directory):
-    shutil.rmtree(extract_directory, ignore_errors=True)
-
-  os.mkdir(extract_directory)
-
-  for deb_path in deb_paths:
-    subprocess.check_call(['dpkg-deb', '-x', deb_path, extract_directory])
-
-  extracted = []
-  for root, _, filenames in os.walk(extract_directory):
-    if 'libx32' in root or 'lib32' in root:
-      continue
-
-    for filename in filenames:
-      if (not filename.endswith('.so') and '.so.' not in filename and
-          not filename.endswith('.a') and '.a' not in filename):
-        continue
-
-      file_path = os.path.join(root, filename)
-      rel_file_path = os.path.relpath(file_path, extract_directory)
-      rel_directory = os.path.dirname(rel_file_path)
-
-      target_dir = os.path.join(output_directory, rel_directory)
-      if not os.path.exists(target_dir):
-        os.makedirs(target_dir)
-
-      target_file_path = os.path.join(output_directory, rel_file_path)
-      extracted.append(target_file_path)
-
-      if os.path.lexists(target_file_path):
-        os.remove(target_file_path)
-
-      if os.path.islink(file_path):
-        link_path = os.readlink(file_path)
-        if os.path.isabs(link_path):
-          # Make absolute links relative.
-          link_path = os.path.relpath(link_path,
-                                      os.path.join('/', rel_directory))
-
-        os.symlink(link_path, target_file_path)
-      else:
-        shutil.copy2(file_path, target_file_path)
-
-  return extracted
-
-
-def GetPackage(package_name):
-  apt_cache = apt.Cache()
-  version = apt_cache[package_name].candidate
-  source_name = version.source_name
-  local_source_name = source_name.replace('.', '_')
-
-  custom_package_path = os.path.join(PACKAGES_DIR, local_source_name) + '.py'
-  if not os.path.exists(custom_package_path):
-    print('Using default package build steps.')
-    return package.Package(source_name, version)
-
-  print('Using custom package build steps.')
-  module = imp.load_source('packages.' + local_source_name, custom_package_path)
-  return module.Package(version)
-
-
-def PatchRpath(path, output_directory):
-  """Patch rpath to be relative to $ORIGIN."""
-  try:
-    rpaths = subprocess.check_output(['patchelf', '--print-rpath',
-                                      path]).strip()
-  except subprocess.CalledProcessError:
-    return
-
-  if not rpaths:
-    return
-
-  processed_rpath = []
-  rel_directory = os.path.join(
-      '/', os.path.dirname(os.path.relpath(path, output_directory)))
-
-  for rpath in rpaths.split(':'):
-    if '$ORIGIN' in rpath:
-      # Already relative.
-      processed_rpath.append(rpath)
-      continue
-
-    processed_rpath.append(
-        os.path.join('$ORIGIN', os.path.relpath(rpath, rel_directory)))
-
-  processed_rpath = ':'.join(processed_rpath)
-  print('Patching rpath for', path, 'to', processed_rpath)
-  subprocess.check_call(
-      ['patchelf', '--force-rpath', '--set-rpath', processed_rpath, path])
-
-
-def _CollectDependencies(apt_cache, pkg, cache, dependencies):
-  """Collect dependencies that need to be built."""
-  C_OR_CXX_DEPS = [
-      'libc++1',
-      'libc6',
-      'libc++abi1',
-      'libgcc1',
-      'libstdc++6',
-  ]
-
-  BLACKLISTED_PACKAGES = [
-      'libcapnp-0.5.3',  # fails to compile on newer clang.
-      'libllvm5.0',
-      'libmircore1',
-      'libmircommon7',
-      'libmirclient9',
-      'libmirprotobuf3',
-      'multiarch-support',
-  ]
-
-  if pkg.name in BLACKLISTED_PACKAGES:
-    return False
-
-  if pkg.section != 'libs' and pkg.section != 'universe/libs':
-    return False
-
-  if pkg.name in C_OR_CXX_DEPS:
-    return True
-
-  is_c_or_cxx = False
-  for dependency in pkg.candidate.dependencies:
-    dependency = dependency[0]
-
-    if dependency.name in cache:
-      is_c_or_cxx |= cache[dependency.name]
-    else:
-      is_c_or_cxx |= _CollectDependencies(apt_cache, apt_cache[dependency.name],
-                                          cache, dependencies)
-  if is_c_or_cxx:
-    dependencies.append(pkg.name)
-
-  cache[pkg.name] = is_c_or_cxx
-  return is_c_or_cxx
-
-
-def GetBuildList(package_name):
-  """Get list of packages that need to be built including dependencies."""
-  apt_cache = apt.Cache()
-  pkg = apt_cache[package_name]
-
-  dependencies = []
-  _CollectDependencies(apt_cache, pkg, {}, dependencies)
-  return dependencies
-
-
-class MSanBuilder(object):
-  """MSan builder."""
-
-  def __init__(self,
-               debug=False,
-               log_path=None,
-               work_dir=None,
-               no_track_origins=False):
-    self.debug = debug
-    self.log_path = log_path
-    self.work_dir = work_dir
-    self.no_track_origins = no_track_origins
-    self.env = None
-
-  def __enter__(self):
-    if not self.work_dir:
-      self.work_dir = tempfile.mkdtemp(dir=self.work_dir)
-
-    if os.path.exists(self.work_dir):
-      shutil.rmtree(self.work_dir, ignore_errors=True)
-
-    os.makedirs(self.work_dir)
-    self.env = SetUpEnvironment(self.work_dir)
-
-    if self.debug and self.log_path:
-      self.env['WRAPPER_DEBUG_LOG_PATH'] = self.log_path
-
-    if self.no_track_origins:
-      self.env['MSAN_NO_TRACK_ORIGINS'] = '1'
-
-    return self
-
-  def __exit__(self, exc_type, exc_value, traceback):
-    if not self.debug:
-      shutil.rmtree(self.work_dir, ignore_errors=True)
-
-  def Build(self, package_name, output_directory, create_subdirs=False):
-    """Build the package and write results into the output directory."""
-    deb_paths = FindPackageDebs(package_name, self.work_dir)
-    if deb_paths:
-      print('Source package already built for', package_name)
-    else:
-      pkg = GetPackage(package_name)
-
-      pkg.InstallBuildDeps()
-      source_directory = pkg.DownloadSource(self.work_dir)
-      print('Source downloaded to', source_directory)
-
-      # custom bin directory for custom build scripts to write wrappers.
-      custom_bin_dir = os.path.join(self.work_dir, package_name + '_bin')
-      os.mkdir(custom_bin_dir)
-      env = self.env.copy()
-      env['PATH'] = custom_bin_dir + ':' + env['PATH']
-
-      pkg.Build(source_directory, env, custom_bin_dir)
-      shutil.rmtree(custom_bin_dir, ignore_errors=True)
-
-      deb_paths = FindPackageDebs(package_name, self.work_dir)
-
-    if not deb_paths:
-      raise MSanBuildException('Failed to find .deb packages.')
-
-    print('Extracting', ' '.join(deb_paths))
-
-    if create_subdirs:
-      extract_directory = os.path.join(output_directory, package_name)
-    else:
-      extract_directory = output_directory
-
-    extracted_paths = ExtractLibraries(deb_paths, self.work_dir,
-                                       extract_directory)
-    for extracted_path in extracted_paths:
-      if os.path.islink(extracted_path):
-        continue
-      if os.path.basename(extracted_path) == 'llvm-symbolizer':
-        continue
-      PatchRpath(extracted_path, extract_directory)
-
-
-def main():
-  parser = argparse.ArgumentParser('msan_build.py', description='MSan builder.')
-  parser.add_argument('package_names', nargs='+', help='Name of the packages.')
-  parser.add_argument('output_dir', help='Output directory.')
-  parser.add_argument('--create-subdirs',
-                      action='store_true',
-                      help=('Create subdirectories in the output '
-                            'directory for each package.'))
-  parser.add_argument('--work-dir', help='Work directory.')
-  parser.add_argument('--no-build-deps',
-                      action='store_true',
-                      help='Don\'t build dependencies.')
-  parser.add_argument('--debug', action='store_true', help='Enable debug mode.')
-  parser.add_argument('--log-path', help='Log path for debugging.')
-  parser.add_argument('--no-track-origins',
-                      action='store_true',
-                      help='Build with -fsanitize-memory-track-origins=0.')
-  args = parser.parse_args()
-
-  if args.no_track_origins:
-    os.environ['MSAN_NO_TRACK_ORIGINS'] = '1'
-
-  if not os.path.exists(args.output_dir):
-    os.makedirs(args.output_dir)
-
-  if args.no_build_deps:
-    package_names = args.package_names
-  else:
-    all_packages = set()
-    package_names = []
-
-    # Get list of packages to build, including all dependencies.
-    for package_name in args.package_names:
-      for dep in GetBuildList(package_name):
-        if dep in all_packages:
-          continue
-
-        if args.create_subdirs:
-          os.mkdir(os.path.join(args.output_dir, dep))
-
-        all_packages.add(dep)
-        package_names.append(dep)
-
-  print('Going to build:')
-  for package_name in package_names:
-    print('\t', package_name)
-
-  with MSanBuilder(debug=args.debug,
-                   log_path=args.log_path,
-                   work_dir=args.work_dir,
-                   no_track_origins=args.no_track_origins) as builder:
-    for package_name in package_names:
-      builder.Build(package_name, args.output_dir, args.create_subdirs)
-
-
-if __name__ == '__main__':
-  main()
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/__init__.py b/infra/base-images/base-sanitizer-libs-builder/packages/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/__init__.py
+++ /dev/null
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/boost1_58.py b/infra/base-images/base-sanitizer-libs-builder/packages/boost1_58.py
deleted file mode 100644
index 8071b7e..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/boost1_58.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import package
-
-
-class Package(package.Package):
-  """boost1.58 package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('boost1.58', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    # Otherwise py_nonblocking.cpp fails to build.
-    env['DEB_CXXFLAGS_APPEND'] += ' -std=c++98'
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/gnutls28.py b/infra/base-images/base-sanitizer-libs-builder/packages/gnutls28.py
deleted file mode 100644
index f8407a6..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/gnutls28.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-import wrapper_utils
-
-
-class Package(package.Package):
-  """gnutls28 package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('gnutls28', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    configure_wrapper = (
-        '#!/bin/bash\n'
-        '/usr/bin/dh_auto_configure "$@" --disable-hardware-acceleration')
-
-    wrapper_utils.InstallWrapper(
-        custom_bin_dir, 'dh_auto_configure', configure_wrapper)
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/libgcrypt20.py b/infra/base-images/base-sanitizer-libs-builder/packages/libgcrypt20.py
deleted file mode 100644
index 9d200af..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/libgcrypt20.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-import wrapper_utils
-
-
-class Package(package.Package):
-  """libgcrypt20 package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('libgcrypt20', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    configure_wrapper = (
-        '#!/bin/bash\n'
-        '/usr/bin/dh_auto_configure "$@" --disable-asm')
-
-    wrapper_utils.InstallWrapper(
-        custom_bin_dir, 'dh_auto_configure', configure_wrapper)
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/mesa.py b/infra/base-images/base-sanitizer-libs-builder/packages/mesa.py
deleted file mode 100644
index ec2e9d2..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/mesa.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import package
-
-
-class Package(package.Package):
-  """mesa package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('mesa', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    env['DEB_CXXFLAGS_APPEND'] += ' -std=c++11'
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/nettle.py b/infra/base-images/base-sanitizer-libs-builder/packages/nettle.py
deleted file mode 100644
index e1b0e2f..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/nettle.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-
-
-def AddNoAsmArg(config_path):
-  """Add --disable-assembler to config scripts."""
-  shutil.move(config_path, config_path + '.real')
-  with open(config_path, 'w') as f:
-    f.write(
-        '#!/bin/sh\n'
-        '%s.real --disable-assembler "$@"\n' % config_path)
-  os.chmod(config_path, 0755)
-
-
-class Package(package.Package):
-  """nettle package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('nettle', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    AddNoAsmArg(os.path.join(source_directory, 'configure'))
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/openssl.py b/infra/base-images/base-sanitizer-libs-builder/packages/openssl.py
deleted file mode 100644
index e24ccc5..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/openssl.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-
-
-def AddNoAsmArg(config_path):
-  """Add --no-asm to config scripts."""
-  shutil.move(config_path, config_path + '.real')
-  with open(config_path, 'w') as f:
-    f.write(
-        '#!/bin/sh\n'
-        '%s.real no-asm "$@"\n' % config_path)
-  os.chmod(config_path, 0755)
-
-
-class Package(package.Package):
-  """openssl package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('openssl', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    AddNoAsmArg(os.path.join(source_directory, 'Configure'))
-    AddNoAsmArg(os.path.join(source_directory, 'config'))
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/package.py b/infra/base-images/base-sanitizer-libs-builder/packages/package.py
deleted file mode 100644
index 059c235..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/package.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-import subprocess
-
-import apt
-
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-
-
-def ApplyPatch(source_directory, patch_name):
-  """Apply custom patch."""
-  subprocess.check_call(['patch', '-p1', '-i',
-                         os.path.join(SCRIPT_DIR, patch_name)],
-                        cwd=source_directory)
-
-
-class PackageException(Exception):
-  """Base package exception."""
-
-
-class Package(object):
-  """Base package."""
-
-  def __init__(self, name, apt_version):
-    self.name = name
-    self.apt_version = apt_version
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    return
-
-  def PostBuild(self, source_directory, env, custom_bin_dir):
-    return
-
-  def PreDownload(self, download_directory):
-    return
-
-  def PostDownload(self, source_directory):
-    return
-
-  def InstallBuildDeps(self):
-    """Install build dependencies for a package."""
-    subprocess.check_call(['apt-get', 'update'])
-    subprocess.check_call(['apt-get', 'build-dep', '-y', self.name])
-
-    # Reload package after update.
-    self.apt_version = (
-        apt.Cache()[self.apt_version.package.name].candidate)
-
-  def DownloadSource(self, download_directory):
-    """Download the source for a package."""
-    self.PreDownload(download_directory)
-
-    source_directory = self.apt_version.fetch_source(download_directory)
-
-    self.PostDownload(source_directory)
-    return source_directory
-
-  def Build(self, source_directory, env, custom_bin_dir):
-    """Build .deb packages."""
-    self.PreBuild(source_directory, env, custom_bin_dir)
-    subprocess.check_call(
-        ['dpkg-buildpackage', '-us', '-uc', '-B'],
-        cwd=source_directory, env=env)
-    self.PostBuild(source_directory, env, custom_bin_dir)
-
-
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pixman.py b/infra/base-images/base-sanitizer-libs-builder/packages/pixman.py
deleted file mode 100644
index 5251246..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pixman.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-
-
-class Package(package.Package):
-  """pixman package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('pixman', apt_version)
-
-  def PostDownload(self, source_directory):
-    # Incorrect checking of GCC vector extension availability.
-    os.system('sed s/support_for_gcc_vector_extensions=yes/'
-              'support_for_gcc_vector_extensions=no/ -i %s/configure.ac' %
-              source_directory)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    blocklist_flag = ' -fsanitize-blacklist=' + os.path.join(
-        os.path.dirname(os.path.abspath(__file__)), 'pixman_blocklist.txt')
-    env['DEB_CXXFLAGS_APPEND'] += blocklist_flag
-    env['DEB_CFLAGS_APPEND'] += blocklist_flag
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt b/infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt
deleted file mode 100644
index 69cf159..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt
+++ /dev/null
@@ -1 +0,0 @@
-src:*/pixman-sse2.c
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py b/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py
deleted file mode 100644
index d3ce7a1..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-from __future__ import print_function
-import glob
-import os
-import subprocess
-
-import package
-
-
-class Package(package.Package):
-  """PulseAudio package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('pulseaudio', apt_version)
-
-  def PostDownload(self, source_directory):
-    """Remove blocklisted patches."""
-    # Fix *droid* patches.
-    bad_patch_path = os.path.join(
-        source_directory, 'debian', 'patches',
-        '0600-droid-sync-with-upstream-for-Android-5-support-and-b.patch')
-    if not os.path.exists(bad_patch_path):
-      return
-
-    print('Applying custom patches.')
-    package.ApplyPatch(source_directory, 'pulseaudio_fix_android.patch')
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch b/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch
deleted file mode 100644
index e86f798..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch
+++ /dev/null
@@ -1,39 +0,0 @@
---- pulseaudio-8.0/src/modules/droid/module-droid-card.c        2017-11-27 22:09:42.533589970 +0000
-+++ pulseaudio-8.0.fixed/src/modules/droid/module-droid-card.c  2017-11-27 22:28:23.847250467 +0000
-@@ -66,10 +66,11 @@
- #include "droid-extcon.h"
- #endif
-
--#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 2
-+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 4
- #include "module-droid-card-19-symdef.h"
- #elif ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
- #include "module-droid-card-22-symdef.h"
-+#else
- #endif
-
- PA_MODULE_AUTHOR("Juho Hämäläinen");
-diff -ru pulseaudio-8.0/src/modules/droid/module-droid-sink.c pulseaudio-8.0.fixed/src/modules/droid/module-droid-sink.c
---- pulseaudio-8.0/src/modules/droid/module-droid-sink.c        2017-11-27 22:09:42.533589970 +0000
-+++ pulseaudio-8.0.fixed/src/modules/droid/module-droid-sink.c  2017-11-27 22:29:53.776348900 +0000
-@@ -40,7 +40,7 @@
- #include "droid-util.h"
- #include "droid-sink.h"
-
--#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 2
-+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 4
- #include "module-droid-sink-19-symdef.h"
- #elif ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
- #include "module-droid-sink-22-symdef.h"
-diff -ru pulseaudio-8.0/src/modules/droid/module-droid-source.c pulseaudio-8.0.fixed/src/modules/droid/module-droid-source.c
---- pulseaudio-8.0/src/modules/droid/module-droid-source.c      2017-11-27 22:09:42.533589970 +0000
-+++ pulseaudio-8.0.fixed/src/modules/droid/module-droid-source.c        2017-11-27 22:30:03.920472828 +0000
-@@ -40,7 +40,7 @@
- #include "droid-util.h"
- #include "droid-source.h"
-
--#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 2
-+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 4
- #include "module-droid-source-19-symdef.h"
- #elif ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
- #include "module-droid-source-22-symdef.h"
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/sqlite3.py b/infra/base-images/base-sanitizer-libs-builder/packages/sqlite3.py
deleted file mode 100644
index 3e1a107..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/sqlite3.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import os
-
-import package
-
-
-class Package(package.Package):
-  """sqlite3 package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('sqlite3', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    os.system(
-        'sed -i "s/package ifneeded sqlite3//" %s/debian/rules' %
-        source_directory)
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/systemd.py b/infra/base-images/base-sanitizer-libs-builder/packages/systemd.py
deleted file mode 100644
index 5cb6d60..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/systemd.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-from __future__ import print_function
-import glob
-import os
-import subprocess
-
-import package
-import wrapper_utils
-
-
-class Package(package.Package):
-  """systemd package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('systemd', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    # Hide msan symbols from nm. the systemd build system uses this to find
-    # undefined symbols and errors out if it does.
-    nm_wrapper = (
-        '#!/bin/bash\n'
-        '/usr/bin/nm "$@" | grep -E -v "U (__msan|memset)"\n'
-        'exit ${PIPESTATUS[0]}\n')
-
-    wrapper_utils.InstallWrapper(custom_bin_dir, 'nm', nm_wrapper,
-                                 [wrapper_utils.DpkgHostArchitecture() + '-nm'])
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/tar.py b/infra/base-images/base-sanitizer-libs-builder/packages/tar.py
deleted file mode 100644
index 74abd5c..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/tar.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-import package
-
-
-class Package(package.Package):
-  """tar package."""
-
-  def __init__(self, apt_version):
-    super(Package, self).__init__('tar', apt_version)
-
-  def PreBuild(self, source_directory, env, custom_bin_dir):
-    env['FORCE_UNSAFE_CONFIGURE'] = '1'
diff --git a/infra/base-images/base-sanitizer-libs-builder/patch_build.py b/infra/base-images/base-sanitizer-libs-builder/patch_build.py
deleted file mode 100755
index cb1f4b1..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/patch_build.py
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-from __future__ import print_function
-import argparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-
-INSTRUMENTED_LIBRARIES_DIRNAME = 'instrumented_libraries'
-MSAN_LIBS_PATH = os.getenv('MSAN_LIBS_PATH', '/msan')
-
-
-def IsElf(file_path):
-  """Whether if the file is an elf file."""
-  with open(file_path) as f:
-    return f.read(4) == '\x7fELF'
-
-
-def Ldd(binary_path):
-  """Run ldd on a file."""
-  try:
-    output = subprocess.check_output(['ldd', binary_path], stderr=subprocess.STDOUT)
-  except subprocess.CalledProcessError:
-    print('Failed to call ldd on', binary_path, file=sys.stderr)
-    return []
-
-  libs = []
-
-  OUTPUT_PATTERN = re.compile(r'\s*([^\s]+)\s*=>\s*([^\s]+)')
-  for line in output.splitlines():
-    match = OUTPUT_PATTERN.match(line)
-    if not match:
-      continue
-
-    libs.append((match.group(1), match.group(2)))
-
-  return libs
-
-
-def FindLib(path):
-  """Find instrumented version of lib."""
-  candidate_path = os.path.join(MSAN_LIBS_PATH, path[1:])
-  if os.path.exists(candidate_path):
-    return candidate_path
-  
-  for lib_dir in os.listdir(MSAN_LIBS_PATH):
-    candidate_path = os.path.join(MSAN_LIBS_PATH, lib_dir, path[1:])
-    if os.path.exists(candidate_path):
-      return candidate_path
-
-  return None
-
-
-def PatchBinary(binary_path, instrumented_dir):
-  """Patch binary to link to instrumented libs."""
-  extra_rpaths = set()
-
-  for name, path in Ldd(binary_path):
-    if not os.path.isabs(path):
-      continue
-
-    instrumented_path = FindLib(path)
-    if not instrumented_path:
-      print('WARNING: Instrumented library not found for', path,
-            file=sys.stderr)
-      continue
-
-    target_path = os.path.join(instrumented_dir, path[1:])
-    if not os.path.exists(target_path):
-      print('Copying instrumented lib to', target_path)
-      target_dir = os.path.dirname(target_path)
-      if not os.path.exists(target_dir):
-        os.makedirs(target_dir)
-      shutil.copy2(instrumented_path, target_path)
-
-    extra_rpaths.add(
-        os.path.join('$ORIGIN', INSTRUMENTED_LIBRARIES_DIRNAME,
-                     os.path.dirname(path[1:])))
-
-  if not extra_rpaths:
-    return
-
-  existing_rpaths = subprocess.check_output(
-      ['patchelf', '--print-rpath', binary_path]).strip()
-  processed_rpaths = ':'.join(extra_rpaths)
-  if existing_rpaths:
-    processed_rpaths += ':' + existing_rpaths
-  print('Patching rpath for', binary_path, 'from', existing_rpaths, 'to',
-        processed_rpaths)
-
-  subprocess.check_call(
-      ['patchelf', '--force-rpath', '--set-rpath',
-       processed_rpaths, binary_path])
-
-
-def PatchBuild(output_directory):
-  """Patch build to use msan libs."""
-  instrumented_dir = os.path.join(output_directory,
-                                  INSTRUMENTED_LIBRARIES_DIRNAME)
-  if not os.path.exists(instrumented_dir):
-    os.mkdir(instrumented_dir)
-
-  for root_dir, _, filenames in os.walk(output_directory):
-    for filename in filenames:
-      file_path = os.path.join(root_dir, filename)
-
-      if os.path.islink(file_path):
-        continue
-
-      if not IsElf(file_path):
-        continue
-
-      PatchBinary(file_path, instrumented_dir)
-
-
-def main():
-  parser = argparse.ArgumentParser('patch_build.py', description='MSan build patcher.')
-  parser.add_argument('output_dir', help='Output directory.')
-
-  args = parser.parse_args()
-
-  PatchBuild(os.path.abspath(args.output_dir))
-
-
-if __name__ == '__main__':
-  main()
diff --git a/infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py b/infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py
deleted file mode 100644
index 0cbf167..0000000
--- a/infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-from __future__ import print_function
-
-import contextlib
-import os
-import subprocess
-
-
-def DpkgHostArchitecture():
-  """Return the host architecture."""
-  return subprocess.check_output(
-      ['dpkg-architecture', '-qDEB_HOST_GNU_TYPE']).strip()
-
-
-def InstallWrapper(bin_dir, name, contents, extra_names=None):
-  """Install a custom wrapper script into |bin_dir|."""
-  path = os.path.join(bin_dir, name)
-  with open(path, 'w') as f:
-    f.write(contents)
-
-  os.chmod(path, 0755)
-
-  if extra_names:
-    CreateSymlinks(path, bin_dir, extra_names)
-
-
-def CreateSymlinks(original_path, bin_dir, extra_names):
-  """Create symlinks."""
-  for extra_name in extra_names:
-    extra_path = os.path.join(bin_dir, extra_name)
-    os.symlink(original_path, extra_path)
diff --git a/infra/base-images/msan-libs-builder/Dockerfile b/infra/base-images/msan-libs-builder/Dockerfile
deleted file mode 100644
index 7780c1f..0000000
--- a/infra/base-images/msan-libs-builder/Dockerfile
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-FROM gcr.io/oss-fuzz-base/base-sanitizer-libs-builder
-
-# Take all libraries from lib/msan
-RUN cp -R /usr/msan/lib/* /usr/lib/
-
-RUN mkdir /msan
-WORKDIR /msan
-
-ENV PYTHONUNBUFFERED 1
-RUN msan_build.py --work-dir=$WORK \
-    libarchive13 \
-    libattr1 \
-    libbz2-1.0 \
-    libfontconfig1 \
-    libfreetype6 \
-    libfribidi0 \
-    libglib2.0-0 \
-    libicu55  \
-    liblz4-1 \
-    liblzma5 \
-    liblzo2-2 \
-    libnettle6 \
-    libpcre2-posix0 \
-    libpcre3 \
-    libpng12-0 \
-    libssl1.0.0 \
-    libxml2 \
-    zlib1g \
-    /msan
diff --git a/infra/bisector.py b/infra/bisector.py
index 1438d0d..51f93c1 100644
--- a/infra/bisector.py
+++ b/infra/bisector.py
@@ -115,7 +115,10 @@
         'Bisection Error: Both the first and the last commits in'
         'the given range have the same behavior, bisection is not possible. ')
     return 1
-  print('Error was introduced at commit %s' % result.commit)
+  if args.type == 'regressed':
+    print('Error was introduced at commit %s' % result.commit)
+  elif args.type == 'fixed':
+    print('Error was fixed at commit %s' % result.commit)
   return 0
 
 
@@ -131,7 +134,7 @@
   return None
 
 
-def _check_for_crash(project_name, fuzz_target, test_case_path):
+def _check_for_crash(project_name, fuzz_target, testcase_path):
   """Check for crash."""
 
   def docker_run(args):
@@ -142,12 +145,15 @@
     return utils.execute(command + args)
 
   logging.info('Checking for crash')
-  out, err, return_code = helper.reproduce_impl(project_name,
-                                                fuzz_target,
-                                                False, [], [],
-                                                test_case_path,
-                                                runner=docker_run,
-                                                err_result=(None, None, None))
+  out, err, return_code = helper.reproduce_impl(
+      project=helper.Project(project_name),
+      fuzzer_name=fuzz_target,
+      valgrind=False,
+      env_to_add=[],
+      fuzzer_args=[],
+      testcase_path=testcase_path,
+      run_function=docker_run,
+      err_result=(None, None, None))
   if return_code is None:
     return None
 
@@ -167,7 +173,7 @@
 # pylint: disable=too-many-locals
 # pylint: disable=too-many-arguments
 # pylint: disable=too-many-statements
-def _bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
+def _bisect(bisect_type, old_commit, new_commit, testcase_path, fuzz_target,
             build_data):
   """Perform the bisect."""
   # pylint: disable=too-many-branches
@@ -212,7 +218,7 @@
       raise BisectError('Invalid bisect type ' + bisect_type, repo_url)
 
     expected_error = _check_for_crash(build_data.project_name, fuzz_target,
-                                      test_case_path)
+                                      testcase_path)
     logging.info('new_commit result = %s', expected_error)
 
     if not should_crash and expected_error:
@@ -231,7 +237,7 @@
         raise BisectError('Failed to build old_commit', repo_url)
 
       if _check_for_crash(build_data.project_name, fuzz_target,
-                          test_case_path) == expected_error:
+                          testcase_path) == expected_error:
         logging.warning('old_commit %s had same result as new_commit %s',
                         old_commit, new_commit)
         # Try again on an slightly older commit.
@@ -266,7 +272,7 @@
         continue
 
       current_error = _check_for_crash(build_data.project_name, fuzz_target,
-                                       test_case_path)
+                                       testcase_path)
       logging.info('Current result = %s', current_error)
       if expected_error == current_error:
         new_idx = curr_idx
@@ -277,16 +283,16 @@
 
 # pylint: disable=too-many-locals
 # pylint: disable=too-many-arguments
-def bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
+def bisect(bisect_type, old_commit, new_commit, testcase_path, fuzz_target,
            build_data):
   """From a commit range, this function caluclates which introduced a
-  specific error from a fuzz test_case_path.
+  specific error from a fuzz testcase_path.
 
   Args:
     bisect_type: The type of the bisect ('regressed' or 'fixed').
     old_commit: The oldest commit in the error regression range.
     new_commit: The newest commit in the error regression range.
-    test_case_path: The file path of the test case that triggers the error
+    testcase_path: The file path of the test case that triggers the error
     fuzz_target: The name of the fuzzer to be tested.
     build_data: a class holding all of the input parameters for bisection.
 
@@ -297,7 +303,7 @@
     ValueError: when a repo url can't be determine from the project.
   """
   try:
-    return _bisect(bisect_type, old_commit, new_commit, test_case_path,
+    return _bisect(bisect_type, old_commit, new_commit, testcase_path,
                    fuzz_target, build_data)
   finally:
     # Clean up projects/ as _bisect may have modified it.
diff --git a/infra/bisector_test.py b/infra/bisector_test.py
index 5e3dc52..d93ac32 100644
--- a/infra/bisector_test.py
+++ b/infra/bisector_test.py
@@ -45,7 +45,7 @@
         architecture='x86_64')
     with self.assertRaises(ValueError):
       bisector.bisect(self.BISECT_TYPE, test_repo.old_commit,
-                      test_repo.new_commit, test_repo.test_case_path,
+                      test_repo.new_commit, test_repo.testcase_path,
                       test_repo.fuzz_target, build_data)
 
   def test_bisect(self):
@@ -58,7 +58,7 @@
             sanitizer='address',
             architecture='x86_64')
         result = bisector.bisect(self.BISECT_TYPE, test_repo.old_commit,
-                                 test_repo.new_commit, test_repo.test_case_path,
+                                 test_repo.new_commit, test_repo.testcase_path,
                                  test_repo.fuzz_target, build_data)
         self.assertEqual(result.commit, test_repo.intro_commit)
 
diff --git a/infra/build/functions/base_images.py b/infra/build/functions/base_images.py
index 8c9b2d8..593323f 100644
--- a/infra/build/functions/base_images.py
+++ b/infra/build/functions/base_images.py
@@ -15,7 +15,6 @@
 ################################################################################
 """Cloud function to build base images on Google Cloud Builder."""
 
-import datetime
 import logging
 
 import google.auth
@@ -25,14 +24,17 @@
     'base-image',
     'base-clang',
     'base-builder',
+    'base-builder-go',
+    'base-builder-jvm',
+    'base-builder-python',
+    'base-builder-rust',
+    'base-builder-swift',
     'base-runner',
     'base-runner-debug',
 ]
 BASE_PROJECT = 'oss-fuzz-base'
 TAG_PREFIX = f'gcr.io/{BASE_PROJECT}/'
-
-BASE_SANITIZER_LIBS_IMAGE = TAG_PREFIX + 'base-sanitizer-libs-builder'
-MSAN_LIBS_IMAGE = TAG_PREFIX + 'msan-libs-builder'
+MAJOR_VERSION = 'v1'
 
 
 def _get_base_image_steps(images, tag_prefix=TAG_PREFIX):
@@ -46,11 +48,14 @@
   }]
 
   for base_image in images:
+    image = tag_prefix + base_image
     steps.append({
         'args': [
             'build',
             '-t',
-            tag_prefix + base_image,
+            image,
+            '-t',
+            f'{image}:{MAJOR_VERSION}',
             '.',
         ],
         'dir': 'oss-fuzz/infra/base-images/' + base_image,
@@ -62,9 +67,8 @@
 
 def get_logs_url(build_id, project_id='oss-fuzz-base'):
   """Returns url that displays the build logs."""
-  url_format = ('https://console.developers.google.com/logs/viewer?'
-                'resource=build%2Fbuild_id%2F{0}&project={1}')
-  return url_format.format(build_id, project_id)
+  return ('https://console.developers.google.com/logs/viewer?'
+          f'resource=build%2Fbuild_id%2F{build_id}&project={project_id}')
 
 
 # pylint: disable=no-member
@@ -77,7 +81,7 @@
       'options': {
           'machineType': 'N1_HIGHCPU_32'
       },
-      'images': images
+      'images': images + [f'{image}:{MAJOR_VERSION}' for image in images]
   }
   cloudbuild = build('cloudbuild',
                      'v1',
@@ -99,43 +103,3 @@
   images = [tag_prefix + base_image for base_image in BASE_IMAGES]
 
   run_build(steps, images)
-
-
-def _get_msan_steps(image):
-  """Get build steps for msan-libs-builder."""
-  timestamp = datetime.datetime.utcnow().strftime('%Y%m%d%H%M')
-  upload_name = 'msan-libs-' + timestamp + '.zip'
-
-  steps = _get_base_image_steps([
-      'base-sanitizer-libs-builder',
-      'msan-libs-builder',
-  ])
-  steps.extend([{
-      'name': image,
-      'args': [
-          'bash',
-          '-c',
-          'cd /msan && zip -r /workspace/libs.zip .',
-      ],
-  }, {
-      'name':
-          'gcr.io/cloud-builders/gsutil',
-      'args': [
-          'cp',
-          '/workspace/libs.zip',
-          'gs://oss-fuzz-msan-libs/' + upload_name,
-      ],
-  }])
-  return steps
-
-
-def base_msan_builder(event, context):
-  """Cloud function to build base images."""
-  del event, context
-  steps = _get_msan_steps(MSAN_LIBS_IMAGE)
-  images = [
-      BASE_SANITIZER_LIBS_IMAGE,
-      MSAN_LIBS_IMAGE,
-  ]
-
-  run_build(steps, images)
diff --git a/infra/build/functions/build_and_run_coverage.py b/infra/build/functions/build_and_run_coverage.py
old mode 100644
new mode 100755
index cc2de5a..1195776
--- a/infra/build/functions/build_and_run_coverage.py
+++ b/infra/build/functions/build_and_run_coverage.py
@@ -13,11 +13,11 @@
 # limitations under the License.
 #
 ################################################################################
-#!/usr/bin/python2
+#!/usr/bin/env python3
 """Starts and runs coverage build on Google Cloud Builder.
-Usage: build_and_run_coverage.py <project_dir>
+
+Usage: build_and_run_coverage.py <project>.
 """
-import datetime
 import json
 import logging
 import os
@@ -27,119 +27,105 @@
 import build_project
 
 SANITIZER = 'coverage'
-CONFIGURATION = ['FUZZING_ENGINE=libfuzzer', 'SANITIZER=%s' % SANITIZER]
+FUZZING_ENGINE = 'libfuzzer'
+ARCHITECTURE = 'x86_64'
+
 PLATFORM = 'linux'
 
-COVERAGE_BUILD_TAG = 'coverage'
+COVERAGE_BUILD_TYPE = 'coverage'
 
 # Where code coverage reports need to be uploaded to.
 COVERAGE_BUCKET_NAME = 'oss-fuzz-coverage'
 
-# Link to the code coverage report in HTML format.
-HTML_REPORT_URL_FORMAT = (build_lib.GCS_URL_BASENAME + COVERAGE_BUCKET_NAME +
-                          '/{project}/reports/{date}/{platform}/index.html')
-
 # This is needed for ClusterFuzz to pick up the most recent reports data.
-LATEST_REPORT_INFO_URL = ('/' + COVERAGE_BUCKET_NAME +
-                          '/latest_report_info/{project}.json')
+
 LATEST_REPORT_INFO_CONTENT_TYPE = 'application/json'
 
-# Link where to upload code coverage report files to.
-UPLOAD_URL_FORMAT = 'gs://' + COVERAGE_BUCKET_NAME + '/{project}/{type}/{date}'
-
 # Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
+LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'jvm', 'rust', 'swift']
 
 
-def usage():
-  """Exit with code 1 and display syntax to use this file."""
-  sys.stderr.write("Usage: " + sys.argv[0] + " <project_dir>\n")
-  sys.exit(1)
+class Bucket:  # pylint: disable=too-few-public-methods
+  """Class representing the coverage GCS bucket."""
+
+  def __init__(self, project, date, platform, testing):
+    self.coverage_bucket_name = 'oss-fuzz-coverage'
+    if testing:
+      self.coverage_bucket_name += '-testing'
+
+    self.date = date
+    self.project = project
+    self.html_report_url = (
+        f'{build_lib.GCS_URL_BASENAME}{self.coverage_bucket_name}/{project}'
+        f'/reports/{date}/{platform}/index.html')
+    self.latest_report_info_url = (f'/{COVERAGE_BUCKET_NAME}'
+                                   f'/latest_report_info/{project}.json')
+
+  def get_upload_url(self, upload_type):
+    """Returns an upload url for |upload_type|."""
+    return (f'gs://{self.coverage_bucket_name}/{self.project}'
+            f'/{upload_type}/{self.date}')
 
 
-# pylint: disable=too-many-locals
-def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
-                    image_project, base_images_project):
+def get_build_steps(  # pylint: disable=too-many-locals, too-many-arguments
+    project_name, project_yaml_contents, dockerfile_lines, image_project,
+    base_images_project, config):
   """Returns build steps for project."""
-  project_yaml = build_project.load_project_yaml(project_name,
-                                                 project_yaml_file,
-                                                 image_project)
-  if project_yaml['disabled']:
-    logging.info('Project "%s" is disabled.', project_name)
+  project = build_project.Project(project_name, project_yaml_contents,
+                                  dockerfile_lines, image_project)
+  if project.disabled:
+    logging.info('Project "%s" is disabled.', project.name)
     return []
 
-  if project_yaml['language'] not in LANGUAGES_WITH_COVERAGE_SUPPORT:
+  if project.fuzzing_language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
     logging.info(
         'Project "%s" is written in "%s", coverage is not supported yet.',
-        project_name, project_yaml['language'])
+        project.name, project.fuzzing_language)
     return []
 
-  name = project_yaml['name']
-  image = project_yaml['image']
-  language = project_yaml['language']
-  report_date = datetime.datetime.now().strftime('%Y%m%d')
+  report_date = build_project.get_datetime_now().strftime('%Y%m%d')
+  bucket = Bucket(project.name, report_date, PLATFORM, config.testing)
 
-  build_steps = build_lib.project_image_steps(name, image, language)
+  build_steps = build_lib.project_image_steps(
+      project.name,
+      project.image,
+      project.fuzzing_language,
+      branch=config.branch,
+      test_image_suffix=config.test_image_suffix)
 
-  env = CONFIGURATION[:]
-  out = '/workspace/out/' + SANITIZER
-  env.append('OUT=' + out)
-  env.append('FUZZING_LANGUAGE=' + language)
-
-  workdir = build_project.workdir_from_dockerfile(dockerfile_lines)
-  if not workdir:
-    workdir = '/src'
-
-  failure_msg = ('*' * 80 + '\nCoverage build failed.\nTo reproduce, run:\n'
-                 'python infra/helper.py build_image {name}\n'
-                 'python infra/helper.py build_fuzzers --sanitizer coverage '
-                 '{name}\n' + '*' * 80).format(name=name)
-
-  # Compilation step.
-  build_steps.append({
-      'name':
-          image,
-      'env':
-          env,
-      'args': [
-          'bash',
-          '-c',
-          # Remove /out to make sure there are non instrumented binaries.
-          # `cd /src && cd {workdir}` (where {workdir} is parsed from the
-          # Dockerfile). Container Builder overrides our workdir so we need
-          # to add this step to set it back.
-          ('rm -r /out && cd /src && cd {workdir} && mkdir -p {out} && '
-           'compile || (echo "{failure_msg}" && false)'
-          ).format(workdir=workdir, out=out, failure_msg=failure_msg),
-      ],
-  })
-
-  download_corpora_steps = build_lib.download_corpora_steps(project_name)
+  build = build_project.Build('libfuzzer', 'coverage', 'x86_64')
+  env = build_project.get_env(project.fuzzing_language, build)
+  build_steps.append(
+      build_project.get_compile_step(project, build, env, config.parallel))
+  download_corpora_steps = build_lib.download_corpora_steps(
+      project.name, testing=config.testing)
   if not download_corpora_steps:
-    logging.info('Skipping code coverage build for %s.', project_name)
+    logging.info('Skipping code coverage build for %s.', project.name)
     return []
 
   build_steps.extend(download_corpora_steps)
 
   failure_msg = ('*' * 80 + '\nCode coverage report generation failed.\n'
                  'To reproduce, run:\n'
-                 'python infra/helper.py build_image {name}\n'
+                 f'python infra/helper.py build_image {project.name}\n'
                  'python infra/helper.py build_fuzzers --sanitizer coverage '
-                 '{name}\n'
-                 'python infra/helper.py coverage {name}\n' +
-                 '*' * 80).format(name=name)
+                 f'{project.name}\n'
+                 f'python infra/helper.py coverage {project.name}\n' + '*' * 80)
 
   # Unpack the corpus and run coverage script.
   coverage_env = env + [
       'HTTP_PORT=',
-      'COVERAGE_EXTRA_ARGS=%s' % project_yaml['coverage_extra_args'].strip(),
+      f'COVERAGE_EXTRA_ARGS={project.coverage_extra_args.strip()}',
   ]
-  if 'dataflow' in project_yaml['fuzzing_engines']:
+  if 'dataflow' in project.fuzzing_engines:
     coverage_env.append('FULL_SUMMARY_PER_TARGET=1')
 
   build_steps.append({
-      'name': 'gcr.io/{0}/base-runner'.format(base_images_project),
-      'env': coverage_env,
+      'name':
+          build_project.get_runner_image_name(base_images_project,
+                                              config.test_image_suffix),
+      'env':
+          coverage_env,
       'args': [
           'bash', '-c',
           ('for f in /corpus/*.zip; do unzip -q $f -d ${f%%.*} || ('
@@ -158,9 +144,7 @@
   })
 
   # Upload the report.
-  upload_report_url = UPLOAD_URL_FORMAT.format(project=project_name,
-                                               type='reports',
-                                               date=report_date)
+  upload_report_url = bucket.get_upload_url('reports')
 
   # Delete the existing report as gsutil cannot overwrite it in a useful way due
   # to the lack of `-T` option (it creates a subdir in the destination dir).
@@ -172,15 +156,14 @@
           '-m',
           'cp',
           '-r',
-          os.path.join(out, 'report'),
+          os.path.join(build.out, 'report'),
           upload_report_url,
       ],
   })
 
   # Upload the fuzzer stats. Delete the old ones just in case.
-  upload_fuzzer_stats_url = UPLOAD_URL_FORMAT.format(project=project_name,
-                                                     type='fuzzer_stats',
-                                                     date=report_date)
+  upload_fuzzer_stats_url = bucket.get_upload_url('fuzzer_stats')
+
   build_steps.append(build_lib.gsutil_rm_rf_step(upload_fuzzer_stats_url))
   build_steps.append({
       'name':
@@ -189,15 +172,13 @@
           '-m',
           'cp',
           '-r',
-          os.path.join(out, 'fuzzer_stats'),
+          os.path.join(build.out, 'fuzzer_stats'),
           upload_fuzzer_stats_url,
       ],
   })
 
   # Upload the fuzzer logs. Delete the old ones just in case
-  upload_fuzzer_logs_url = UPLOAD_URL_FORMAT.format(project=project_name,
-                                                    type='logs',
-                                                    date=report_date)
+  upload_fuzzer_logs_url = bucket.get_upload_url('logs')
   build_steps.append(build_lib.gsutil_rm_rf_step(upload_fuzzer_logs_url))
   build_steps.append({
       'name':
@@ -206,15 +187,13 @@
           '-m',
           'cp',
           '-r',
-          os.path.join(out, 'logs'),
+          os.path.join(build.out, 'logs'),
           upload_fuzzer_logs_url,
       ],
   })
 
   # Upload srcmap.
-  srcmap_upload_url = UPLOAD_URL_FORMAT.format(project=project_name,
-                                               type='srcmap',
-                                               date=report_date)
+  srcmap_upload_url = bucket.get_upload_url('srcmap')
   srcmap_upload_url = srcmap_upload_url.rstrip('/') + '.json'
   build_steps.append({
       'name': 'gcr.io/cloud-builders/gsutil',
@@ -227,15 +206,13 @@
 
   # Update the latest report information file for ClusterFuzz.
   latest_report_info_url = build_lib.get_signed_url(
-      LATEST_REPORT_INFO_URL.format(project=project_name),
+      bucket.latest_report_info_url,
       content_type=LATEST_REPORT_INFO_CONTENT_TYPE)
   latest_report_info_body = json.dumps({
       'fuzzer_stats_dir':
           upload_fuzzer_stats_url,
       'html_report_url':
-          HTML_REPORT_URL_FORMAT.format(project=project_name,
-                                        date=report_date,
-                                        platform=PLATFORM),
+          bucket.html_report_url,
       'report_date':
           report_date,
       'report_summary_path':
@@ -251,25 +228,10 @@
 
 def main():
   """Build and run coverage for projects."""
-  if len(sys.argv) != 2:
-    usage()
-
-  image_project = 'oss-fuzz'
-  base_images_project = 'oss-fuzz-base'
-  project_dir = sys.argv[1].rstrip(os.path.sep)
-  project_name = os.path.basename(project_dir)
-  dockerfile_path = os.path.join(project_dir, 'Dockerfile')
-  project_yaml_path = os.path.join(project_dir, 'project.yaml')
-
-  with open(dockerfile_path) as docker_file:
-    dockerfile_lines = docker_file.readlines()
-
-  with open(project_yaml_path) as project_yaml_file:
-    steps = get_build_steps(project_name, project_yaml_file, dockerfile_lines,
-                            image_project, base_images_project)
-
-  build_project.run_build(steps, project_name, COVERAGE_BUILD_TAG)
+  return build_project.build_script_main(
+      'Generates coverage report for project.', get_build_steps,
+      COVERAGE_BUILD_TYPE)
 
 
-if __name__ == "__main__":
-  main()
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/infra/build/functions/build_and_run_coverage_test.py b/infra/build/functions/build_and_run_coverage_test.py
new file mode 100644
index 0000000..83ea39e
--- /dev/null
+++ b/infra/build/functions/build_and_run_coverage_test.py
@@ -0,0 +1,78 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Unit tests for build_and_run_coverage."""
+import json
+import os
+import sys
+import unittest
+from unittest import mock
+
+from pyfakefs import fake_filesystem_unittest
+
+FUNCTIONS_DIR = os.path.dirname(__file__)
+sys.path.append(FUNCTIONS_DIR)
+# pylint: disable=wrong-import-position
+
+import build_and_run_coverage
+import build_project
+import test_utils
+
+# pylint: disable=no-member
+
+
+class TestRequestCoverageBuilds(fake_filesystem_unittest.TestCase):
+  """Unit tests for sync."""
+
+  def setUp(self):
+    self.maxDiff = None  # pylint: disable=invalid-name
+    self.setUpPyfakefs()
+
+  @mock.patch('build_lib.get_signed_url', return_value='test_url')
+  @mock.patch('build_lib.download_corpora_steps',
+              return_value=[{
+                  'url': 'test_download'
+              }])
+  @mock.patch('build_project.get_datetime_now',
+              return_value=test_utils.FAKE_DATETIME)
+  def test_get_coverage_build_steps(self, mock_url, mock_corpora_steps,
+                                    mock_get_datetime_now):
+    """Test for get_build_steps."""
+    del mock_url, mock_corpora_steps, mock_get_datetime_now
+    project_yaml_contents = ('language: c++\n'
+                             'sanitizers:\n'
+                             '  - address\n'
+                             'architectures:\n'
+                             '  - x86_64\n')
+    self.fs.create_dir(test_utils.PROJECT_DIR)
+    test_utils.create_project_data(test_utils.PROJECT, project_yaml_contents)
+
+    expected_build_steps_file_path = test_utils.get_test_data_file_path(
+        'expected_coverage_build_steps.json')
+    self.fs.add_real_file(expected_build_steps_file_path)
+    with open(expected_build_steps_file_path) as expected_build_steps_file:
+      expected_coverage_build_steps = json.load(expected_build_steps_file)
+
+    config = build_project.Config(False, False, None, False)
+    project_yaml, dockerfile = build_project.get_project_data(
+        test_utils.PROJECT)
+    build_steps = build_and_run_coverage.get_build_steps(
+        test_utils.PROJECT, project_yaml, dockerfile, test_utils.IMAGE_PROJECT,
+        test_utils.BASE_IMAGES_PROJECT, config)
+    self.assertEqual(build_steps, expected_coverage_build_steps)
+
+
+if __name__ == '__main__':
+  unittest.main(exit=False)
diff --git a/infra/build/functions/build_lib.py b/infra/build/functions/build_lib.py
index 007579e..292ef68 100644
--- a/infra/build/functions/build_lib.py
+++ b/infra/build/functions/build_lib.py
@@ -83,11 +83,23 @@
   return url
 
 
-def _get_targets_list(project_name):
+def get_upload_bucket(engine, architecture, testing):
+  """Returns the upload bucket for |engine| and architecture. Returns the
+  testing bucket if |testing|."""
+  bucket = ENGINE_INFO[engine].upload_bucket
+  if architecture != 'x86_64':
+    bucket += '-' + architecture
+  if testing:
+    bucket += '-testing'
+  return bucket
+
+
+def _get_targets_list(project_name, testing):
   """Returns target list."""
-  # libFuzzer ASan is the default configuration, get list of targets from it.
-  url = get_targets_list_url(ENGINE_INFO['libfuzzer'].upload_bucket,
-                             project_name, 'address')
+  # libFuzzer ASan 'x86_84' is the default configuration, get list of targets
+  # from it.
+  bucket = get_upload_bucket('libfuzzer', 'x86_64', testing)
+  url = get_targets_list_url(bucket, project_name, 'address')
 
   url = urlparse.urljoin(GCS_URL_BASENAME, url)
   response = requests.get(url)
@@ -104,7 +116,7 @@
 def get_signed_url(path, method='PUT', content_type=''):
   """Returns signed url."""
   timestamp = int(time.time() + BUILD_TIMEOUT)
-  blob = '{0}\n\n{1}\n{2}\n{3}'.format(method, content_type, timestamp, path)
+  blob = f'{method}\n\n{content_type}\n{timestamp}\n{path}'
 
   service_account_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')
   if service_account_path:
@@ -119,7 +131,7 @@
                                           credentials=credentials,
                                           cache_discovery=False)
     client_id = project + '@appspot.gserviceaccount.com'
-    service_account = 'projects/-/serviceAccounts/{0}'.format(client_id)
+    service_account = f'projects/-/serviceAccounts/{client_id}'
     response = iam.projects().serviceAccounts().signBlob(
         name=service_account,
         body={
@@ -133,14 +145,13 @@
       'Expires': timestamp,
       'Signature': signature,
   }
-  return ('https://storage.googleapis.com{0}?'.format(path) +
-          urlparse.urlencode(values))
+  return f'https://storage.googleapis.com{path}?{urlparse.urlencode(values)}'
 
 
-def download_corpora_steps(project_name):
+def download_corpora_steps(project_name, testing):
   """Returns GCB steps for downloading corpora backups for the given project.
   """
-  fuzz_targets = _get_targets_list(project_name)
+  fuzz_targets = _get_targets_list(project_name, testing)
   if not fuzz_targets:
     sys.stderr.write('No fuzz targets found for project "%s".\n' % project_name)
     return None
@@ -206,15 +217,72 @@
   return step
 
 
-def project_image_steps(name, image, language):
+def get_pull_test_images_steps(test_image_suffix):
+  """Returns steps to pull testing versions of base-images and tag them so that
+  they are used in builds."""
+  images = [
+      'gcr.io/oss-fuzz-base/base-builder',
+      'gcr.io/oss-fuzz-base/base-builder-swift',
+      'gcr.io/oss-fuzz-base/base-builder-jvm',
+      'gcr.io/oss-fuzz-base/base-builder-go',
+      'gcr.io/oss-fuzz-base/base-builder-python',
+      'gcr.io/oss-fuzz-base/base-builder-rust',
+  ]
+  steps = []
+  for image in images:
+    test_image = image + '-' + test_image_suffix
+    steps.append({
+        'name': 'gcr.io/cloud-builders/docker',
+        'args': [
+            'pull',
+            test_image,
+        ],
+        'waitFor': '-'  # Start this immediately, don't wait for previous step.
+    })
+
+    # This step is hacky but gives us great flexibility. OSS-Fuzz has hardcoded
+    # references to gcr.io/oss-fuzz-base/base-builder (in dockerfiles, for
+    # example) and gcr.io/oss-fuzz-base-runner (in this build code). But the
+    # testing versions of those images are called e.g.
+    # gcr.io/oss-fuzz-base/base-builder-testing and
+    # gcr.io/oss-fuzz-base/base-runner-testing. How can we get the build to use
+    # the testing images instead of the real ones? By doing this step: tagging
+    # the test image with the non-test version, so that the test version is used
+    # instead of pulling the real one.
+    steps.append({
+        'name': 'gcr.io/cloud-builders/docker',
+        'args': ['tag', test_image, image],
+    })
+  return steps
+
+
+def get_srcmap_step_id():
+  """Returns the id for the srcmap step."""
+  return 'srcmap'
+
+
+def project_image_steps(name,
+                        image,
+                        language,
+                        branch=None,
+                        test_image_suffix=None):
   """Returns GCB steps to build OSS-Fuzz project image."""
-  steps = [{
+  clone_step = {
       'args': [
-          'clone',
-          'https://github.com/google/oss-fuzz.git',
+          'clone', 'https://github.com/google/oss-fuzz.git', '--depth', '1'
       ],
       'name': 'gcr.io/cloud-builders/git',
-  }, {
+  }
+  if branch:
+    # Do this to support testing other branches.
+    clone_step['args'].extend(['--branch', branch])
+
+  steps = [clone_step]
+  if test_image_suffix:
+    steps.extend(get_pull_test_images_steps(test_image_suffix))
+
+  srcmap_step_id = get_srcmap_step_id()
+  steps += [{
       'name': 'gcr.io/cloud-builders/docker',
       'args': [
           'build',
@@ -224,8 +292,7 @@
       ],
       'dir': 'oss-fuzz/projects/' + name,
   }, {
-      'name':
-          image,
+      'name': image,
       'args': [
           'bash', '-c',
           'srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json'
@@ -234,6 +301,7 @@
           'OSSFUZZ_REVISION=$REVISION_ID',
           'FUZZING_LANGUAGE=%s' % language,
       ],
+      'id': srcmap_step_id
   }]
 
   return steps
diff --git a/infra/build/functions/build_project.py b/infra/build/functions/build_project.py
old mode 100644
new mode 100755
index 9115c85..bdc7985
--- a/infra/build/functions/build_project.py
+++ b/infra/build/functions/build_project.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-#!/usr/bin/python2
+#!/usr/bin/env python3
 """Starts project build on Google Cloud Builder.
 
 Usage: build_project.py <project_dir>
@@ -21,37 +21,27 @@
 
 from __future__ import print_function
 
+import argparse
+import collections
 import datetime
 import json
 import logging
 import os
+import posixpath
 import re
 import sys
 
+from googleapiclient.discovery import build as cloud_build
+import oauth2client.client
 import six
 import yaml
 
-from oauth2client.client import GoogleCredentials
-from googleapiclient.discovery import build
-
 import build_lib
 
-FUZZING_BUILD_TAG = 'fuzzing'
+FUZZING_BUILD_TYPE = 'fuzzing'
 
 GCB_LOGS_BUCKET = 'oss-fuzz-gcb-logs'
 
-CONFIGURATIONS = {
-    'sanitizer-address': ['SANITIZER=address'],
-    'sanitizer-dataflow': ['SANITIZER=dataflow'],
-    'sanitizer-memory': ['SANITIZER=memory'],
-    'sanitizer-undefined': ['SANITIZER=undefined'],
-    'engine-libfuzzer': ['FUZZING_ENGINE=libfuzzer'],
-    'engine-afl': ['FUZZING_ENGINE=afl'],
-    'engine-honggfuzz': ['FUZZING_ENGINE=honggfuzz'],
-    'engine-dataflow': ['FUZZING_ENGINE=dataflow'],
-    'engine-none': ['FUZZING_ENGINE=none'],
-}
-
 DEFAULT_ARCHITECTURES = ['x86_64']
 DEFAULT_ENGINES = ['libfuzzer', 'afl', 'honggfuzz']
 DEFAULT_SANITIZERS = ['address', 'undefined']
@@ -61,19 +51,100 @@
 
 QUEUE_TTL_SECONDS = 60 * 60 * 24  # 24 hours.
 
+PROJECTS_DIR = os.path.abspath(
+    os.path.join(__file__, os.path.pardir, os.path.pardir, os.path.pardir,
+                 os.path.pardir, 'projects'))
 
-def usage():
-  """Exit with code 1 and display syntax to use this file."""
-  sys.stderr.write('Usage: ' + sys.argv[0] + ' <project_dir>\n')
-  sys.exit(1)
+DEFAULT_GCB_OPTIONS = {'machineType': 'N1_HIGHCPU_32'}
+
+Config = collections.namedtuple(
+    'Config', ['testing', 'test_image_suffix', 'branch', 'parallel'])
+
+WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)')
 
 
-def set_yaml_defaults(project_name, project_yaml, image_project):
-  """Set project.yaml's default parameters."""
+class Build:  # pylint: disable=too-few-public-methods
+  """Class representing the configuration for a build."""
+
+  def __init__(self, fuzzing_engine, sanitizer, architecture):
+    self.fuzzing_engine = fuzzing_engine
+    self.sanitizer = sanitizer
+    self.architecture = architecture
+    self.targets_list_filename = build_lib.get_targets_list_filename(
+        self.sanitizer)
+
+  @property
+  def out(self):
+    """Returns the out directory for the build."""
+    return posixpath.join(
+        '/workspace/out/',
+        f'{self.fuzzing_engine}-{self.sanitizer}-{self.architecture}')
+
+
+def get_project_data(project_name):
+  """Returns a tuple containing the contents of the project.yaml and Dockerfile
+  of |project_name|. Raises a FileNotFoundError if there is no Dockerfile for
+  |project_name|."""
+  project_dir = os.path.join(PROJECTS_DIR, project_name)
+  dockerfile_path = os.path.join(project_dir, 'Dockerfile')
+  try:
+    with open(dockerfile_path) as dockerfile:
+      dockerfile = dockerfile.read()
+  except FileNotFoundError:
+    logging.error('Project "%s" does not have a dockerfile.', project_name)
+    raise
+  project_yaml_path = os.path.join(project_dir, 'project.yaml')
+  with open(project_yaml_path, 'r') as project_yaml_file_handle:
+    project_yaml_contents = project_yaml_file_handle.read()
+  return project_yaml_contents, dockerfile
+
+
+class Project:  # pylint: disable=too-many-instance-attributes
+  """Class representing an OSS-Fuzz project."""
+
+  def __init__(self, name, project_yaml_contents, dockerfile, image_project):
+    project_yaml = yaml.safe_load(project_yaml_contents)
+    self.name = name
+    self.image_project = image_project
+    self.workdir = workdir_from_dockerfile(dockerfile)
+    set_yaml_defaults(project_yaml)
+    self._sanitizers = project_yaml['sanitizers']
+    self.disabled = project_yaml['disabled']
+    self.architectures = project_yaml['architectures']
+    self.fuzzing_engines = project_yaml['fuzzing_engines']
+    self.coverage_extra_args = project_yaml['coverage_extra_args']
+    self.labels = project_yaml['labels']
+    self.fuzzing_language = project_yaml['language']
+    self.run_tests = project_yaml['run_tests']
+
+  @property
+  def sanitizers(self):
+    """Returns processed sanitizers."""
+    assert isinstance(self._sanitizers, list)
+    processed_sanitizers = []
+    for sanitizer in self._sanitizers:
+      if isinstance(sanitizer, six.string_types):
+        processed_sanitizers.append(sanitizer)
+      elif isinstance(sanitizer, dict):
+        for key in sanitizer.keys():
+          processed_sanitizers.append(key)
+
+    return processed_sanitizers
+
+  @property
+  def image(self):
+    """Returns the docker image for the project."""
+    return f'gcr.io/{self.image_project}/{self.name}'
+
+
+def get_last_step_id(steps):
+  """Returns the id of the last step in |steps|."""
+  return steps[-1]['id']
+
+
+def set_yaml_defaults(project_yaml):
+  """Sets project.yaml's default parameters."""
   project_yaml.setdefault('disabled', False)
-  project_yaml.setdefault('name', project_name)
-  project_yaml.setdefault('image',
-                          'gcr.io/{0}/{1}'.format(image_project, project_name))
   project_yaml.setdefault('architectures', DEFAULT_ARCHITECTURES)
   project_yaml.setdefault('sanitizers', DEFAULT_SANITIZERS)
   project_yaml.setdefault('fuzzing_engines', DEFAULT_ENGINES)
@@ -82,291 +153,310 @@
   project_yaml.setdefault('labels', {})
 
 
-def is_supported_configuration(fuzzing_engine, sanitizer, architecture):
+def is_supported_configuration(build):
   """Check if the given configuration is supported."""
-  fuzzing_engine_info = build_lib.ENGINE_INFO[fuzzing_engine]
-  if architecture == 'i386' and sanitizer != 'address':
+  fuzzing_engine_info = build_lib.ENGINE_INFO[build.fuzzing_engine]
+  if build.architecture == 'i386' and build.sanitizer != 'address':
     return False
-  return (sanitizer in fuzzing_engine_info.supported_sanitizers and
-          architecture in fuzzing_engine_info.supported_architectures)
+  return (build.sanitizer in fuzzing_engine_info.supported_sanitizers and
+          build.architecture in fuzzing_engine_info.supported_architectures)
 
 
-def get_sanitizers(project_yaml):
-  """Retrieve sanitizers from project.yaml."""
-  sanitizers = project_yaml['sanitizers']
-  assert isinstance(sanitizers, list)
-
-  processed_sanitizers = []
-  for sanitizer in sanitizers:
-    if isinstance(sanitizer, six.string_types):
-      processed_sanitizers.append(sanitizer)
-    elif isinstance(sanitizer, dict):
-      for key in sanitizer.keys():
-        processed_sanitizers.append(key)
-
-  return processed_sanitizers
-
-
-def workdir_from_dockerfile(dockerfile_lines):
-  """Parse WORKDIR from the Dockerfile."""
-  workdir_regex = re.compile(r'\s*WORKDIR\s*([^\s]+)')
+def workdir_from_dockerfile(dockerfile):
+  """Parses WORKDIR from the Dockerfile."""
+  dockerfile_lines = dockerfile.split('\n')
   for line in dockerfile_lines:
-    match = re.match(workdir_regex, line)
+    match = re.match(WORKDIR_REGEX, line)
     if match:
       # We need to escape '$' since they're used for subsitutions in Container
       # Builer builds.
       return match.group(1).replace('$', '$$')
 
-  return None
+  return '/src'
 
 
-def load_project_yaml(project_name, project_yaml_file, image_project):
-  """Loads project yaml and sets default values."""
-  project_yaml = yaml.safe_load(project_yaml_file)
-  set_yaml_defaults(project_name, project_yaml, image_project)
-  return project_yaml
+def get_datetime_now():
+  """Returns datetime.datetime.now(). Used for mocking."""
+  return datetime.datetime.now()
 
 
-# pylint: disable=too-many-locals, too-many-statements, too-many-branches
-def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
-                    image_project, base_images_project):
-  """Returns build steps for project."""
-  project_yaml = load_project_yaml(project_name, project_yaml_file,
-                                   image_project)
+def get_env(fuzzing_language, build):
+  """Returns an environment for building. The environment is returned as a list
+  and is suitable for use as the "env" parameter in a GCB build step. The
+  environment variables are based on the values of |fuzzing_language| and
+  |build."""
+  env_dict = {
+      'FUZZING_LANGUAGE': fuzzing_language,
+      'FUZZING_ENGINE': build.fuzzing_engine,
+      'SANITIZER': build.sanitizer,
+      'ARCHITECTURE': build.architecture,
+      # Set HOME so that it doesn't point to a persisted volume (see
+      # https://github.com/google/oss-fuzz/issues/6035).
+      'HOME': '/root',
+      'OUT': build.out,
+  }
+  return list(sorted([f'{key}={value}' for key, value in env_dict.items()]))
 
-  if project_yaml['disabled']:
-    logging.info('Project "%s" is disabled.', project_name)
-    return []
 
-  name = project_yaml['name']
-  image = project_yaml['image']
-  language = project_yaml['language']
-  run_tests = project_yaml['run_tests']
-  time_stamp = datetime.datetime.now().strftime('%Y%m%d%H%M')
-
-  build_steps = build_lib.project_image_steps(name, image, language)
-  # Copy over MSan instrumented libraries.
-  build_steps.append({
-      'name': 'gcr.io/{0}/msan-libs-builder'.format(base_images_project),
+def get_compile_step(project, build, env, parallel):
+  """Returns the GCB step for compiling |projects| fuzzers using |env|. The type
+  of build is specified by |build|."""
+  failure_msg = (
+      '*' * 80 + '\nFailed to build.\nTo reproduce, run:\n'
+      f'python infra/helper.py build_image {project.name}\n'
+      'python infra/helper.py build_fuzzers --sanitizer '
+      f'{build.sanitizer} --engine {build.fuzzing_engine} --architecture '
+      f'{build.architecture} {project.name}\n' + '*' * 80)
+  compile_step = {
+      'name': project.image,
+      'env': env,
       'args': [
           'bash',
           '-c',
-          'cp -r /msan /workspace',
+          # Remove /out to make sure there are non instrumented binaries.
+          # `cd /src && cd {workdir}` (where {workdir} is parsed from the
+          # Dockerfile). Container Builder overrides our workdir so we need
+          # to add this step to set it back.
+          (f'rm -r /out && cd /src && cd {project.workdir} && '
+           f'mkdir -p {build.out} && compile || '
+           f'(echo "{failure_msg}" && false)'),
       ],
-  })
+      'id': get_id('compile', build),
+  }
+  if parallel:
+    maybe_add_parallel(compile_step, build_lib.get_srcmap_step_id(), parallel)
+  return compile_step
 
-  for fuzzing_engine in project_yaml['fuzzing_engines']:
-    for sanitizer in get_sanitizers(project_yaml):
-      for architecture in project_yaml['architectures']:
-        if not is_supported_configuration(fuzzing_engine, sanitizer,
-                                          architecture):
+
+def maybe_add_parallel(step, wait_for_id, parallel):
+  """Makes |step| run immediately after |wait_for_id| if |parallel|. Mutates
+  |step|."""
+  if not parallel:
+    return
+  step['waitFor'] = wait_for_id
+
+
+def get_id(step_type, build):
+  """Returns a unique step id based on |step_type| and |build|. Useful for
+  parallelizing builds."""
+  return (f'{step_type}-{build.fuzzing_engine}-{build.sanitizer}'
+          f'-{build.architecture}')
+
+
+def get_build_steps(  # pylint: disable=too-many-locals, too-many-statements, too-many-branches, too-many-arguments
+    project_name, project_yaml_contents, dockerfile, image_project,
+    base_images_project, config):
+  """Returns build steps for project."""
+
+  project = Project(project_name, project_yaml_contents, dockerfile,
+                    image_project)
+
+  if project.disabled:
+    logging.info('Project "%s" is disabled.', project.name)
+    return []
+
+  timestamp = get_datetime_now().strftime('%Y%m%d%H%M')
+
+  build_steps = build_lib.project_image_steps(
+      project.name,
+      project.image,
+      project.fuzzing_language,
+      branch=config.branch,
+      test_image_suffix=config.test_image_suffix)
+
+  # Sort engines to make AFL first to test if libFuzzer has an advantage in
+  # finding bugs first since it is generally built first.
+  for fuzzing_engine in sorted(project.fuzzing_engines):
+    for sanitizer in project.sanitizers:
+      for architecture in project.architectures:
+        build = Build(fuzzing_engine, sanitizer, architecture)
+        if not is_supported_configuration(build):
           continue
 
-        env = CONFIGURATIONS['engine-' + fuzzing_engine][:]
-        env.extend(CONFIGURATIONS['sanitizer-' + sanitizer])
-        out = '/workspace/out/' + sanitizer
-        stamped_name = '-'.join([name, sanitizer, time_stamp])
-        latest_version_file = '-'.join(
-            [name, sanitizer, LATEST_VERSION_FILENAME])
-        zip_file = stamped_name + '.zip'
-        stamped_srcmap_file = stamped_name + '.srcmap.json'
-        bucket = build_lib.ENGINE_INFO[fuzzing_engine].upload_bucket
-        if architecture != 'x86_64':
-          bucket += '-' + architecture
+        env = get_env(project.fuzzing_language, build)
+        compile_step = get_compile_step(project, build, env, config.parallel)
+        build_steps.append(compile_step)
 
-        upload_url = build_lib.get_signed_url(
-            build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, name, zip_file))
-        srcmap_url = build_lib.get_signed_url(
-            build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, name,
-                                                   stamped_srcmap_file))
-        latest_version_url = build_lib.GCS_UPLOAD_URL_FORMAT.format(
-            bucket, name, latest_version_file)
-        latest_version_url = build_lib.get_signed_url(
-            latest_version_url, content_type=LATEST_VERSION_CONTENT_TYPE)
-
-        targets_list_filename = build_lib.get_targets_list_filename(sanitizer)
-        targets_list_url = build_lib.get_signed_url(
-            build_lib.get_targets_list_url(bucket, name, sanitizer))
-
-        env.append('OUT=' + out)
-        env.append('MSAN_LIBS_PATH=/workspace/msan')
-        env.append('ARCHITECTURE=' + architecture)
-        env.append('FUZZING_LANGUAGE=' + language)
-
-        workdir = workdir_from_dockerfile(dockerfile_lines)
-        if not workdir:
-          workdir = '/src'
-
-        failure_msg = ('*' * 80 + '\nFailed to build.\nTo reproduce, run:\n'
-                       'python infra/helper.py build_image {name}\n'
-                       'python infra/helper.py build_fuzzers --sanitizer '
-                       '{sanitizer} --engine {engine} --architecture '
-                       '{architecture} {name}\n' + '*' * 80).format(
-                           name=name,
-                           sanitizer=sanitizer,
-                           engine=fuzzing_engine,
-                           architecture=architecture)
-
-        build_steps.append(
-            # compile
-            {
-                'name':
-                    image,
-                'env':
-                    env,
-                'args': [
-                    'bash',
-                    '-c',
-                    # Remove /out to break loudly when a build script
-                    # incorrectly uses /out instead of $OUT.
-                    # `cd /src && cd {workdir}` (where {workdir} is parsed from
-                    # the Dockerfile). Container Builder overrides our workdir
-                    # so we need to add this step to set it back.
-                    ('rm -r /out && cd /src && cd {workdir} && mkdir -p {out} '
-                     '&& compile || (echo "{failure_msg}" && false)'
-                    ).format(workdir=workdir, out=out, failure_msg=failure_msg),
-                ],
-            })
-
-        if sanitizer == 'memory':
-          # Patch dynamic libraries to use instrumented ones.
-          build_steps.append({
+        if project.run_tests:
+          failure_msg = (
+              '*' * 80 + '\nBuild checks failed.\n'
+              'To reproduce, run:\n'
+              f'python infra/helper.py build_image {project.name}\n'
+              'python infra/helper.py build_fuzzers --sanitizer '
+              f'{build.sanitizer} --engine {build.fuzzing_engine} '
+              f'--architecture {build.architecture} {project.name}\n'
+              'python infra/helper.py check_build --sanitizer '
+              f'{build.sanitizer} --engine {build.fuzzing_engine} '
+              f'--architecture {build.architecture} {project.name}\n' +
+              '*' * 80)
+          # Test fuzz targets.
+          test_step = {
               'name':
-                  'gcr.io/{0}/msan-libs-builder'.format(base_images_project),
+                  get_runner_image_name(base_images_project,
+                                        config.test_image_suffix),
+              'env':
+                  env,
               'args': [
-                  'bash',
-                  '-c',
-                  # TODO(ochang): Replace with just patch_build.py once
-                  # permission in image is fixed.
-                  'python /usr/local/bin/patch_build.py {0}'.format(out),
+                  'bash', '-c',
+                  f'test_all.py || (echo "{failure_msg}" && false)'
               ],
-          })
+              'id':
+                  get_id('build-check', build)
+          }
+          maybe_add_parallel(test_step, get_last_step_id(build_steps),
+                             config.parallel)
+          build_steps.append(test_step)
 
-        if run_tests:
-          failure_msg = ('*' * 80 + '\nBuild checks failed.\n'
-                         'To reproduce, run:\n'
-                         'python infra/helper.py build_image {name}\n'
-                         'python infra/helper.py build_fuzzers --sanitizer '
-                         '{sanitizer} --engine {engine} --architecture '
-                         '{architecture} {name}\n'
-                         'python infra/helper.py check_build --sanitizer '
-                         '{sanitizer} --engine {engine} --architecture '
-                         '{architecture} {name}\n' + '*' * 80).format(
-                             name=name,
-                             sanitizer=sanitizer,
-                             engine=fuzzing_engine,
-                             architecture=architecture)
-
-          build_steps.append(
-              # test binaries
-              {
-                  'name':
-                      'gcr.io/{0}/base-runner'.format(base_images_project),
-                  'env':
-                      env,
-                  'args': [
-                      'bash', '-c',
-                      'test_all.py || (echo "{0}" && false)'.format(failure_msg)
-                  ],
-              })
-
-        if project_yaml['labels']:
-          # write target labels
+        if project.labels:
+          # Write target labels.
           build_steps.append({
               'name':
-                  image,
+                  project.image,
               'env':
                   env,
               'args': [
                   '/usr/local/bin/write_labels.py',
-                  json.dumps(project_yaml['labels']),
-                  out,
+                  json.dumps(project.labels),
+                  build.out,
               ],
           })
 
-        if sanitizer == 'dataflow' and fuzzing_engine == 'dataflow':
-          dataflow_steps = dataflow_post_build_steps(name, env,
-                                                     base_images_project)
+        if build.sanitizer == 'dataflow' and build.fuzzing_engine == 'dataflow':
+          dataflow_steps = dataflow_post_build_steps(project.name, env,
+                                                     base_images_project,
+                                                     config.testing,
+                                                     config.test_image_suffix)
           if dataflow_steps:
             build_steps.extend(dataflow_steps)
           else:
             sys.stderr.write('Skipping dataflow post build steps.\n')
 
         build_steps.extend([
-            # generate targets list
+            # Generate targets list.
             {
                 'name':
-                    'gcr.io/{0}/base-runner'.format(base_images_project),
+                    get_runner_image_name(base_images_project,
+                                          config.test_image_suffix),
                 'env':
                     env,
                 'args': [
-                    'bash',
-                    '-c',
-                    'targets_list > /workspace/{0}'.format(
-                        targets_list_filename),
-                ],
-            },
-            # zip binaries
-            {
-                'name':
-                    image,
-                'args': [
                     'bash', '-c',
-                    'cd {out} && zip -r {zip_file} *'.format(out=out,
-                                                             zip_file=zip_file)
+                    f'targets_list > /workspace/{build.targets_list_filename}'
                 ],
-            },
-            # upload srcmap
-            {
-                'name': 'gcr.io/{0}/uploader'.format(base_images_project),
-                'args': [
-                    '/workspace/srcmap.json',
-                    srcmap_url,
-                ],
-            },
-            # upload binaries
-            {
-                'name': 'gcr.io/{0}/uploader'.format(base_images_project),
-                'args': [
-                    os.path.join(out, zip_file),
-                    upload_url,
-                ],
-            },
-            # upload targets list
-            {
-                'name':
-                    'gcr.io/{0}/uploader'.format(base_images_project),
-                'args': [
-                    '/workspace/{0}'.format(targets_list_filename),
-                    targets_list_url,
-                ],
-            },
-            # upload the latest.version file
-            build_lib.http_upload_step(zip_file, latest_version_url,
-                                       LATEST_VERSION_CONTENT_TYPE),
-            # cleanup
-            {
-                'name': image,
-                'args': [
-                    'bash',
-                    '-c',
-                    'rm -r ' + out,
-                ],
-            },
+            }
         ])
+        upload_steps = get_upload_steps(project, build, timestamp,
+                                        base_images_project, config.testing)
+        build_steps.extend(upload_steps)
 
   return build_steps
 
 
-def dataflow_post_build_steps(project_name, env, base_images_project):
+def get_targets_list_upload_step(bucket, project, build, uploader_image):
+  """Returns the step to upload targets_list for |build| of |project| to
+  |bucket|."""
+  targets_list_url = build_lib.get_signed_url(
+      build_lib.get_targets_list_url(bucket, project.name, build.sanitizer))
+  return {
+      'name': uploader_image,
+      'args': [
+          f'/workspace/{build.targets_list_filename}',
+          targets_list_url,
+      ],
+  }
+
+
+def get_uploader_image(base_images_project):
+  """Returns the uploader base image in |base_images_project|."""
+  return f'gcr.io/{base_images_project}/uploader'
+
+
+def get_upload_steps(project, build, timestamp, base_images_project, testing):
+  """Returns the steps for uploading the fuzzer build specified by |project| and
+  |build|. Uses |timestamp| for naming the uploads. Uses |base_images_project|
+  and |testing| for determining which image to use for the upload."""
+  bucket = build_lib.get_upload_bucket(build.fuzzing_engine, build.architecture,
+                                       testing)
+  stamped_name = '-'.join([project.name, build.sanitizer, timestamp])
+  zip_file = stamped_name + '.zip'
+  upload_url = build_lib.get_signed_url(
+      build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, project.name, zip_file))
+  stamped_srcmap_file = stamped_name + '.srcmap.json'
+  srcmap_url = build_lib.get_signed_url(
+      build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, project.name,
+                                             stamped_srcmap_file))
+  latest_version_file = '-'.join(
+      [project.name, build.sanitizer, LATEST_VERSION_FILENAME])
+  latest_version_url = build_lib.GCS_UPLOAD_URL_FORMAT.format(
+      bucket, project.name, latest_version_file)
+  latest_version_url = build_lib.get_signed_url(
+      latest_version_url, content_type=LATEST_VERSION_CONTENT_TYPE)
+  uploader_image = get_uploader_image(base_images_project)
+
+  upload_steps = [
+      # Zip binaries.
+      {
+          'name': project.image,
+          'args': ['bash', '-c', f'cd {build.out} && zip -r {zip_file} *'],
+      },
+      # Upload srcmap.
+      {
+          'name': uploader_image,
+          'args': [
+              '/workspace/srcmap.json',
+              srcmap_url,
+          ],
+      },
+      # Upload binaries.
+      {
+          'name': uploader_image,
+          'args': [
+              os.path.join(build.out, zip_file),
+              upload_url,
+          ],
+      },
+      # Upload targets list.
+      get_targets_list_upload_step(bucket, project, build, uploader_image),
+      # Upload the latest.version file.
+      build_lib.http_upload_step(zip_file, latest_version_url,
+                                 LATEST_VERSION_CONTENT_TYPE),
+      # Cleanup.
+      get_cleanup_step(project, build),
+  ]
+  return upload_steps
+
+
+def get_cleanup_step(project, build):
+  """Returns the step for cleaning up after doing |build| of |project|."""
+  return {
+      'name': project.image,
+      'args': [
+          'bash',
+          '-c',
+          'rm -r ' + build.out,
+      ],
+  }
+
+
+def get_runner_image_name(base_images_project, test_image_suffix):
+  """Returns the runner image that should be used, based on
+  |base_images_project|. Returns the testing image if |test_image_suffix|."""
+  image = f'gcr.io/{base_images_project}/base-runner'
+  if test_image_suffix:
+    image += '-' + test_image_suffix
+  return image
+
+
+def dataflow_post_build_steps(project_name, env, base_images_project, testing,
+                              test_image_suffix):
   """Appends dataflow post build steps."""
-  steps = build_lib.download_corpora_steps(project_name)
+  steps = build_lib.download_corpora_steps(project_name, testing)
   if not steps:
     return None
 
   steps.append({
       'name':
-          'gcr.io/{0}/base-runner'.format(base_images_project),
+          get_runner_image_name(base_images_project, test_image_suffix),
       'env':
           env + [
               'COLLECT_DFT_TIMEOUT=2h',
@@ -387,63 +477,126 @@
   return steps
 
 
-def get_logs_url(build_id, image_project='oss-fuzz'):
+def get_logs_url(build_id, cloud_project='oss-fuzz'):
   """Returns url where logs are displayed for the build."""
-  url_format = ('https://console.developers.google.com/logs/viewer?'
-                'resource=build%2Fbuild_id%2F{0}&project={1}')
-  return url_format.format(build_id, image_project)
+  return ('https://console.cloud.google.com/logs/viewer?'
+          f'resource=build%2Fbuild_id%2F{build_id}&project={cloud_project}')
+
+
+def get_gcb_url(build_id, cloud_project='oss-fuzz'):
+  """Returns url where logs are displayed for the build."""
+  return (f'https://console.cloud.google.com/cloud-build/builds/{build_id}'
+          f'?project={cloud_project}')
 
 
 # pylint: disable=no-member
-def run_build(build_steps, project_name, tag):
-  """Run the build for given steps on cloud build."""
+def run_build(oss_fuzz_project,
+              build_steps,
+              credentials,
+              build_type,
+              cloud_project='oss-fuzz'):
+  """Run the build for given steps on cloud build. |build_steps| are the steps
+  to run. |credentials| are are used to authenticate to GCB and build in
+  |cloud_project|. |oss_fuzz_project| and |build_type| are used to tag the build
+  in GCB so the build can be queried for debugging purposes."""
   options = {}
   if 'GCB_OPTIONS' in os.environ:
     options = yaml.safe_load(os.environ['GCB_OPTIONS'])
+  else:
+    options = DEFAULT_GCB_OPTIONS
 
+  tags = [oss_fuzz_project + '-' + build_type, build_type, oss_fuzz_project]
   build_body = {
       'steps': build_steps,
       'timeout': str(build_lib.BUILD_TIMEOUT) + 's',
       'options': options,
       'logsBucket': GCB_LOGS_BUCKET,
-      'tags': [project_name + '-' + tag,],
+      'tags': tags,
       'queueTtl': str(QUEUE_TTL_SECONDS) + 's',
   }
 
-  credentials = GoogleCredentials.get_application_default()
-  cloudbuild = build('cloudbuild',
-                     'v1',
-                     credentials=credentials,
-                     cache_discovery=False)
-  build_info = cloudbuild.projects().builds().create(projectId='oss-fuzz',
+  cloudbuild = cloud_build('cloudbuild',
+                           'v1',
+                           credentials=credentials,
+                           cache_discovery=False)
+  build_info = cloudbuild.projects().builds().create(projectId=cloud_project,
                                                      body=build_body).execute()
   build_id = build_info['metadata']['build']['id']
 
-  print('Logs:', get_logs_url(build_id), file=sys.stderr)
-  print(build_id)
+  logging.info('Build ID: %s', build_id)
+  logging.info('Logs: %s', get_logs_url(build_id, cloud_project))
+  logging.info('Cloud build page: %s', get_gcb_url(build_id, cloud_project))
+  return build_id
+
+
+def get_args(description):
+  """Parses command line arguments and returns them. Suitable for a build
+  script."""
+  parser = argparse.ArgumentParser(sys.argv[0], description=description)
+  parser.add_argument('projects', help='Projects.', nargs='+')
+  parser.add_argument('--testing',
+                      action='store_true',
+                      required=False,
+                      default=False,
+                      help='Upload to testing buckets.')
+  parser.add_argument('--test-image-suffix',
+                      required=False,
+                      default=None,
+                      help='Use testing base-images.')
+  parser.add_argument('--branch',
+                      required=False,
+                      default=None,
+                      help='Use specified OSS-Fuzz branch.')
+  parser.add_argument('--parallel',
+                      action='store_true',
+                      required=False,
+                      default=False,
+                      help='Do builds in parallel.')
+  return parser.parse_args()
+
+
+def build_script_main(script_description, get_build_steps_func, build_type):
+  """Gets arguments from command line using |script_description| as helpstring
+  description. Gets build_steps using |get_build_steps_func| and then runs those
+  steps on GCB, tagging the builds with |build_type|. Returns 0 on success, 1 on
+  failure."""
+  args = get_args(script_description)
+  logging.basicConfig(level=logging.INFO)
+
+  image_project = 'oss-fuzz'
+  base_images_project = 'oss-fuzz-base'
+
+  credentials = oauth2client.client.GoogleCredentials.get_application_default()
+  error = False
+  config = Config(args.testing, args.test_image_suffix, args.branch,
+                  args.parallel)
+  for project_name in args.projects:
+    logging.info('Getting steps for: "%s".', project_name)
+    try:
+      project_yaml_contents, dockerfile_contents = get_project_data(
+          project_name)
+    except FileNotFoundError:
+      logging.error('Couldn\'t get project data. Skipping %s.', project_name)
+      error = True
+      continue
+
+    steps = get_build_steps_func(project_name, project_yaml_contents,
+                                 dockerfile_contents, image_project,
+                                 base_images_project, config)
+    if not steps:
+      logging.error('No steps. Skipping %s.', project_name)
+      error = True
+      continue
+
+    run_build(project_name, steps, credentials, build_type)
+  return 0 if not error else 1
 
 
 def main():
   """Build and run projects."""
-  if len(sys.argv) != 2:
-    usage()
-
-  image_project = 'oss-fuzz'
-  base_images_project = 'oss-fuzz-base'
-  project_dir = sys.argv[1].rstrip(os.path.sep)
-  dockerfile_path = os.path.join(project_dir, 'Dockerfile')
-  project_yaml_path = os.path.join(project_dir, 'project.yaml')
-  project_name = os.path.basename(project_dir)
-
-  with open(dockerfile_path) as dockerfile:
-    dockerfile_lines = dockerfile.readlines()
-
-  with open(project_yaml_path) as project_yaml_file:
-    steps = get_build_steps(project_name, project_yaml_file, dockerfile_lines,
-                            image_project, base_images_project)
-
-  run_build(steps, project_name, FUZZING_BUILD_TAG)
+  return build_script_main('Builds a project on GCB.', get_build_steps,
+                           FUZZING_BUILD_TYPE)
 
 
 if __name__ == '__main__':
-  main()
+  sys.exit(main())
diff --git a/infra/build/functions/build_project_test.py b/infra/build/functions/build_project_test.py
new file mode 100644
index 0000000..43f6c1c
--- /dev/null
+++ b/infra/build/functions/build_project_test.py
@@ -0,0 +1,77 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Unit tests for build_project."""
+import json
+import os
+import sys
+import unittest
+from unittest import mock
+
+from pyfakefs import fake_filesystem_unittest
+
+FUNCTIONS_DIR = os.path.dirname(__file__)
+sys.path.append(FUNCTIONS_DIR)
+# pylint: disable=wrong-import-position
+
+import build_project
+import test_utils
+
+# pylint: disable=no-member
+
+
+class TestRequestCoverageBuilds(fake_filesystem_unittest.TestCase):
+  """Unit tests for sync."""
+
+  def setUp(self):
+    self.maxDiff = None  # pylint: disable=invalid-name
+    self.setUpPyfakefs()
+
+  @mock.patch('build_lib.get_signed_url', return_value='test_url')
+  @mock.patch('build_project.get_datetime_now',
+              return_value=test_utils.FAKE_DATETIME)
+  def test_get_build_steps(self, mock_url, mock_get_datetime_now):
+    """Test for get_build_steps."""
+    del mock_url, mock_get_datetime_now
+    project_yaml_contents = ('language: c++\n'
+                             'sanitizers:\n'
+                             '  - address\n'
+                             '  - memory\n'
+                             '  - undefined\n'
+                             'architectures:\n'
+                             '  - x86_64\n'
+                             '  - i386\n')
+    self.fs.create_dir(test_utils.PROJECT_DIR)
+    test_utils.create_project_data(test_utils.PROJECT, project_yaml_contents)
+
+    expected_build_steps_file_path = test_utils.get_test_data_file_path(
+        'expected_build_steps.json')
+    self.fs.add_real_file(expected_build_steps_file_path)
+    with open(expected_build_steps_file_path) as expected_build_steps_file:
+      expected_build_steps = json.load(expected_build_steps_file)
+
+    config = build_project.Config(False, False, None, False)
+    project_yaml, dockerfile = build_project.get_project_data(
+        test_utils.PROJECT)
+    build_steps = build_project.get_build_steps(test_utils.PROJECT,
+                                                project_yaml, dockerfile,
+                                                test_utils.IMAGE_PROJECT,
+                                                test_utils.BASE_IMAGES_PROJECT,
+                                                config)
+    self.assertEqual(build_steps, expected_build_steps)
+
+
+if __name__ == '__main__':
+  unittest.main(exit=False)
diff --git a/infra/build/functions/deploy.sh b/infra/build/functions/deploy.sh
index ea094e3..3edf6ee 100755
--- a/infra/build/functions/deploy.sh
+++ b/infra/build/functions/deploy.sh
@@ -80,9 +80,10 @@
 	--runtime python38 \
 	--project $project \
 	--timeout 540 \
-  --region us-central1 \
-  --set-env-vars GCP_PROJECT=$project,FUNCTION_REGION=us-central1 \
-  --max-instances 1
+	--region us-central1 \
+	--set-env-vars GCP_PROJECT=$project,FUNCTION_REGION=us-central1 \
+	--max-instances 1 \
+	--memory 2048MB
 }
 
 if [ $# == 1 ]; then
@@ -135,11 +136,6 @@
 					  $BASE_IMAGE_JOB_TOPIC \
 					  $PROJECT_ID
 
-deploy_cloud_function base-msan-build \
-					  build_msan \
-					  $BASE_IMAGE_JOB_TOPIC \
-					  $PROJECT_ID
-
 deploy_cloud_function request-build \
 					  build_project \
 					  $BUILD_JOB_TOPIC \
diff --git a/infra/build/functions/expected_build_steps.json b/infra/build/functions/expected_build_steps.json
deleted file mode 100644
index da9c636..0000000
--- a/infra/build/functions/expected_build_steps.json
+++ /dev/null
@@ -1,330 +0,0 @@
-[
-  {
-    "args": [
-      "clone",
-      "https://github.com/google/oss-fuzz.git"
-    ],
-    "name": "gcr.io/cloud-builders/git"
-  },
-  {
-    "name": "gcr.io/cloud-builders/docker",
-    "args": [
-      "build",
-      "-t",
-      "gcr.io/oss-fuzz/test-project",
-      "."
-    ],
-    "dir": "oss-fuzz/projects/test-project"
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json"
-    ],
-    "env": [
-      "OSSFUZZ_REVISION=$REVISION_ID",
-      "FUZZING_LANGUAGE=c++"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/msan-libs-builder",
-    "args": [
-      "bash",
-      "-c",
-      "cp -r /msan /workspace"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "env": [
-      "FUZZING_ENGINE=libfuzzer",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/address && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=libfuzzer",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=libfuzzer",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "targets_list > /workspace/targets.list.address"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "cd /workspace/out/address && zip -r test-project-address-202001010000.zip *"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/srcmap.json",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/out/address/test-project-address-202001010000.zip",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/targets.list.address",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/curl",
-    "args": [
-      "-H",
-      "Content-Type: text/plain",
-      "-X",
-      "PUT",
-      "-d",
-      "test-project-address-202001010000.zip",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /workspace/out/address"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "env": [
-      "FUZZING_ENGINE=afl",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/address && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=afl",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer address --engine afl --architecture x86_64 test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=afl",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "targets_list > /workspace/targets.list.address"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "cd /workspace/out/address && zip -r test-project-address-202001010000.zip *"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/srcmap.json",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/out/address/test-project-address-202001010000.zip",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/targets.list.address",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/curl",
-    "args": [
-      "-H",
-      "Content-Type: text/plain",
-      "-X",
-      "PUT",
-      "-d",
-      "test-project-address-202001010000.zip",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /workspace/out/address"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "env": [
-      "FUZZING_ENGINE=honggfuzz",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/address && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=honggfuzz",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer address --engine honggfuzz --architecture x86_64 test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=honggfuzz",
-      "SANITIZER=address",
-      "OUT=/workspace/out/address",
-      "MSAN_LIBS_PATH=/workspace/msan",
-      "ARCHITECTURE=x86_64",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "targets_list > /workspace/targets.list.address"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "cd /workspace/out/address && zip -r test-project-address-202001010000.zip *"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/srcmap.json",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/out/address/test-project-address-202001010000.zip",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/uploader",
-    "args": [
-      "/workspace/targets.list.address",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/curl",
-    "args": [
-      "-H",
-      "Content-Type: text/plain",
-      "-X",
-      "PUT",
-      "-d",
-      "test-project-address-202001010000.zip",
-      "test_url"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /workspace/out/address"
-    ]
-  }
-]
diff --git a/infra/build/functions/expected_coverage_build_steps.json b/infra/build/functions/expected_coverage_build_steps.json
deleted file mode 100644
index 19b1d5b..0000000
--- a/infra/build/functions/expected_coverage_build_steps.json
+++ /dev/null
@@ -1,144 +0,0 @@
-[
-  {
-    "args": [
-      "clone",
-      "https://github.com/google/oss-fuzz.git"
-    ],
-    "name": "gcr.io/cloud-builders/git"
-  },
-  {
-    "name": "gcr.io/cloud-builders/docker",
-    "args": [
-      "build",
-      "-t",
-      "gcr.io/oss-fuzz/test-project",
-      "."
-    ],
-    "dir": "oss-fuzz/projects/test-project"
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "args": [
-      "bash",
-      "-c",
-      "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json"
-    ],
-    "env": [
-      "OSSFUZZ_REVISION=$REVISION_ID",
-      "FUZZING_LANGUAGE=c++"
-    ]
-  },
-  {
-    "name": "gcr.io/oss-fuzz/test-project",
-    "env": [
-      "FUZZING_ENGINE=libfuzzer",
-      "SANITIZER=coverage",
-      "OUT=/workspace/out/coverage",
-      "FUZZING_LANGUAGE=c++"
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/coverage && compile || (echo \"********************************************************************************\nCoverage build failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer coverage test-project\n********************************************************************************\" && false)"
-    ]
-  },
-  {
-    "url": "test_download"
-  },
-  {
-    "name": "gcr.io/oss-fuzz-base/base-runner",
-    "env": [
-      "FUZZING_ENGINE=libfuzzer",
-      "SANITIZER=coverage",
-      "OUT=/workspace/out/coverage",
-      "FUZZING_LANGUAGE=c++",
-      "HTTP_PORT=",
-      "COVERAGE_EXTRA_ARGS="
-    ],
-    "args": [
-      "bash",
-      "-c",
-      "for f in /corpus/*.zip; do unzip -q $f -d ${f%%.*} || (echo \"Failed to unpack the corpus for $(basename ${f%%.*}). This usually means that corpus backup for a particular fuzz target does not exist. If a fuzz target was added in the last 24 hours, please wait one more day. Otherwise, something is wrong with the fuzz target or the infrastructure, and corpus pruning task does not finish successfully.\" && exit 1); done && coverage || (echo \"********************************************************************************\nCode coverage report generation failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer coverage test-project\npython infra/helper.py coverage test-project\n********************************************************************************\" && false)"
-    ],
-    "volumes": [
-      {
-        "name": "corpus",
-        "path": "/corpus"
-      }
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "entrypoint": "sh",
-    "args": [
-      "-c",
-      "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/reports/20200101 || exit 0"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "args": [
-      "-m",
-      "cp",
-      "-r",
-      "/workspace/out/coverage/report",
-      "gs://oss-fuzz-coverage/test-project/reports/20200101"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "entrypoint": "sh",
-    "args": [
-      "-c",
-      "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101 || exit 0"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "args": [
-      "-m",
-      "cp",
-      "-r",
-      "/workspace/out/coverage/fuzzer_stats",
-      "gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "entrypoint": "sh",
-    "args": [
-      "-c",
-      "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/logs/20200101 || exit 0"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "args": [
-      "-m",
-      "cp",
-      "-r",
-      "/workspace/out/coverage/logs",
-      "gs://oss-fuzz-coverage/test-project/logs/20200101"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/gsutil",
-    "args": [
-      "cp",
-      "/workspace/srcmap.json",
-      "gs://oss-fuzz-coverage/test-project/srcmap/20200101.json"
-    ]
-  },
-  {
-    "name": "gcr.io/cloud-builders/curl",
-    "args": [
-      "-H",
-      "Content-Type: application/json",
-      "-X",
-      "PUT",
-      "-d",
-      "{\"fuzzer_stats_dir\": \"gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101\", \"html_report_url\": \"https://storage.googleapis.com/oss-fuzz-coverage/test-project/reports/20200101/linux/index.html\", \"report_date\": \"20200101\", \"report_summary_path\": \"gs://oss-fuzz-coverage/test-project/reports/20200101/linux/summary.json\"}",
-      "test_url"
-    ]
-  }
-]
\ No newline at end of file
diff --git a/infra/build/functions/main.py b/infra/build/functions/main.py
index 1bfd358..c34dc13 100644
--- a/infra/build/functions/main.py
+++ b/infra/build/functions/main.py
@@ -45,8 +45,3 @@
 def builds_status(event, context):
   """Entry point for builds status cloud function."""
   update_build_status.update_status(event, context)
-
-
-def build_msan(event, context):
-  """Entry point for base msan builder."""
-  base_images.base_msan_builder(event, context)
diff --git a/infra/build/functions/project_sync.py b/infra/build/functions/project_sync.py
index debdbbd..7b30cae 100644
--- a/infra/build/functions/project_sync.py
+++ b/infra/build/functions/project_sync.py
@@ -94,8 +94,8 @@
 def delete_project(cloud_scheduler_client, project):
   """Delete the given project."""
   logging.info('Deleting project %s', project.name)
-  for tag in (build_project.FUZZING_BUILD_TAG,
-              build_and_run_coverage.COVERAGE_BUILD_TAG):
+  for tag in (build_project.FUZZING_BUILD_TYPE,
+              build_and_run_coverage.COVERAGE_BUILD_TYPE):
     try:
       delete_scheduler(cloud_scheduler_client, project.name, tag)
     except exceptions.NotFound:
@@ -124,9 +124,9 @@
     try:
       create_scheduler(cloud_scheduler_client, project_name,
                        projects[project_name].schedule,
-                       build_project.FUZZING_BUILD_TAG, FUZZING_BUILD_TOPIC)
+                       build_project.FUZZING_BUILD_TYPE, FUZZING_BUILD_TOPIC)
       create_scheduler(cloud_scheduler_client, project_name, COVERAGE_SCHEDULE,
-                       build_and_run_coverage.COVERAGE_BUILD_TAG,
+                       build_and_run_coverage.COVERAGE_BUILD_TYPE,
                        COVERAGE_BUILD_TOPIC)
       project_metadata = projects[project_name]
       Project(name=project_name,
@@ -149,7 +149,7 @@
         logging.info('Schedule changed.')
         update_scheduler(cloud_scheduler_client, project,
                          projects[project.name].schedule,
-                         build_project.FUZZING_BUILD_TAG)
+                         build_project.FUZZING_BUILD_TYPE)
         project.schedule = project_metadata.schedule
         project_changed = True
       except exceptions.GoogleAPICallError as error:
@@ -232,7 +232,7 @@
 
 def sync(event, context):
   """Sync projects with cloud datastore."""
-  del event, context  #unused
+  del event, context  # Unused.
 
   with ndb.Client().context():
     git_creds = get_github_creds()
diff --git a/infra/build/functions/project_sync_test.py b/infra/build/functions/project_sync_test.py
index f907338..ad1330e 100644
--- a/infra/build/functions/project_sync_test.py
+++ b/infra/build/functions/project_sync_test.py
@@ -71,7 +71,7 @@
   # pylint: disable=no-self-use
   def location_path(self, project_id, location_id):
     """Return project path."""
-    return 'projects/{}/location/{}'.format(project_id, location_id)
+    return f'projects/{project_id}/location/{location_id}'
 
   def create_job(self, parent, job):
     """Simulate create job."""
@@ -81,8 +81,7 @@
   # pylint: disable=no-self-use
   def job_path(self, project_id, location_id, name):
     """Return job path."""
-    return 'projects/{}/location/{}/jobs/{}'.format(project_id, location_id,
-                                                    name)
+    return f'projects/{project_id}/location/{location_id}/jobs/{name}'
 
   def delete_job(self, name):
     """Simulate delete jobs."""
diff --git a/infra/build/functions/request_build.py b/infra/build/functions/request_build.py
index 6f0ab62..543bafb 100644
--- a/infra/build/functions/request_build.py
+++ b/infra/build/functions/request_build.py
@@ -15,13 +15,10 @@
 ################################################################################
 """Cloud function to request builds."""
 import base64
-import logging
 
 import google.auth
-from googleapiclient.discovery import build
 from google.cloud import ndb
 
-import build_lib
 import build_project
 from datastore_entities import BuildsHistory
 from datastore_entities import Project
@@ -55,46 +52,33 @@
   project = query.get()
   if not project:
     raise RuntimeError(
-        'Project {0} not available in cloud datastore'.format(project_name))
-  project_yaml_contents = project.project_yaml_contents
-  dockerfile_lines = project.dockerfile_contents.split('\n')
+        f'Project {project_name} not available in cloud datastore')
 
-  return (project_yaml_contents, dockerfile_lines)
+  return project.project_yaml_contents, project.dockerfile_contents
+
+
+def get_empty_config():
+  """Returns an empty build config."""
+  return build_project.Config(False, None, None, False)
 
 
 def get_build_steps(project_name, image_project, base_images_project):
   """Retrieve build steps."""
+  # TODO(metzman): Figure out if we need this.
   project_yaml_contents, dockerfile_lines = get_project_data(project_name)
+  build_config = get_empty_config()
   return build_project.get_build_steps(project_name, project_yaml_contents,
                                        dockerfile_lines, image_project,
-                                       base_images_project)
+                                       base_images_project, build_config)
 
 
-# pylint: disable=no-member
-def run_build(project_name, image_project, build_steps, credentials, tag):
-  """Execute build on cloud build."""
-  build_body = {
-      'steps': build_steps,
-      'timeout': str(build_lib.BUILD_TIMEOUT) + 's',
-      'options': {
-          'machineType': 'N1_HIGHCPU_32'
-      },
-      'logsBucket': build_project.GCB_LOGS_BUCKET,
-      'tags': [project_name + '-' + tag,],
-      'queueTtl': str(QUEUE_TTL_SECONDS) + 's',
-  }
-
-  cloudbuild = build('cloudbuild',
-                     'v1',
-                     credentials=credentials,
-                     cache_discovery=False)
-  build_info = cloudbuild.projects().builds().create(projectId=image_project,
-                                                     body=build_body).execute()
-  build_id = build_info['metadata']['build']['id']
-
-  update_build_history(project_name, build_id, tag)
-  logging.info('Build ID: %s', build_id)
-  logging.info('Logs: %s', build_project.get_logs_url(build_id, image_project))
+def run_build(oss_fuzz_project, build_steps, credentials, build_type,
+              cloud_project):
+  """Execute build on cloud build. Wrapper around build_project.py that also
+  updates the db."""
+  build_id = build_project.run_build(oss_fuzz_project, build_steps, credentials,
+                                     build_type, cloud_project)
+  update_build_history(oss_fuzz_project, build_id, build_type)
 
 
 # pylint: disable=no-member
@@ -107,9 +91,14 @@
     raise RuntimeError('Project name missing from payload')
 
   with ndb.Client().context():
-    credentials, image_project = google.auth.default()
-    build_steps = get_build_steps(project_name, image_project, BASE_PROJECT)
+    credentials, cloud_project = google.auth.default()
+    build_steps = get_build_steps(project_name, cloud_project, BASE_PROJECT)
     if not build_steps:
       return
-    run_build(project_name, image_project, build_steps, credentials,
-              build_project.FUZZING_BUILD_TAG)
+    run_build(
+        project_name,
+        build_steps,
+        credentials,
+        build_project.FUZZING_BUILD_TYPE,
+        cloud_project=cloud_project,
+    )
diff --git a/infra/build/functions/request_build_test.py b/infra/build/functions/request_build_test.py
index 22a4a10..1eb1d8e 100644
--- a/infra/build/functions/request_build_test.py
+++ b/infra/build/functions/request_build_test.py
@@ -14,23 +14,17 @@
 #
 ################################################################################
 """Unit tests for Cloud Function request builds which builds projects."""
-import json
-import datetime
 import os
 import sys
 import unittest
-from unittest import mock
 
 from google.cloud import ndb
 
 sys.path.append(os.path.dirname(__file__))
 # pylint: disable=wrong-import-position
 
-from datastore_entities import BuildsHistory
-from datastore_entities import Project
-from request_build import get_build_steps
-from request_build import get_project_data
-from request_build import update_build_history
+import datastore_entities
+import request_build
 import test_utils
 
 # pylint: disable=no-member
@@ -48,65 +42,42 @@
 
   def setUp(self):
     test_utils.reset_ds_emulator()
-
-  @mock.patch('build_lib.get_signed_url', return_value='test_url')
-  @mock.patch('datetime.datetime')
-  def test_get_build_steps(self, mocked_url, mocked_time):
-    """Test for get_build_steps."""
-    del mocked_url, mocked_time
-    datetime.datetime = test_utils.SpoofedDatetime
-    project_yaml_contents = ('language: c++\n'
-                             'sanitizers:\n'
-                             '  - address\n'
-                             'architectures:\n'
-                             '  - x86_64\n')
-    image_project = 'oss-fuzz'
-    base_images_project = 'oss-fuzz-base'
-    testcase_path = os.path.join(os.path.dirname(__file__),
-                                 'expected_build_steps.json')
-    with open(testcase_path) as testcase_file:
-      expected_build_steps = json.load(testcase_file)
-
-    with ndb.Client().context():
-      Project(name='test-project',
-              project_yaml_contents=project_yaml_contents,
-              dockerfile_contents='test line').put()
-      build_steps = get_build_steps('test-project', image_project,
-                                    base_images_project)
-    self.assertEqual(build_steps, expected_build_steps)
+    self.maxDiff = None  # pylint: disable=invalid-name
 
   def test_get_build_steps_no_project(self):
     """Test for when project isn't available in datastore."""
     with ndb.Client().context():
-      self.assertRaises(RuntimeError, get_build_steps, 'test-project',
-                        'oss-fuzz', 'oss-fuzz-base')
+      self.assertRaises(RuntimeError, request_build.get_build_steps,
+                        'test-project', 'oss-fuzz', 'oss-fuzz-base')
 
   def test_build_history(self):
     """Testing build history."""
     with ndb.Client().context():
-      BuildsHistory(id='test-project-fuzzing',
-                    build_tag='fuzzing',
-                    project='test-project',
-                    build_ids=[str(i) for i in range(1, 65)]).put()
-      update_build_history('test-project', '65', 'fuzzing')
+      datastore_entities.BuildsHistory(id='test-project-fuzzing',
+                                       build_tag='fuzzing',
+                                       project='test-project',
+                                       build_ids=[str(i) for i in range(1, 65)
+                                                 ]).put()
+      request_build.update_build_history('test-project', '65', 'fuzzing')
       expected_build_ids = [str(i) for i in range(2, 66)]
 
-      self.assertEqual(BuildsHistory.query().get().build_ids,
+      self.assertEqual(datastore_entities.BuildsHistory.query().get().build_ids,
                        expected_build_ids)
 
   def test_build_history_no_existing_project(self):
     """Testing build history when build history object is missing."""
     with ndb.Client().context():
-      update_build_history('test-project', '1', 'fuzzing')
+      request_build.update_build_history('test-project', '1', 'fuzzing')
       expected_build_ids = ['1']
 
-      self.assertEqual(BuildsHistory.query().get().build_ids,
+      self.assertEqual(datastore_entities.BuildsHistory.query().get().build_ids,
                        expected_build_ids)
 
   def test_get_project_data(self):
     """Testing get project data."""
     with ndb.Client().context():
-      self.assertRaises(RuntimeError, get_project_data, 'test-project')
+      self.assertRaises(RuntimeError, request_build.get_project_data,
+                        'test-project')
 
   @classmethod
   def tearDownClass(cls):
diff --git a/infra/build/functions/request_coverage_build.py b/infra/build/functions/request_coverage_build.py
index 1b4ac0e..a3890cb 100644
--- a/infra/build/functions/request_coverage_build.py
+++ b/infra/build/functions/request_coverage_build.py
@@ -27,27 +27,31 @@
 
 def get_build_steps(project_name, image_project, base_images_project):
   """Retrieve build steps."""
+  build_config = request_build.get_empty_config()
   project_yaml_contents, dockerfile_lines = request_build.get_project_data(
       project_name)
   return build_and_run_coverage.get_build_steps(project_name,
                                                 project_yaml_contents,
                                                 dockerfile_lines, image_project,
-                                                base_images_project)
+                                                base_images_project,
+                                                build_config)
 
 
 def request_coverage_build(event, context):
   """Entry point for coverage build cloud function."""
-  del context  #unused
+  del context  # Unused.
   if 'data' in event:
     project_name = base64.b64decode(event['data']).decode('utf-8')
   else:
     raise RuntimeError('Project name missing from payload')
 
   with ndb.Client().context():
-    credentials, image_project = google.auth.default()
-    build_steps = get_build_steps(project_name, image_project, BASE_PROJECT)
+    credentials, cloud_project = google.auth.default()
+    build_steps = get_build_steps(project_name, cloud_project, BASE_PROJECT)
     if not build_steps:
       return
-    request_build.run_build(project_name, image_project, build_steps,
+    request_build.run_build(project_name,
+                            build_steps,
                             credentials,
-                            build_and_run_coverage.COVERAGE_BUILD_TAG)
+                            build_and_run_coverage.COVERAGE_BUILD_TYPE,
+                            cloud_project=cloud_project)
diff --git a/infra/build/functions/request_coverage_build_test.py b/infra/build/functions/request_coverage_build_test.py
deleted file mode 100644
index 1327e36..0000000
--- a/infra/build/functions/request_coverage_build_test.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright 2020 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-"""Unit tests for Cloud Function that builds coverage reports."""
-import json
-import datetime
-import os
-import sys
-import unittest
-from unittest import mock
-
-from google.cloud import ndb
-
-sys.path.append(os.path.dirname(__file__))
-# pylint: disable=wrong-import-position
-
-from datastore_entities import Project
-from build_and_run_coverage import get_build_steps
-import test_utils
-
-# pylint: disable=no-member
-
-
-class TestRequestCoverageBuilds(unittest.TestCase):
-  """Unit tests for sync."""
-
-  @classmethod
-  def setUpClass(cls):
-    cls.ds_emulator = test_utils.start_datastore_emulator()
-    test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore',
-                                       test_utils.DATASTORE_READY_INDICATOR)
-    test_utils.set_gcp_environment()
-
-  def setUp(self):
-    test_utils.reset_ds_emulator()
-
-  @mock.patch('build_lib.get_signed_url', return_value='test_url')
-  @mock.patch('build_lib.download_corpora_steps',
-              return_value=[{
-                  'url': 'test_download'
-              }])
-  @mock.patch('datetime.datetime')
-  def test_get_coverage_build_steps(self, mocked_url, mocked_corpora_steps,
-                                    mocked_time):
-    """Test for get_build_steps."""
-    del mocked_url, mocked_corpora_steps, mocked_time
-    datetime.datetime = test_utils.SpoofedDatetime
-    project_yaml_contents = ('language: c++\n'
-                             'sanitizers:\n'
-                             '  - address\n'
-                             'architectures:\n'
-                             '  - x86_64\n')
-    dockerfile_contents = 'test line'
-    image_project = 'oss-fuzz'
-    base_images_project = 'oss-fuzz-base'
-    testcase_path = os.path.join(os.path.dirname(__file__),
-                                 'expected_coverage_build_steps.json')
-    with open(testcase_path) as testcase_file:
-      expected_coverage_build_steps = json.load(testcase_file)
-
-    with ndb.Client().context():
-      Project(name='test-project',
-              project_yaml_contents=project_yaml_contents,
-              dockerfile_contents=dockerfile_contents).put()
-
-    dockerfile_lines = dockerfile_contents.split('\n')
-    build_steps = get_build_steps('test-project', project_yaml_contents,
-                                  dockerfile_lines, image_project,
-                                  base_images_project)
-    self.assertEqual(build_steps, expected_coverage_build_steps)
-
-  @classmethod
-  def tearDownClass(cls):
-    test_utils.cleanup_emulator(cls.ds_emulator)
-
-
-if __name__ == '__main__':
-  unittest.main(exit=False)
diff --git a/infra/build/functions/test_data/expected_build_steps.json b/infra/build/functions/test_data/expected_build_steps.json
new file mode 100644
index 0000000..f0e3983
--- /dev/null
+++ b/infra/build/functions/test_data/expected_build_steps.json
@@ -0,0 +1,628 @@
+[
+  {
+    "args": [
+      "clone",
+      "https://github.com/google/oss-fuzz.git",
+      "--depth",
+      "1"
+    ],
+    "name": "gcr.io/cloud-builders/git"
+  },
+  {
+    "name": "gcr.io/cloud-builders/docker",
+    "args": [
+      "build",
+      "-t",
+      "gcr.io/oss-fuzz/test-project",
+      "."
+    ],
+    "dir": "oss-fuzz/projects/test-project"
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json"
+    ],
+    "env": [
+      "OSSFUZZ_REVISION=$REVISION_ID",
+      "FUZZING_LANGUAGE=c++"
+    ],
+    "id": "srcmap"
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=afl",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/afl-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/afl-address-x86_64 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-afl-address-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=afl",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/afl-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer address --engine afl --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "build-check-afl-address-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=afl",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/afl-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "targets_list > /workspace/targets.list.address"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "cd /workspace/out/afl-address-x86_64 && zip -r test-project-address-202001010000.zip *"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/srcmap.json",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/out/afl-address-x86_64/test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/targets.list.address",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: text/plain",
+      "-X",
+      "PUT",
+      "-d",
+      "test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /workspace/out/afl-address-x86_64"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=honggfuzz",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/honggfuzz-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/honggfuzz-address-x86_64 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-honggfuzz-address-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=honggfuzz",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/honggfuzz-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer address --engine honggfuzz --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "build-check-honggfuzz-address-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=honggfuzz",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/honggfuzz-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "targets_list > /workspace/targets.list.address"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "cd /workspace/out/honggfuzz-address-x86_64 && zip -r test-project-address-202001010000.zip *"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/srcmap.json",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/out/honggfuzz-address-x86_64/test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/targets.list.address",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: text/plain",
+      "-X",
+      "PUT",
+      "-d",
+      "test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /workspace/out/honggfuzz-address-x86_64"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-x86_64 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-libfuzzer-address-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "build-check-libfuzzer-address-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-address-x86_64",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "targets_list > /workspace/targets.list.address"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "cd /workspace/out/libfuzzer-address-x86_64 && zip -r test-project-address-202001010000.zip *"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/srcmap.json",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/out/libfuzzer-address-x86_64/test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/targets.list.address",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: text/plain",
+      "-X",
+      "PUT",
+      "-d",
+      "test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /workspace/out/libfuzzer-address-x86_64"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=i386",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-address-i386",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-i386 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-libfuzzer-address-i386"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=i386",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-address-i386",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 test-project\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture i386 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "build-check-libfuzzer-address-i386"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=i386",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-address-i386",
+      "SANITIZER=address"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "targets_list > /workspace/targets.list.address"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "cd /workspace/out/libfuzzer-address-i386 && zip -r test-project-address-202001010000.zip *"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/srcmap.json",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/out/libfuzzer-address-i386/test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/targets.list.address",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: text/plain",
+      "-X",
+      "PUT",
+      "-d",
+      "test-project-address-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /workspace/out/libfuzzer-address-i386"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-memory-x86_64",
+      "SANITIZER=memory"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-memory-x86_64 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-libfuzzer-memory-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-memory-x86_64",
+      "SANITIZER=memory"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "build-check-libfuzzer-memory-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-memory-x86_64",
+      "SANITIZER=memory"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "targets_list > /workspace/targets.list.memory"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "cd /workspace/out/libfuzzer-memory-x86_64 && zip -r test-project-memory-202001010000.zip *"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/srcmap.json",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/out/libfuzzer-memory-x86_64/test-project-memory-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/targets.list.memory",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: text/plain",
+      "-X",
+      "PUT",
+      "-d",
+      "test-project-memory-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /workspace/out/libfuzzer-memory-x86_64"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-undefined-x86_64",
+      "SANITIZER=undefined"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-undefined-x86_64 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-libfuzzer-undefined-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-undefined-x86_64",
+      "SANITIZER=undefined"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "test_all.py || (echo \"********************************************************************************\nBuild checks failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\npython infra/helper.py check_build --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "build-check-libfuzzer-undefined-x86_64"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-undefined-x86_64",
+      "SANITIZER=undefined"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "targets_list > /workspace/targets.list.undefined"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "cd /workspace/out/libfuzzer-undefined-x86_64 && zip -r test-project-undefined-202001010000.zip *"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/srcmap.json",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/out/libfuzzer-undefined-x86_64/test-project-undefined-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/uploader",
+    "args": [
+      "/workspace/targets.list.undefined",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: text/plain",
+      "-X",
+      "PUT",
+      "-d",
+      "test-project-undefined-202001010000.zip",
+      "test_url"
+    ]
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /workspace/out/libfuzzer-undefined-x86_64"
+    ]
+  }
+]
diff --git a/infra/build/functions/test_data/expected_coverage_build_steps.json b/infra/build/functions/test_data/expected_coverage_build_steps.json
new file mode 100644
index 0000000..2af48f5
--- /dev/null
+++ b/infra/build/functions/test_data/expected_coverage_build_steps.json
@@ -0,0 +1,152 @@
+[
+  {
+    "args": [
+      "clone",
+      "https://github.com/google/oss-fuzz.git",
+      "--depth",
+      "1"
+    ],
+    "name": "gcr.io/cloud-builders/git"
+  },
+  {
+    "name": "gcr.io/cloud-builders/docker",
+    "args": [
+      "build",
+      "-t",
+      "gcr.io/oss-fuzz/test-project",
+      "."
+    ],
+    "dir": "oss-fuzz/projects/test-project"
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "args": [
+      "bash",
+      "-c",
+      "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json"
+    ],
+    "env": [
+      "OSSFUZZ_REVISION=$REVISION_ID",
+      "FUZZING_LANGUAGE=c++"
+    ],
+    "id": "srcmap"
+  },
+  {
+    "name": "gcr.io/oss-fuzz/test-project",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-coverage-x86_64",
+      "SANITIZER=coverage"
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-coverage-x86_64 && compile || (echo \"********************************************************************************\nFailed to build.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer coverage --engine libfuzzer --architecture x86_64 test-project\n********************************************************************************\" && false)"
+    ],
+    "id": "compile-libfuzzer-coverage-x86_64"
+  },
+  {
+    "url": "test_download"
+  },
+  {
+    "name": "gcr.io/oss-fuzz-base/base-runner",
+    "env": [
+      "ARCHITECTURE=x86_64",
+      "FUZZING_ENGINE=libfuzzer",
+      "FUZZING_LANGUAGE=c++",
+      "HOME=/root",
+      "OUT=/workspace/out/libfuzzer-coverage-x86_64",
+      "SANITIZER=coverage",
+      "HTTP_PORT=",
+      "COVERAGE_EXTRA_ARGS="
+    ],
+    "args": [
+      "bash",
+      "-c",
+      "for f in /corpus/*.zip; do unzip -q $f -d ${f%%.*} || (echo \"Failed to unpack the corpus for $(basename ${f%%.*}). This usually means that corpus backup for a particular fuzz target does not exist. If a fuzz target was added in the last 24 hours, please wait one more day. Otherwise, something is wrong with the fuzz target or the infrastructure, and corpus pruning task does not finish successfully.\" && exit 1); done && coverage || (echo \"********************************************************************************\nCode coverage report generation failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer coverage test-project\npython infra/helper.py coverage test-project\n********************************************************************************\" && false)"
+    ],
+    "volumes": [
+      {
+        "name": "corpus",
+        "path": "/corpus"
+      }
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "entrypoint": "sh",
+    "args": [
+      "-c",
+      "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/reports/20200101 || exit 0"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "args": [
+      "-m",
+      "cp",
+      "-r",
+      "/workspace/out/libfuzzer-coverage-x86_64/report",
+      "gs://oss-fuzz-coverage/test-project/reports/20200101"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "entrypoint": "sh",
+    "args": [
+      "-c",
+      "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101 || exit 0"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "args": [
+      "-m",
+      "cp",
+      "-r",
+      "/workspace/out/libfuzzer-coverage-x86_64/fuzzer_stats",
+      "gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "entrypoint": "sh",
+    "args": [
+      "-c",
+      "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/logs/20200101 || exit 0"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "args": [
+      "-m",
+      "cp",
+      "-r",
+      "/workspace/out/libfuzzer-coverage-x86_64/logs",
+      "gs://oss-fuzz-coverage/test-project/logs/20200101"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/gsutil",
+    "args": [
+      "cp",
+      "/workspace/srcmap.json",
+      "gs://oss-fuzz-coverage/test-project/srcmap/20200101.json"
+    ]
+  },
+  {
+    "name": "gcr.io/cloud-builders/curl",
+    "args": [
+      "-H",
+      "Content-Type: application/json",
+      "-X",
+      "PUT",
+      "-d",
+      "{\"fuzzer_stats_dir\": \"gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101\", \"html_report_url\": \"https://storage.googleapis.com/oss-fuzz-coverage/test-project/reports/20200101/linux/index.html\", \"report_date\": \"20200101\", \"report_summary_path\": \"gs://oss-fuzz-coverage/test-project/reports/20200101/linux/summary.json\"}",
+      "test_url"
+    ]
+  }
+]
diff --git a/infra/build/functions/test_utils.py b/infra/build/functions/test_utils.py
index 9aac8ea..a093bcf 100644
--- a/infra/build/functions/test_utils.py
+++ b/infra/build/functions/test_utils.py
@@ -24,16 +24,31 @@
 DATASTORE_READY_INDICATOR = b'is now running'
 DATASTORE_EMULATOR_PORT = 8432
 EMULATOR_TIMEOUT = 20
-TEST_PROJECT_ID = 'test-project'
+
+FUNCTIONS_DIR = os.path.dirname(__file__)
+OSS_FUZZ_DIR = os.path.dirname(os.path.dirname(os.path.dirname(FUNCTIONS_DIR)))
+PROJECTS_DIR = os.path.join(OSS_FUZZ_DIR, 'projects')
+
+FAKE_DATETIME = datetime.datetime(2020, 1, 1, 0, 0, 0)
+IMAGE_PROJECT = 'oss-fuzz'
+BASE_IMAGES_PROJECT = 'oss-fuzz-base'
+PROJECT = 'test-project'
+PROJECT_DIR = os.path.join(PROJECTS_DIR, PROJECT)
 
 
-# pylint: disable=arguments-differ
-class SpoofedDatetime(datetime.datetime):
-  """Mocking Datetime class for now() function."""
+def create_project_data(project,
+                        project_yaml_contents,
+                        dockerfile_contents='test line'):
+  """Creates a project.yaml with |project_yaml_contents| and a Dockerfile with
+  |dockerfile_contents| for |project|."""
+  project_dir = os.path.join(PROJECTS_DIR, project)
+  project_yaml_path = os.path.join(project_dir, 'project.yaml')
+  with open(project_yaml_path, 'w') as project_yaml_handle:
+    project_yaml_handle.write(project_yaml_contents)
 
-  @classmethod
-  def now(cls):
-    return datetime.datetime(2020, 1, 1, 0, 0, 0)
+  dockerfile_path = os.path.join(project_dir, 'Dockerfile')
+  with open(dockerfile_path, 'w') as dockerfile_handle:
+    dockerfile_handle.write(dockerfile_contents)
 
 
 def start_datastore_emulator():
@@ -46,7 +61,7 @@
       'start',
       '--consistency=1.0',
       '--host-port=localhost:' + str(DATASTORE_EMULATOR_PORT),
-      '--project=' + TEST_PROJECT_ID,
+      '--project=' + PROJECT,
       '--no-store-on-disk',
   ],
                           stdout=subprocess.PIPE,
@@ -76,15 +91,13 @@
   thread.daemon = True
   thread.start()
   if not ready_event.wait(timeout):
-    raise RuntimeError(
-        '{} emulator did not get ready in time.'.format(emulator))
+    raise RuntimeError(f'{emulator} emulator did not get ready in time.')
   return thread
 
 
 def reset_ds_emulator():
   """Reset ds emulator/clean all entities."""
-  req = requests.post(
-      'http://localhost:{}/reset'.format(DATASTORE_EMULATOR_PORT))
+  req = requests.post(f'http://localhost:{DATASTORE_EMULATOR_PORT}/reset')
   req.raise_for_status()
 
 
@@ -98,7 +111,12 @@
   """Set environment variables for simulating in google cloud platform."""
   os.environ['DATASTORE_EMULATOR_HOST'] = 'localhost:' + str(
       DATASTORE_EMULATOR_PORT)
-  os.environ['GOOGLE_CLOUD_PROJECT'] = TEST_PROJECT_ID
-  os.environ['DATASTORE_DATASET'] = TEST_PROJECT_ID
-  os.environ['GCP_PROJECT'] = TEST_PROJECT_ID
+  os.environ['GOOGLE_CLOUD_PROJECT'] = PROJECT
+  os.environ['DATASTORE_DATASET'] = PROJECT
+  os.environ['GCP_PROJECT'] = PROJECT
   os.environ['FUNCTION_REGION'] = 'us-central1'
+
+
+def get_test_data_file_path(filename):
+  """Returns the path to a test data file with name |filename|."""
+  return os.path.join(os.path.dirname(__file__), 'test_data', filename)
diff --git a/infra/build/functions/update_build_status.py b/infra/build/functions/update_build_status.py
index af65a41..9272166 100644
--- a/infra/build/functions/update_build_status.py
+++ b/infra/build/functions/update_build_status.py
@@ -145,8 +145,8 @@
       }
 
     if not upload_log(build_id):
-      log_name = 'log-{0}'.format(build_id)
-      raise MissingBuildLogError('Missing build log file {0}'.format(log_name))
+      log_name = f'log-{build_id}'
+      raise MissingBuildLogError(f'Missing build log file {log_name}')
 
     history.append({
         'build_id': build_id,
@@ -203,19 +203,15 @@
   if not last_build_successful:
     badge = 'failing'
 
-  print("[badge] {}: {}".format(project, badge))
+  print(f'[badge] {project}: {badge}')
 
   for extension in BADGE_IMAGE_TYPES:
-    badge_name = '{badge}.{extension}'.format(badge=badge, extension=extension)
+    badge_name = f'{badge}.{extension}'
 
     # Copy blob from badge_images/badge_name to badges/project/
-    blob_name = '{badge_dir}/{badge_name}'.format(badge_dir=BADGE_DIR,
-                                                  badge_name=badge_name)
+    blob_name = f'{BADGE_DIR}/{badge_name}'
 
-    destination_blob_name = '{badge_dir}/{project_name}.{extension}'.format(
-        badge_dir=DESTINATION_BADGE_DIR,
-        project_name=project,
-        extension=extension)
+    destination_blob_name = f'{DESTINATION_BADGE_DIR}/{project}.{extension}'
 
     status_bucket = get_storage_client().get_bucket(STATUS_BUCKET)
     badge_blob = status_bucket.blob(blob_name)
@@ -228,12 +224,12 @@
   """Upload log file to GCS."""
   status_bucket = get_storage_client().get_bucket(STATUS_BUCKET)
   gcb_bucket = get_storage_client().get_bucket(build_project.GCB_LOGS_BUCKET)
-  log_name = 'log-{0}.txt'.format(build_id)
+  log_name = f'log-{build_id}.txt'
   log = gcb_bucket.blob(log_name)
   dest_log = status_bucket.blob(log_name)
 
   if not log.exists():
-    print('Failed to find build log {0}'.format(log_name), file=sys.stderr)
+    print('Failed to find build log', log_name, file=sys.stderr)
     return False
 
   if dest_log.exists():
@@ -258,10 +254,10 @@
     return
 
   if status_type == 'fuzzing':
-    tag = build_project.FUZZING_BUILD_TAG
+    tag = build_project.FUZZING_BUILD_TYPE
     status_filename = FUZZING_STATUS_FILENAME
   elif status_type == 'coverage':
-    tag = build_and_run_coverage.COVERAGE_BUILD_TAG
+    tag = build_and_run_coverage.COVERAGE_BUILD_TYPE
     status_filename = COVERAGE_STATUS_FILENAME
   else:
     raise RuntimeError('Invalid build status type ' + status_type)
diff --git a/infra/build/functions/update_build_status_test.py b/infra/build/functions/update_build_status_test.py
index 6784fac..24a32f6 100644
--- a/infra/build/functions/update_build_status_test.py
+++ b/infra/build/functions/update_build_status_test.py
@@ -56,14 +56,14 @@
 class TestGetBuildHistory(unittest.TestCase):
   """Unit tests for get_build_history."""
 
-  def test_get_build_history(self, mocked_upload_log, mocked_cloud_build,
-                             mocked_google_auth):
+  def test_get_build_history(self, mock_upload_log, mock_cloud_build,
+                             mock_google_auth):
     """Test for get_build_steps."""
-    del mocked_cloud_build, mocked_google_auth
-    mocked_upload_log.return_value = True
+    del mock_cloud_build, mock_google_auth
+    mock_upload_log.return_value = True
     builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'SUCCESS'}]
-    mocked_get_build = MockGetBuild(builds)
-    update_build_status.get_build = mocked_get_build.get_build
+    mock_get_build = MockGetBuild(builds)
+    update_build_status.get_build = mock_get_build.get_build
 
     expected_projects = {
         'history': [{
@@ -79,27 +79,26 @@
     self.assertDictEqual(update_build_status.get_build_history(['1']),
                          expected_projects)
 
-  def test_get_build_history_missing_log(self, mocked_upload_log,
-                                         mocked_cloud_build,
-                                         mocked_google_auth):
+  def test_get_build_history_missing_log(self, mock_upload_log,
+                                         mock_cloud_build, mock_google_auth):
     """Test for missing build log file."""
-    del mocked_cloud_build, mocked_google_auth
+    del mock_cloud_build, mock_google_auth
     builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'SUCCESS'}]
-    mocked_get_build = MockGetBuild(builds)
-    update_build_status.get_build = mocked_get_build.get_build
-    mocked_upload_log.return_value = False
+    mock_get_build = MockGetBuild(builds)
+    update_build_status.get_build = mock_get_build.get_build
+    mock_upload_log.return_value = False
     self.assertRaises(update_build_status.MissingBuildLogError,
                       update_build_status.get_build_history, ['1'])
 
-  def test_get_build_history_no_last_success(self, mocked_upload_log,
-                                             mocked_cloud_build,
-                                             mocked_google_auth):
+  def test_get_build_history_no_last_success(self, mock_upload_log,
+                                             mock_cloud_build,
+                                             mock_google_auth):
     """Test when there is no last successful build."""
-    del mocked_cloud_build, mocked_google_auth
+    del mock_cloud_build, mock_google_auth
     builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'FAILURE'}]
-    mocked_get_build = MockGetBuild(builds)
-    update_build_status.get_build = mocked_get_build.get_build
-    mocked_upload_log.return_value = True
+    mock_get_build = MockGetBuild(builds)
+    update_build_status.get_build = mock_get_build.get_build
+    mock_upload_log.return_value = True
 
     expected_projects = {
         'history': [{
@@ -229,12 +228,12 @@
   @mock.patch('google.auth.default', return_value=['temp', 'temp'])
   @mock.patch('update_build_status.build', return_value='cloudbuild')
   @mock.patch('update_build_status.upload_log')
-  def test_update_build_status(self, mocked_upload_log, mocked_cloud_build,
-                               mocked_google_auth):
+  def test_update_build_status(self, mock_upload_log, mock_cloud_build,
+                               mock_google_auth):
     """Testing update build status as a whole."""
-    del self, mocked_cloud_build, mocked_google_auth
+    del self, mock_cloud_build, mock_google_auth
     update_build_status.upload_status = MagicMock()
-    mocked_upload_log.return_value = True
+    mock_upload_log.return_value = True
     status_filename = 'status.json'
     with ndb.Client().context():
       BuildsHistory(id='test-project-1-fuzzing',
@@ -264,8 +263,8 @@
           'build_id': '3',
           'status': 'WORKING'
       }]
-      mocked_get_build = MockGetBuild(builds)
-      update_build_status.get_build = mocked_get_build.get_build
+      mock_get_build = MockGetBuild(builds)
+      update_build_status.get_build = mock_get_build.get_build
 
       expected_data = {
           'projects': [{
diff --git a/infra/build_and_push_test_images.py b/infra/build_and_push_test_images.py
new file mode 100755
index 0000000..44c65ae
--- /dev/null
+++ b/infra/build_and_push_test_images.py
@@ -0,0 +1,92 @@
+#! /usr/bin/env python3
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Script for building and pushing base-images to gcr.io/oss-fuzz-base/ with
+"-test" suffix. This is useful for reusing the build infra to test image
+changes."""
+import logging
+import multiprocessing
+import os
+import subprocess
+import sys
+
+TAG_PREFIX = 'gcr.io/oss-fuzz-base/'
+INFRA_DIR = os.path.dirname(__file__)
+IMAGES_DIR = os.path.join(INFRA_DIR, 'base-images')
+
+
+def push_image(tag):
+  """Pushes image with |tag| to docker registry."""
+  logging.info('Pushing: %s', tag)
+  command = ['docker', 'push', tag]
+  subprocess.run(command, check=True)
+  logging.info('Pushed: %s', tag)
+
+
+def build_and_push_image(image, test_image_suffix):
+  """Builds and pushes |image| to docker registry with "-testing" suffix."""
+  main_tag = TAG_PREFIX + image
+  testing_tag = main_tag + '-' + test_image_suffix
+  tags = [main_tag, testing_tag]
+  build_image(image, tags)
+  push_image(testing_tag)
+
+
+def build_image(image, tags):
+  """Builds |image| and tags it with |tags|."""
+  logging.info('Building: %s', image)
+  command = ['docker', 'build']
+  for tag in tags:
+    command.extend(['--tag', tag])
+    path = os.path.join(IMAGES_DIR, image)
+  command.append(path)
+  subprocess.run(command, check=True)
+  logging.info('Built: %s', image)
+
+
+def build_and_push_images(test_image_suffix):
+  """Builds and pushes base-images."""
+  images = [
+      ['base-image'],
+      ['base-clang'],
+      # base-runner is also dependent on base-clang.
+      ['base-builder', 'base-runner'],
+      [
+          'base-runner-debug', 'base-builder-go', 'base-builder-jvm',
+          'base-builder-python', 'base-builder-rust', 'base-builder-swift'
+      ],
+  ]
+  max_parallelization = max([len(image_list) for image_list in images])
+  proc_count = min(multiprocessing.cpu_count(), max_parallelization)
+  logging.info('Using %d parallel processes.', proc_count)
+  pool = multiprocessing.Pool(proc_count)
+  for image_list in images:
+    args_list = [(image, test_image_suffix) for image in image_list]
+    pool.starmap(build_and_push_image, args_list)
+
+
+def main():
+  """"Builds base-images tags them with "-testing" suffix (in addition to normal
+  tag) and pushes testing suffixed images to docker registry."""
+  test_image_suffix = sys.argv[1]
+  logging.basicConfig(level=logging.DEBUG)
+  logging.info('Doing simple gcloud command to ensure 2FA passes.')
+  subprocess.run(['gcloud', 'projects', 'list', '--limit=1'], check=True)
+  build_and_push_images(test_image_suffix)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/infra/build_fuzzers.Dockerfile b/infra/build_fuzzers.Dockerfile
index df06ff7..77a34ae 100644
--- a/infra/build_fuzzers.Dockerfile
+++ b/infra/build_fuzzers.Dockerfile
@@ -13,7 +13,8 @@
 # limitations under the License.
 #
 ################################################################################
-# Docker image to run the CIFuzz action build_fuzzers in.
+# Docker image to run fuzzers for CIFuzz (the run_fuzzers action on GitHub
+# actions).
 
 FROM gcr.io/oss-fuzz-base/cifuzz-base
 
@@ -22,5 +23,9 @@
 # just expand to '/opt/oss-fuzz'.
 ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/build_fuzzers_entrypoint.py"]
 
+WORKDIR ${OSS_FUZZ_ROOT}/infra
+
 # Update infra source code.
 ADD . ${OSS_FUZZ_ROOT}/infra
+
+RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt
\ No newline at end of file
diff --git a/infra/build_specified_commit.py b/infra/build_specified_commit.py
index b2130ea..d7b6670 100644
--- a/infra/build_specified_commit.py
+++ b/infra/build_specified_commit.py
@@ -11,7 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-"""Module to build a image from a specific commit, branch or pull request
+"""Module to build a image from a specific commit, branch or pull request.
 
 This module is allows each of the OSS Fuzz projects fuzzers to be built
 from a specific point in time. This feature can be used for implementations
@@ -147,7 +147,7 @@
 @retry.wrap(_IMAGE_BUILD_TRIES, 2)
 def _build_image_with_retries(project_name):
   """Build image with retries."""
-  return helper.build_image_impl(project_name)
+  return helper.build_image_impl(helper.Project(project_name))
 
 
 def get_required_post_checkout_steps(dockerfile_path):
@@ -223,15 +223,16 @@
           post_checkout_step,
       ])
 
-    result = helper.build_fuzzers_impl(project_name=build_data.project_name,
+    project = helper.Project(build_data.project_name)
+    result = helper.build_fuzzers_impl(project=project,
                                        clean=True,
                                        engine=build_data.engine,
                                        sanitizer=build_data.sanitizer,
                                        architecture=build_data.architecture,
                                        env_to_add=None,
                                        source_path=host_src_path,
-                                       mount_location='/src')
-    if result == 0 or i == num_retry:
+                                       mount_path='/src')
+    if result or i == num_retry:
       break
 
     # Retry with an OSS-Fuzz builder container that's closer to the project
@@ -285,7 +286,7 @@
     cleanup()
 
   cleanup()
-  return result == 0
+  return result
 
 
 def detect_main_repo(project_name, repo_name=None, commit=None):
@@ -297,10 +298,9 @@
     project_name: The name of the oss-fuzz project.
     repo_name: The name of the main repo in an OSS-Fuzz project.
     commit: A commit SHA that is associated with the main repo.
-    src_dir: The location of the projects source on the docker image.
 
   Returns:
-    The repo's origin, the repo's path.
+    A tuple containing (the repo's origin, the repo's path).
   """
 
   if not repo_name and not commit:
diff --git a/infra/build_specified_commit_test.py b/infra/build_specified_commit_test.py
index a865045..00f5094 100644
--- a/infra/build_specified_commit_test.py
+++ b/infra/build_specified_commit_test.py
@@ -16,7 +16,6 @@
   1. The inference of the main repo for a specific project.
   2. The building of a projects fuzzers from a specific commit.
 
-IMPORTANT: This test needs to be run with root privileges.
 """
 import os
 import tempfile
@@ -27,7 +26,7 @@
 import repo_manager
 import test_repos
 
-# Necessary because __file__ changes with os.chdir
+# necessary because __file__ changes with os.chdir
 TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__))
 
 
@@ -45,32 +44,39 @@
     should not.
     """
     with tempfile.TemporaryDirectory() as tmp_dir:
-      test_case = test_repos.TEST_REPOS[1]
-      self.assertTrue(helper.build_image_impl(test_case.project_name))
+      test_repo = test_repos.TEST_REPOS[1]
+      self.assertTrue(helper.build_image_impl(test_repo.project_name))
       host_src_dir = build_specified_commit.copy_src_from_docker(
-          test_case.project_name, tmp_dir)
+          test_repo.project_name, tmp_dir)
 
       test_repo_manager = repo_manager.clone_repo_and_get_manager(
-          test_case.git_url, host_src_dir, test_case.oss_repo_name)
+          test_repo.git_url, host_src_dir, test_repo.oss_repo_name)
       build_data = build_specified_commit.BuildData(
           sanitizer='address',
           architecture='x86_64',
           engine='libfuzzer',
-          project_name=test_case.project_name)
+          project_name=test_repo.project_name)
 
-      build_specified_commit.build_fuzzers_from_commit(test_case.old_commit,
+      build_specified_commit.build_fuzzers_from_commit(test_repo.old_commit,
                                                        test_repo_manager,
                                                        host_src_dir, build_data)
-      old_error_code = helper.reproduce_impl(test_case.project_name,
-                                             test_case.fuzz_target, False, [],
-                                             [], test_case.test_case_path)
-      build_specified_commit.build_fuzzers_from_commit(test_case.new_commit,
+      project = helper.Project(test_repo.project_name)
+      old_result = helper.reproduce_impl(project=project,
+                                         fuzzer_name=test_repo.fuzz_target,
+                                         valgrind=False,
+                                         env_to_add=[],
+                                         fuzzer_args=[],
+                                         testcase_path=test_repo.testcase_path)
+      build_specified_commit.build_fuzzers_from_commit(test_repo.project_name,
                                                        test_repo_manager,
                                                        host_src_dir, build_data)
-      new_error_code = helper.reproduce_impl(test_case.project_name,
-                                             test_case.fuzz_target, False, [],
-                                             [], test_case.test_case_path)
-      self.assertNotEqual(new_error_code, old_error_code)
+      new_result = helper.reproduce_impl(project=project,
+                                         fuzzer_name=test_repo.fuzz_target,
+                                         valgrind=False,
+                                         env_to_add=[],
+                                         fuzzer_args=[],
+                                         testcase_path=test_repo.testcase_path)
+      self.assertNotEqual(new_result, old_result)
 
   def test_detect_main_repo_from_commit(self):
     """Test the detect main repo function from build specific commit module."""
diff --git a/infra/ci/build.py b/infra/ci/build.py
index addeb78..7a02d60 100755
--- a/infra/ci/build.py
+++ b/infra/ci/build.py
@@ -25,20 +25,22 @@
 import subprocess
 import yaml
 
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import constants
+
 CANARY_PROJECT = 'skcms'
 
 DEFAULT_ARCHITECTURES = ['x86_64']
 DEFAULT_ENGINES = ['afl', 'honggfuzz', 'libfuzzer']
 DEFAULT_SANITIZERS = ['address', 'undefined']
 
-# Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
-
 
 def get_changed_files_output():
   """Returns the output of a git command that discovers changed files."""
   branch_commit_hash = subprocess.check_output(
-      ['git', 'merge-base', 'FETCH_HEAD', 'origin/HEAD']).strip().decode()
+      ['git', 'merge-base', 'HEAD', 'origin/HEAD']).strip().decode()
 
   return subprocess.check_output(
       ['git', 'diff', '--name-only', branch_commit_hash + '..']).decode()
@@ -112,7 +114,7 @@
     return False
 
   language = project_yaml.get('language')
-  if language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
+  if language not in constants.LANGUAGES_WITH_COVERAGE_SUPPORT:
     print(('Project is written in "{language}", '
            'coverage is not supported yet.').format(language=language))
     return False
@@ -213,11 +215,16 @@
   images = [
       'base-image',
       'base-builder',
+      'base-builder-go',
+      'base-builder-jvm',
+      'base-builder-python',
+      'base-builder-rust',
+      'base-builder-swift',
       'base-runner',
   ]
   for image in images:
     try:
-      execute_helper_command(['build_image', image, '--no-pull'])
+      execute_helper_command(['build_image', image, '--no-pull', '--cache'])
     except subprocess.CalledProcessError:
       return 1
 
@@ -239,6 +246,7 @@
 
 def main():
   """Build modified projects or canary project."""
+  os.environ['OSS_FUZZ_CI'] = '1'
   infra_changed = is_infra_changed()
   if infra_changed:
     print('Pulling and building base images first.')
diff --git a/infra/ci/requirements.txt b/infra/ci/requirements.txt
index f0a8be0..310ba53 100644
--- a/infra/ci/requirements.txt
+++ b/infra/ci/requirements.txt
@@ -6,3 +6,5 @@
 pytest-xdist==2.2.0
 PyYAML==5.4
 yapf==0.30.0
+# Needed for cifuzz tests.
+Jinja2==2.11.3
diff --git a/infra/cifuzz/actions/build_fuzzers/action.yml b/infra/cifuzz/actions/build_fuzzers/action.yml
index 835b7b4..5cc35a1 100644
--- a/infra/cifuzz/actions/build_fuzzers/action.yml
+++ b/infra/cifuzz/actions/build_fuzzers/action.yml
@@ -21,9 +21,6 @@
   project-src-path:
     description: "The path to the project's source code checkout."
     required: false
-  build-integration-path:
-    description: "The path to the the project's build integration."
-    required: false
   bad-build-check:
     description: "Whether or not OSS-Fuzz's check for bad builds should be done."
     required: false
@@ -38,6 +35,5 @@
     ALLOWED_BROKEN_TARGETS_PERCENTAGE: ${{ inputs.allowed-broken-targets-percentage}}
     SANITIZER: ${{ inputs.sanitizer }}
     PROJECT_SRC_PATH: ${{ inputs.project-src-path }}
-    BUILD_INTEGRATION_PATH: ${{ inputs.build-integration-path }}
     LOW_DISK_SPACE: 'True'
     BAD_BUILD_CHECK: ${{ inputs.bad-build-check }}
diff --git a/infra/cifuzz/actions/run_fuzzers/action.yml b/infra/cifuzz/actions/run_fuzzers/action.yml
index d1c03c8..b56dbce 100644
--- a/infra/cifuzz/actions/run_fuzzers/action.yml
+++ b/infra/cifuzz/actions/run_fuzzers/action.yml
@@ -19,9 +19,6 @@
   sanitizer:
     description: 'The sanitizer to run the fuzzers with.'
     default: 'address'
-  build-integration-path:
-    description: "The path to the the project's build integration."
-    required: false
   run-fuzzers-mode:
     description: |
       The mode to run the fuzzers with ("ci" or "batch").
@@ -30,6 +27,18 @@
       "batch" is in alpha and should not be used in production.
     required: false
     default: 'ci'
+  github-token:
+    description: |
+      Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET
+      You should use "secrets.GITHUB_TOKEN" in your workflow file, do not
+      hardcode the token.
+      TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361):
+      Document locking this down.
+    required: false
+  report-unreproducible-crashes:
+    description: 'If True, then unreproducible crashes will be reported by CIFuzz.'
+    required: false
+    default: false
 runs:
   using: 'docker'
   image: '../../../run_fuzzers.Dockerfile'
@@ -40,8 +49,6 @@
     DRY_RUN: ${{ inputs.dry-run}}
     SANITIZER: ${{ inputs.sanitizer }}
     RUN_FUZZERS_MODE: ${{ inputs.run-fuzzers-mode }}
-    # TODO(metzman): Even though this param is used for building, it's needed
-    # for running because we use it to distinguish OSS-Fuzz from non-OSS-Fuzz.
-    # We should do something explicit instead.
-    BUILD_INTEGRATION_PATH: ${{ inputs.build-integration-path }}
+    GITHUB_TOKEN: ${{ inputs.github-token }}
     LOW_DISK_SPACE: 'True'
+    REPORT_UNREPRODUCIBLE_CRASHES: ${{ inputs.report-unreproducible-crashes }}
diff --git a/infra/cifuzz/affected_fuzz_targets.py b/infra/cifuzz/affected_fuzz_targets.py
index f9f2242..be35c5c 100644
--- a/infra/cifuzz/affected_fuzz_targets.py
+++ b/infra/cifuzz/affected_fuzz_targets.py
@@ -17,19 +17,17 @@
 import os
 import sys
 
-import coverage
-
 # pylint: disable=wrong-import-position,import-error
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 import utils
 
 
-def remove_unaffected_fuzz_targets(project_name, out_dir, files_changed,
-                                   repo_path):
+def remove_unaffected_fuzz_targets(clusterfuzz_deployment, out_dir,
+                                   files_changed, repo_path):
   """Removes all non affected fuzz targets in the out directory.
 
   Args:
-    project_name: The name of the relevant OSS-Fuzz project.
+    clusterfuzz_deployment: The ClusterFuzz deployment object.
     out_dir: The location of the fuzz target binaries.
     files_changed: A list of files changed compared to HEAD.
     repo_path: The location of the OSS-Fuzz repo in the docker image.
@@ -38,7 +36,6 @@
   targets are unaffected. For example, this means that fuzz targets which don't
   have coverage data on will not be deleted.
   """
-  # TODO(metzman): Make this use clusterfuzz deployment.
   if not files_changed:
     # Don't remove any fuzz targets if there is no difference from HEAD.
     logging.info('No files changed compared to HEAD.')
@@ -52,14 +49,13 @@
     logging.error('No fuzz targets found in out dir.')
     return
 
-  coverage_getter = coverage.OssFuzzCoverageGetter(project_name, repo_path)
-  if not coverage_getter.fuzzer_stats_url:
+  coverage = clusterfuzz_deployment.get_coverage(repo_path)
+  if not coverage:
     # Don't remove any fuzz targets unless we have data.
     logging.error('Could not find latest coverage report.')
     return
 
-  affected_fuzz_targets = get_affected_fuzz_targets(coverage_getter,
-                                                    fuzz_target_paths,
+  affected_fuzz_targets = get_affected_fuzz_targets(coverage, fuzz_target_paths,
                                                     files_changed)
 
   if not affected_fuzz_targets:
@@ -79,11 +75,11 @@
                     fuzz_target_path)
 
 
-def is_fuzz_target_affected(coverage_getter, fuzz_target_path, files_changed):
+def is_fuzz_target_affected(coverage, fuzz_target_path, files_changed):
   """Returns True if a fuzz target (|fuzz_target_path|) is affected by
   |files_changed|."""
   fuzz_target = os.path.basename(fuzz_target_path)
-  covered_files = coverage_getter.get_files_covered_by_target(fuzz_target)
+  covered_files = coverage.get_files_covered_by_target(fuzz_target)
   if not covered_files:
     # Assume a fuzz target is affected if we can't get its coverage from
     # OSS-Fuzz.
@@ -104,13 +100,11 @@
   return False
 
 
-def get_affected_fuzz_targets(coverage_getter, fuzz_target_paths,
-                              files_changed):
+def get_affected_fuzz_targets(coverage, fuzz_target_paths, files_changed):
   """Returns a list of paths of affected targets."""
   affected_fuzz_targets = set()
   for fuzz_target_path in fuzz_target_paths:
-    if is_fuzz_target_affected(coverage_getter, fuzz_target_path,
-                               files_changed):
+    if is_fuzz_target_affected(coverage, fuzz_target_path, files_changed):
       affected_fuzz_targets.add(fuzz_target_path)
 
   return affected_fuzz_targets
diff --git a/infra/cifuzz/affected_fuzz_targets_test.py b/infra/cifuzz/affected_fuzz_targets_test.py
index 05f27c0..823654d 100644
--- a/infra/cifuzz/affected_fuzz_targets_test.py
+++ b/infra/cifuzz/affected_fuzz_targets_test.py
@@ -21,6 +21,9 @@
 import parameterized
 
 import affected_fuzz_targets
+import clusterfuzz_deployment
+import test_helpers
+import workspace_utils
 
 # pylint: disable=protected-access
 
@@ -30,15 +33,15 @@
 
 EXAMPLE_FILE_CHANGED = 'test.txt'
 
-TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                              'test_data')
+TEST_DATA_OUT_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                                  'test_data', 'build-out')
 
 
 class RemoveUnaffectedFuzzTargets(unittest.TestCase):
   """Tests remove_unaffected_fuzzers."""
 
-  TEST_FUZZER_1 = os.path.join(TEST_DATA_PATH, 'out', 'example_crash_fuzzer')
-  TEST_FUZZER_2 = os.path.join(TEST_DATA_PATH, 'out', 'example_nocrash_fuzzer')
+  TEST_FUZZER_1 = os.path.join(TEST_DATA_OUT_PATH, 'example_crash_fuzzer')
+  TEST_FUZZER_2 = os.path.join(TEST_DATA_OUT_PATH, 'example_nocrash_fuzzer')
 
   # yapf: disable
   @parameterized.parameterized.expand([
@@ -57,18 +60,27 @@
   # yapf: enable
   def test_remove_unaffected_fuzz_targets(self, side_effect, expected_dir_len):
     """Tests that remove_unaffected_fuzzers has the intended effect."""
+    config = test_helpers.create_run_config(
+        is_github=True,
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
+        workspace='/workspace')
+    workspace = workspace_utils.Workspace(config)
+    deployment = clusterfuzz_deployment.get_clusterfuzz_deployment(
+        config, workspace)
     # We can't use fakefs in this test because this test executes
     # utils.is_fuzz_target_local. This function relies on the executable bit
     # being set, which doesn't work properly in fakefs.
     with tempfile.TemporaryDirectory() as tmp_dir, mock.patch(
-        'coverage.OssFuzzCoverageGetter.get_files_covered_by_target'
-    ) as mocked_get_files:
-      with mock.patch('coverage._get_fuzzer_stats_dir_url', return_value=1):
-        mocked_get_files.side_effect = side_effect
+        'get_coverage.OSSFuzzCoverage.get_files_covered_by_target'
+    ) as mock_get_files:
+      with mock.patch('get_coverage._get_oss_fuzz_fuzzer_stats_dir_url',
+                      return_value=1):
+        mock_get_files.side_effect = side_effect
         shutil.copy(self.TEST_FUZZER_1, tmp_dir)
         shutil.copy(self.TEST_FUZZER_2, tmp_dir)
+
         affected_fuzz_targets.remove_unaffected_fuzz_targets(
-            EXAMPLE_PROJECT, tmp_dir, [EXAMPLE_FILE_CHANGED], '')
+            deployment, tmp_dir, [EXAMPLE_FILE_CHANGED], '')
         self.assertEqual(expected_dir_len, len(os.listdir(tmp_dir)))
 
 
diff --git a/infra/cifuzz/base_runner_utils.py b/infra/cifuzz/base_runner_utils.py
new file mode 100644
index 0000000..2463754
--- /dev/null
+++ b/infra/cifuzz/base_runner_utils.py
@@ -0,0 +1,33 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Utilities for scripts from gcr.io/oss-fuzz-base/base-runner."""
+
+import os
+
+import config_utils
+
+
+def get_env(config, workspace):
+  """Returns a dictionary containing the current environment with additional env
+  vars set to values needed to run a fuzzer."""
+  env = os.environ.copy()
+  env['SANITIZER'] = config.sanitizer
+  env['FUZZING_LANGUAGE'] = config.language
+  env['OUT'] = workspace.out
+  env['CIFUZZ'] = 'True'
+  env['FUZZING_ENGINE'] = config_utils.DEFAULT_ENGINE
+  env['ARCHITECTURE'] = config_utils.DEFAULT_ARCHITECTURE
+  # Do this so we don't fail in tests.
+  env['FUZZER_ARGS'] = '-rss_limit_mb=2560 -timeout=25'
+  return env
diff --git a/infra/cifuzz/build_fuzzers.py b/infra/cifuzz/build_fuzzers.py
index 78180b5..6722be5 100644
--- a/infra/cifuzz/build_fuzzers.py
+++ b/infra/cifuzz/build_fuzzers.py
@@ -19,18 +19,17 @@
 import sys
 
 import affected_fuzz_targets
+import base_runner_utils
+import clusterfuzz_deployment
 import continuous_integration
 import docker
+import workspace_utils
 
 # pylint: disable=wrong-import-position,import-error
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 import helper
 import utils
 
-# Default fuzz configuration.
-DEFAULT_ENGINE = 'libfuzzer'
-DEFAULT_ARCHITECTURE = 'x86_64'
-
 logging.basicConfig(
     format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
     level=logging.DEBUG)
@@ -55,89 +54,82 @@
   def __init__(self, config, ci_system):
     self.config = config
     self.ci_system = ci_system
-    self.out_dir = os.path.join(config.workspace, 'out')
-    os.makedirs(self.out_dir, exist_ok=True)
-    self.work_dir = os.path.join(config.workspace, 'work')
-    os.makedirs(self.work_dir, exist_ok=True)
+    self.workspace = workspace_utils.Workspace(config)
+    self.workspace.initialize_dir(self.workspace.out)
+    self.workspace.initialize_dir(self.workspace.work)
+    self.clusterfuzz_deployment = (
+        clusterfuzz_deployment.get_clusterfuzz_deployment(
+            self.config, self.workspace))
     self.image_repo_path = None
     self.host_repo_path = None
     self.repo_manager = None
 
   def build_image_and_checkout_src(self):
     """Builds the project builder image and checkout source code for the patch
-    we want to fuzz (if necessary). Returns True on success.
-    Must be implemented by child classes."""
+    we want to fuzz (if necessary). Returns True on success."""
     result = self.ci_system.prepare_for_fuzzer_build()
     if not result.success:
       return False
     self.image_repo_path = result.image_repo_path
     self.repo_manager = result.repo_manager
+    logging.info('repo_dir: %s.', self.repo_manager.repo_dir)
     self.host_repo_path = self.repo_manager.repo_dir
     return True
 
   def build_fuzzers(self):
     """Moves the source code we want to fuzz into the project builder and builds
     the fuzzers from that source code. Returns True on success."""
-    docker_args = get_common_docker_args(self.config.sanitizer,
-                                         self.config.language)
-    container = utils.get_container_name()
-
-    if container:
+    docker_args, docker_container = docker.get_base_docker_run_args(
+        self.workspace, self.config.sanitizer, self.config.language,
+        self.config.docker_in_docker)
+    if not docker_container:
       docker_args.extend(
-          _get_docker_build_fuzzers_args_container(self.out_dir, container))
-    else:
-      docker_args.extend(
-          _get_docker_build_fuzzers_args_not_container(self.out_dir,
-                                                       self.host_repo_path))
-
-    if self.config.sanitizer == 'memory':
-      docker_args.extend(_get_docker_build_fuzzers_args_msan(self.work_dir))
-      self.handle_msan_prebuild(container)
+          _get_docker_build_fuzzers_args_not_container(self.host_repo_path))
 
     docker_args.extend([
-        docker.get_project_image_name(self.config.project_name),
+        docker.get_project_image_name(self.config.oss_fuzz_project_name),
         '/bin/bash',
         '-c',
     ])
-    rm_path = os.path.join(self.image_repo_path, '*')
-    image_src_path = os.path.dirname(self.image_repo_path)
-    bash_command = 'rm -rf {0} && cp -r {1} {2} && compile'.format(
-        rm_path, self.host_repo_path, image_src_path)
-    docker_args.append(bash_command)
+    build_command = self.ci_system.get_build_command(self.host_repo_path,
+                                                     self.image_repo_path)
+    docker_args.append(build_command)
     logging.info('Building with %s sanitizer.', self.config.sanitizer)
-    if helper.docker_run(docker_args):
-      # docker_run returns nonzero on failure.
+
+    # TODO(metzman): Stop using helper.docker_run so we can get rid of
+    # docker.get_base_docker_run_args and merge its contents into
+    # docker.get_base_docker_run_command.
+    if not helper.docker_run(docker_args):
       logging.error('Building fuzzers failed.')
       return False
 
-    if self.config.sanitizer == 'memory':
-      self.handle_msan_postbuild(container)
     return True
 
-  def handle_msan_postbuild(self, container):
-    """Post-build step for MSAN builds. Patches the build to use MSAN
-    libraries."""
-    helper.docker_run([
-        '--volumes-from', container, '-e',
-        'WORK={work_dir}'.format(work_dir=self.work_dir),
-        docker.MSAN_LIBS_BUILDER_TAG, 'patch_build.py', '/out'
-    ])
+  def upload_build(self):
+    """Upload build."""
+    if self.config.upload_build:
+      self.clusterfuzz_deployment.upload_build(
+          self.repo_manager.get_current_commit())
 
-  def handle_msan_prebuild(self, container):
-    """Pre-build step for MSAN builds. Copies MSAN libs to |msan_libs_dir| and
-    returns docker arguments to use that directory for MSAN libs."""
-    logging.info('Copying MSAN libs.')
-    helper.docker_run([
-        '--volumes-from', container, docker.MSAN_LIBS_BUILDER_TAG, 'bash', '-c',
-        'cp -r /msan {work_dir}'.format(work_dir=self.work_dir)
-    ])
+    return True
+
+  def check_fuzzer_build(self):
+    """Checks the fuzzer build. Returns True on success or if config specifies
+    to skip check."""
+    if not self.config.bad_build_check:
+      return True
+
+    return check_fuzzer_build(self.config)
 
   def build(self):
     """Builds the image, checkouts the source (if needed), builds the fuzzers
     and then removes the unaffectted fuzzers. Returns True on success."""
     methods = [
-        self.build_image_and_checkout_src, self.build_fuzzers,
-        self.remove_unaffected_fuzz_targets
+        self.build_image_and_checkout_src,
+        self.build_fuzzers,
+        self.remove_unaffected_fuzz_targets,
+        self.check_fuzzer_build,
+        self.upload_build,
     ]
     for method in methods:
       if not method():
@@ -154,7 +146,7 @@
     changed_files = self.ci_system.get_changed_code_under_test(
         self.repo_manager)
     affected_fuzz_targets.remove_unaffected_fuzz_targets(
-        self.config.project_name, self.out_dir, changed_files,
+        self.clusterfuzz_deployment, self.workspace.out, changed_files,
         self.image_repo_path)
     return True
 
@@ -186,94 +178,39 @@
   return builder.build()
 
 
-def get_common_docker_args(sanitizer, language):
-  """Returns a list of common docker arguments."""
-  return [
-      '--cap-add',
-      'SYS_PTRACE',
-      '-e',
-      'FUZZING_ENGINE=' + DEFAULT_ENGINE,
-      '-e',
-      'SANITIZER=' + sanitizer,
-      '-e',
-      'ARCHITECTURE=' + DEFAULT_ARCHITECTURE,
-      '-e',
-      'CIFUZZ=True',
-      '-e',
-      'FUZZING_LANGUAGE=' + language,
-  ]
-
-
-def check_fuzzer_build(out_dir,
-                       sanitizer,
-                       language,
-                       allowed_broken_targets_percentage=None):
+def check_fuzzer_build(config):
   """Checks the integrity of the built fuzzers.
 
   Args:
-    out_dir: The directory containing the fuzzer binaries.
-    sanitizer: The sanitizer the fuzzers are built with.
+    config: The config object.
 
   Returns:
-    True if fuzzers are correct.
+    True if fuzzers pass OSS-Fuzz's build check.
   """
-  if not os.path.exists(out_dir):
-    logging.error('Invalid out directory: %s.', out_dir)
+  workspace = workspace_utils.Workspace(config)
+  if not os.path.exists(workspace.out):
+    logging.error('Invalid out directory: %s.', workspace.out)
     return False
-  if not os.listdir(out_dir):
-    logging.error('No fuzzers found in out directory: %s.', out_dir)
+  if not os.listdir(workspace.out):
+    logging.error('No fuzzers found in out directory: %s.', workspace.out)
     return False
 
-  command = get_common_docker_args(sanitizer, language)
+  env = base_runner_utils.get_env(config, workspace)
+  if config.allowed_broken_targets_percentage is not None:
+    env['ALLOWED_BROKEN_TARGETS_PERCENTAGE'] = (
+        config.allowed_broken_targets_percentage)
 
-  if allowed_broken_targets_percentage is not None:
-    command += [
-        '-e',
-        ('ALLOWED_BROKEN_TARGETS_PERCENTAGE=' +
-         allowed_broken_targets_percentage)
-    ]
-
-  container = utils.get_container_name()
-  if container:
-    command += ['-e', 'OUT=' + out_dir, '--volumes-from', container]
-  else:
-    command += ['-v', '%s:/out' % out_dir]
-  command.extend(['-t', docker.BASE_RUNNER_TAG, 'test_all.py'])
-  exit_code = helper.docker_run(command)
-  logging.info('check fuzzer build exit code: %d', exit_code)
-  if exit_code:
-    logging.error('Check fuzzer build failed.')
-    return False
-  return True
+  stdout, stderr, retcode = utils.execute('test_all.py', env=env)
+  print(f'Build check: stdout: {stdout}\nstderr: {stderr}')
+  if retcode == 0:
+    logging.info('Build check passed.')
+    return True
+  logging.error('Build check failed.')
+  return False
 
 
-def _get_docker_build_fuzzers_args_container(host_out_dir, container):
+def _get_docker_build_fuzzers_args_not_container(host_repo_path):
   """Returns arguments to the docker build arguments that are needed to use
-  |host_out_dir| when the host of the OSS-Fuzz builder container is another
-  container."""
-  return ['-e', 'OUT=' + host_out_dir, '--volumes-from', container]
-
-
-def _get_docker_build_fuzzers_args_not_container(host_out_dir, host_repo_path):
-  """Returns arguments to the docker build arguments that are needed to use
-  |host_out_dir| when the host of the OSS-Fuzz builder container is not
+  |host_repo_path| when the host of the OSS-Fuzz builder container is not
   another container."""
-  image_out_dir = '/out'
-  return [
-      '-e',
-      'OUT=' + image_out_dir,
-      '-v',
-      '%s:%s' % (host_out_dir, image_out_dir),
-      '-v',
-      '%s:%s' % (host_repo_path, host_repo_path),
-  ]
-
-
-def _get_docker_build_fuzzers_args_msan(work_dir):
-  """Returns arguments to the docker build command that are needed to use
-  MSAN."""
-  # TODO(metzman): MSAN is broken, fix.
-  return [
-      '-e', 'MSAN_LIBS_PATH={msan_libs_path}'.format(
-          msan_libs_path=os.path.join(work_dir, 'msan'))
-  ]
+  return ['-v', f'{host_repo_path}:{host_repo_path}']
diff --git a/infra/cifuzz/build_fuzzers_entrypoint.py b/infra/cifuzz/build_fuzzers_entrypoint.py
index 04f5620..e8e368f 100644
--- a/infra/cifuzz/build_fuzzers_entrypoint.py
+++ b/infra/cifuzz/build_fuzzers_entrypoint.py
@@ -13,7 +13,6 @@
 # limitations under the License.
 """Builds a specific OSS-Fuzz project's fuzzers for CI tools."""
 import logging
-import os
 import sys
 
 import build_fuzzers
@@ -22,19 +21,34 @@
 # pylint: disable=c-extension-no-member
 # pylint gets confused because of the relative import of cifuzz.
 
-# TODO: Turn default logging to INFO when CIFuzz is stable
 logging.basicConfig(
     format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
     level=logging.DEBUG)
 
 
-def main():
-  """Build OSS-Fuzz project's fuzzers for CI tools.
-  This script is used to kick off the Github Actions CI tool. It is the
-  entrypoint of the Dockerfile in this directory. This action can be added to
-  any OSS-Fuzz project's workflow that uses Github.
+def build_fuzzers_entrypoint():
+  """Builds OSS-Fuzz project's fuzzers for CI tools."""
+  config = config_utils.BuildFuzzersConfig()
 
-  Note: The resulting clusterfuzz binaries of this build are placed in
+  if config.dry_run:
+    # Sets the default return code on error to success.
+    returncode = 0
+  else:
+    # The default return code when an error occurs.
+    returncode = 1
+
+  if not build_fuzzers.build_fuzzers(config):
+    logging.error('Error building fuzzers for (commit: %s, pr_ref: %s).',
+                  config.commit_sha, config.pr_ref)
+    return returncode
+
+  return 0
+
+
+def main():
+  """Builds OSS-Fuzz project's fuzzers for CI tools.
+
+  Note: The resulting fuzz target binaries of this build are placed in
   the directory: ${GITHUB_WORKSPACE}/out
 
   Required environment variables:
@@ -50,44 +64,9 @@
     SANITIZER: The sanitizer to use when running fuzzers.
 
   Returns:
-    0 on success or 1 on failure.
+    0 on success or nonzero on failure.
   """
-  config = config_utils.BuildFuzzersConfig()
-
-  if config.dry_run:
-    # Sets the default return code on error to success.
-    returncode = 0
-  else:
-    # The default return code when an error occurs.
-    returncode = 1
-
-  if not config.workspace:
-    logging.error('This script needs to be run within Github actions.')
-    return returncode
-
-  if not build_fuzzers.build_fuzzers(config):
-    logging.error(
-        'Error building fuzzers for project %s (commit: %s, pr_ref: %s).',
-        config.project_name, config.commit_sha, config.pr_ref)
-    return returncode
-
-  out_dir = os.path.join(config.workspace, 'out')
-
-  if not config.bad_build_check:
-    # If we've gotten to this point and we don't need to do bad_build_check,
-    # then the build has succeeded.
-    returncode = 0
-  # yapf: disable
-  elif build_fuzzers.check_fuzzer_build(
-      out_dir,
-      config.sanitizer,
-      config.language,
-      allowed_broken_targets_percentage=config.allowed_broken_targets_percentage
-  ):
-    # yapf: enable
-    returncode = 0
-
-  return returncode
+  return build_fuzzers_entrypoint()
 
 
 if __name__ == '__main__':
diff --git a/infra/cifuzz/build_fuzzers_test.py b/infra/cifuzz/build_fuzzers_test.py
index 2987788..5c068ac 100644
--- a/infra/cifuzz/build_fuzzers_test.py
+++ b/infra/cifuzz/build_fuzzers_test.py
@@ -28,8 +28,8 @@
 OSS_FUZZ_DIR = os.path.dirname(INFRA_DIR)
 
 import build_fuzzers
-import config_utils
 import continuous_integration
+import repo_manager
 import test_helpers
 
 # NOTE: This integration test relies on
@@ -53,23 +53,7 @@
 # A fuzzer to be built in build_fuzzers integration tests.
 EXAMPLE_BUILD_FUZZER = 'do_stuff_fuzzer'
 
-# pylint: disable=no-self-use,protected-access,too-few-public-methods
-
-
-def create_config(**kwargs):
-  """Creates a config object and then sets every attribute that is a key in
-  |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an
-  attribute of Config."""
-  with mock.patch('os.path.basename', return_value=None), mock.patch(
-      'config_utils.get_project_src_path',
-      return_value=None), mock.patch('config_utils._is_dry_run',
-                                     return_value=True):
-    config = config_utils.BuildFuzzersConfig()
-
-  for key, value in kwargs.items():
-    assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
-    setattr(config, key, value)
-  return config
+# pylint: disable=no-self-use,protected-access,too-few-public-methods,unused-argument
 
 
 class BuildFuzzersTest(unittest.TestCase):
@@ -79,17 +63,19 @@
               return_value=('example.com', '/path'))
   @mock.patch('repo_manager._clone', return_value=None)
   @mock.patch('continuous_integration.checkout_specified_commit')
-  @mock.patch('helper.docker_run')
-  def test_cifuzz_env_var(self, mocked_docker_run, _, __, ___):
+  @mock.patch('helper.docker_run', return_value=False)  # We want to quit early.
+  def test_cifuzz_env_var(self, mock_docker_run, _, __, ___):
     """Tests that the CIFUZZ env var is set."""
 
     with tempfile.TemporaryDirectory() as tmp_dir:
       build_fuzzers.build_fuzzers(
-          create_config(project_name=EXAMPLE_PROJECT,
-                        project_repo_name=EXAMPLE_PROJECT,
-                        workspace=tmp_dir,
-                        pr_ref='refs/pull/1757/merge'))
-    docker_run_command = mocked_docker_run.call_args_list[0][0][0]
+          test_helpers.create_build_config(
+              oss_fuzz_project_name=EXAMPLE_PROJECT,
+              project_repo_name=EXAMPLE_PROJECT,
+              workspace=tmp_dir,
+              pr_ref='refs/pull/1757/merge'))
+
+      docker_run_command = mock_docker_run.call_args_list[0][0][0]
 
     def command_has_env_var_arg(command, env_var_arg):
       for idx, element in enumerate(command):
@@ -105,23 +91,25 @@
 
 class InternalGithubBuildTest(unittest.TestCase):
   """Tests for building OSS-Fuzz projects on GitHub actions."""
-  PROJECT_NAME = 'myproject'
   PROJECT_REPO_NAME = 'myproject'
   SANITIZER = 'address'
   COMMIT_SHA = 'fake'
   PR_REF = 'fake'
 
-  def _create_builder(self, tmp_dir):
+  def _create_builder(self, tmp_dir, oss_fuzz_project_name='myproject'):
     """Creates an InternalGithubBuilder and returns it."""
-    config = create_config(project_name=self.PROJECT_NAME,
-                           project_repo_name=self.PROJECT_REPO_NAME,
-                           workspace=tmp_dir,
-                           sanitizer=self.SANITIZER,
-                           commit_sha=self.COMMIT_SHA,
-                           pr_ref=self.PR_REF,
-                           is_github=True)
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=oss_fuzz_project_name,
+        project_repo_name=self.PROJECT_REPO_NAME,
+        workspace=tmp_dir,
+        sanitizer=self.SANITIZER,
+        commit_sha=self.COMMIT_SHA,
+        pr_ref=self.PR_REF,
+        is_github=True)
     ci_system = continuous_integration.get_ci(config)
-    return build_fuzzers.Builder(config, ci_system)
+    builder = build_fuzzers.Builder(config, ci_system)
+    builder.repo_manager = repo_manager.RepoManager('/fake')
+    return builder
 
   @mock.patch('repo_manager._clone', side_effect=None)
   @mock.patch('continuous_integration.checkout_specified_commit',
@@ -141,6 +129,29 @@
     self.assertEqual(os.path.basename(builder.host_repo_path),
                      os.path.basename(image_repo_path))
 
+  @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_build',
+              return_value=True)
+  def test_upload_build_disabled(self, mock_upload_build):
+    """Test upload build (disabled)."""
+    with tempfile.TemporaryDirectory() as tmp_dir:
+      builder = self._create_builder(tmp_dir)
+      builder.upload_build()
+
+    mock_upload_build.assert_not_called()
+
+  @mock.patch('repo_manager.RepoManager.get_current_commit',
+              return_value='commit')
+  @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_build',
+              return_value=True)
+  def test_upload_build(self, mock_upload_build, mock_get_current_commit):
+    """Test upload build."""
+    with tempfile.TemporaryDirectory() as tmp_dir:
+      builder = self._create_builder(tmp_dir, oss_fuzz_project_name='')
+      builder.config.upload_build = True
+      builder.upload_build()
+
+    mock_upload_build.assert_called_with('commit')
+
 
 @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
                  'INTEGRATION_TESTS=1 not set')
@@ -148,36 +159,59 @@
   """Integration tests for build_fuzzers."""
 
   def setUp(self):
-    self.tmp_dir_obj = tempfile.TemporaryDirectory()
-    self.workspace = self.tmp_dir_obj.name
-    self.out_dir = os.path.join(self.workspace, 'out')
+    self.temp_dir_obj = tempfile.TemporaryDirectory()
+    self.workspace = self.temp_dir_obj.name
+    self.out_dir = os.path.join(self.workspace, 'build-out')
     test_helpers.patch_environ(self)
 
+    base_runner_path = os.path.join(INFRA_DIR, 'base-images', 'base-runner')
+    os.environ['PATH'] = os.environ['PATH'] + os.pathsep + base_runner_path
+
   def tearDown(self):
-    self.tmp_dir_obj.cleanup()
+    self.temp_dir_obj.cleanup()
 
   def test_external_github_project(self):
     """Tests building fuzzers from an external project on Github."""
-    project_name = 'external-project'
-    build_integration_path = 'fuzzer-build-integration'
+    project_repo_name = 'external-project'
     git_url = 'https://github.com/jonathanmetzman/cifuzz-external-example.git'
     # This test is dependant on the state of
     # github.com/jonathanmetzman/cifuzz-external-example.
-    config = create_config(project_name=project_name,
-                           project_repo_name=project_name,
-                           workspace=self.workspace,
-                           build_integration_path=build_integration_path,
-                           git_url=git_url,
-                           commit_sha='HEAD',
-                           base_commit='HEAD^1')
+    config = test_helpers.create_build_config(
+        project_repo_name=project_repo_name,
+        workspace=self.workspace,
+        git_url=git_url,
+        commit_sha='HEAD',
+        is_github=True,
+        base_commit='HEAD^1')
+    self.assertTrue(build_fuzzers.build_fuzzers(config))
+    self.assertTrue(
+        os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER)))
+
+  def test_external_generic_project(self):
+    """Tests building fuzzers from an external project not on Github."""
+    project_repo_name = 'cifuzz-external-example'
+    git_url = 'https://github.com/jonathanmetzman/cifuzz-external-example.git'
+    # This test is dependant on the state of
+    # github.com/jonathanmetzman/cifuzz-external-example.
+    manager = repo_manager.clone_repo_and_get_manager(
+        'https://github.com/jonathanmetzman/cifuzz-external-example',
+        self.temp_dir_obj.name)
+    project_src_path = manager.repo_dir
+    config = test_helpers.create_build_config(
+        project_repo_name=project_repo_name,
+        workspace=self.workspace,
+        git_url=git_url,
+        commit_sha='HEAD',
+        project_src_path=project_src_path,
+        base_commit='HEAD^1')
     self.assertTrue(build_fuzzers.build_fuzzers(config))
     self.assertTrue(
         os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER)))
 
   def test_valid_commit(self):
     """Tests building fuzzers with valid inputs."""
-    config = create_config(
-        project_name=EXAMPLE_PROJECT,
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
         project_repo_name='oss-fuzz',
         workspace=self.workspace,
         commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523',
@@ -189,31 +223,32 @@
 
   def test_valid_pull_request(self):
     """Tests building fuzzers with valid pull request."""
-    # TODO(metzman): What happens when this branch closes?
-    config = create_config(project_name=EXAMPLE_PROJECT,
-                           project_repo_name='oss-fuzz',
-                           workspace=self.workspace,
-                           pr_ref='refs/pull/1757/merge',
-                           base_ref='master',
-                           is_github=True)
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
+        project_repo_name='oss-fuzz',
+        workspace=self.workspace,
+        pr_ref='refs/pull/1757/merge',
+        base_ref='master',
+        is_github=True)
     self.assertTrue(build_fuzzers.build_fuzzers(config))
     self.assertTrue(
         os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER)))
 
   def test_invalid_pull_request(self):
     """Tests building fuzzers with invalid pull request."""
-    config = create_config(project_name=EXAMPLE_PROJECT,
-                           project_repo_name='oss-fuzz',
-                           workspace=self.workspace,
-                           pr_ref='ref-1/merge',
-                           base_ref='master',
-                           is_github=True)
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
+        project_repo_name='oss-fuzz',
+        workspace=self.workspace,
+        pr_ref='ref-1/merge',
+        base_ref='master',
+        is_github=True)
     self.assertTrue(build_fuzzers.build_fuzzers(config))
 
-  def test_invalid_project_name(self):
+  def test_invalid_oss_fuzz_project_name(self):
     """Tests building fuzzers with invalid project name."""
-    config = create_config(
-        project_name='not_a_valid_project',
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name='not_a_valid_project',
         project_repo_name='oss-fuzz',
         workspace=self.workspace,
         commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')
@@ -221,8 +256,8 @@
 
   def test_invalid_repo_name(self):
     """Tests building fuzzers with invalid repo name."""
-    config = create_config(
-        project_name=EXAMPLE_PROJECT,
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
         project_repo_name='not-real-repo',
         workspace=self.workspace,
         commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')
@@ -230,18 +265,19 @@
 
   def test_invalid_commit_sha(self):
     """Tests building fuzzers with invalid commit SHA."""
-    config = create_config(project_name=EXAMPLE_PROJECT,
-                           project_repo_name='oss-fuzz',
-                           workspace=self.workspace,
-                           commit_sha='',
-                           is_github=True)
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
+        project_repo_name='oss-fuzz',
+        workspace=self.workspace,
+        commit_sha='',
+        is_github=True)
     with self.assertRaises(AssertionError):
       build_fuzzers.build_fuzzers(config)
 
   def test_invalid_workspace(self):
     """Tests building fuzzers with invalid workspace."""
-    config = create_config(
-        project_name=EXAMPLE_PROJECT,
+    config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
         project_repo_name='oss-fuzz',
         workspace=os.path.join(self.workspace, 'not', 'a', 'dir'),
         commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')
@@ -255,44 +291,47 @@
   LANGUAGE = 'c++'
 
   def setUp(self):
-    self.tmp_dir_obj = tempfile.TemporaryDirectory()
-    self.test_files_path = os.path.join(self.tmp_dir_obj.name, 'test_files')
-    shutil.copytree(TEST_DATA_PATH, self.test_files_path)
+    self.temp_dir_obj = tempfile.TemporaryDirectory()
+    workspace_path = os.path.join(self.temp_dir_obj.name, 'workspace')
+    self.config = test_helpers.create_build_config(
+        oss_fuzz_project_name=EXAMPLE_PROJECT,
+        sanitizer=self.SANITIZER,
+        language=self.LANGUAGE,
+        workspace=workspace_path,
+        pr_ref='refs/pull/1757/merge')
+    self.workspace = test_helpers.create_workspace(workspace_path)
+    shutil.copytree(TEST_DATA_PATH, workspace_path)
+    test_helpers.patch_environ(self, runner=True)
 
   def tearDown(self):
-    self.tmp_dir_obj.cleanup()
+    self.temp_dir_obj.cleanup()
 
   def test_correct_fuzzer_build(self):
     """Checks check_fuzzer_build function returns True for valid fuzzers."""
-    test_fuzzer_dir = os.path.join(self.test_files_path, 'out')
-    self.assertTrue(
-        build_fuzzers.check_fuzzer_build(test_fuzzer_dir, self.SANITIZER,
-                                         self.LANGUAGE))
+    self.assertTrue(build_fuzzers.check_fuzzer_build(self.config))
 
-  def test_not_a_valid_fuzz_path(self):
-    """Tests that False is returned when a bad path is given."""
-    self.assertFalse(
-        build_fuzzers.check_fuzzer_build('not/a/valid/path', self.SANITIZER,
-                                         self.LANGUAGE))
+  def test_not_a_valid_path(self):
+    """Tests that False is returned when a nonexistent path is given."""
+    self.config.workspace = 'not/a/valid/path'
+    self.assertFalse(build_fuzzers.check_fuzzer_build(self.config))
 
-  def test_not_a_valid_fuzzer(self):
-    """Checks a directory that exists but does not have fuzzers is False."""
-    self.assertFalse(
-        build_fuzzers.check_fuzzer_build(self.test_files_path, self.SANITIZER,
-                                         self.LANGUAGE))
+  def test_no_valid_fuzzers(self):
+    """Tests that False is returned when an empty directory is given."""
+    with tempfile.TemporaryDirectory() as tmp_dir:
+      self.config.workspace = tmp_dir
+      os.mkdir(os.path.join(self.config.workspace, 'build-out'))
+      self.assertFalse(build_fuzzers.check_fuzzer_build(self.config))
 
-  @mock.patch('helper.docker_run')
-  def test_allow_broken_fuzz_targets_percentage(self, mocked_docker_run):
+  @mock.patch('utils.execute', return_value=(None, None, 0))
+  def test_allow_broken_fuzz_targets_percentage(self, mock_execute):
     """Tests that ALLOWED_BROKEN_TARGETS_PERCENTAGE is set when running
     docker if passed to check_fuzzer_build."""
-    mocked_docker_run.return_value = 0
-    test_fuzzer_dir = os.path.join(TEST_DATA_PATH, 'out')
-    build_fuzzers.check_fuzzer_build(test_fuzzer_dir,
-                                     self.SANITIZER,
-                                     self.LANGUAGE,
-                                     allowed_broken_targets_percentage='0')
-    self.assertIn('-e ALLOWED_BROKEN_TARGETS_PERCENTAGE=0',
-                  ' '.join(mocked_docker_run.call_args[0][0]))
+    percentage = '0'
+    self.config.allowed_broken_targets_percentage = percentage
+    build_fuzzers.check_fuzzer_build(self.config)
+    self.assertEqual(
+        mock_execute.call_args[1]['env']['ALLOWED_BROKEN_TARGETS_PERCENTAGE'],
+        percentage)
 
 
 @unittest.skip('Test is too long to be run with presubmit.')
@@ -304,11 +343,12 @@
 
   @classmethod
   def _create_config(cls, tmp_dir, sanitizer):
-    return create_config(project_name=cls.PROJECT_NAME,
-                         project_repo_name=cls.PROJECT_NAME,
-                         workspace=tmp_dir,
-                         pr_ref=cls.PR_REF,
-                         sanitizer=sanitizer)
+    return test_helpers.create_build_config(
+        oss_fuzz_project_name=cls.PROJECT_NAME,
+        project_repo_name=cls.PROJECT_NAME,
+        workspace=tmp_dir,
+        pr_ref=cls.PR_REF,
+        sanitizer=sanitizer)
 
   @parameterized.parameterized.expand([('memory',), ('undefined',)])
   def test_valid_project_curl(self, sanitizer):
@@ -318,18 +358,6 @@
           build_fuzzers.build_fuzzers(self._create_config(tmp_dir, sanitizer)))
 
 
-class GetDockerBuildFuzzersArgsContainerTest(unittest.TestCase):
-  """Tests that _get_docker_build_fuzzers_args_container works as intended."""
-
-  def test_get_docker_build_fuzzers_args_container(self):
-    """Tests that _get_docker_build_fuzzers_args_container works as intended."""
-    out_dir = '/my/out'
-    container = 'my-container'
-    result = build_fuzzers._get_docker_build_fuzzers_args_container(
-        out_dir, container)
-    self.assertEqual(result, ['-e', 'OUT=/my/out', '--volumes-from', container])
-
-
 class GetDockerBuildFuzzersArgsNotContainerTest(unittest.TestCase):
   """Tests that _get_docker_build_fuzzers_args_not_container works as
   intended."""
@@ -337,25 +365,10 @@
   def test_get_docker_build_fuzzers_args_no_container(self):
     """Tests that _get_docker_build_fuzzers_args_not_container works
     as intended."""
-    host_out_dir = '/cifuzz/out'
     host_repo_path = '/host/repo'
     result = build_fuzzers._get_docker_build_fuzzers_args_not_container(
-        host_out_dir, host_repo_path)
-    expected_result = [
-        '-e', 'OUT=/out', '-v', '/cifuzz/out:/out', '-v',
-        '/host/repo:/host/repo'
-    ]
-    self.assertEqual(result, expected_result)
-
-
-class GetDockerBuildFuzzersArgsMsanTest(unittest.TestCase):
-  """Tests that _get_docker_build_fuzzers_args_msan works as intended."""
-
-  def test_get_docker_build_fuzzers_args_msan(self):
-    """Tests that _get_docker_build_fuzzers_args_msan works as intended."""
-    work_dir = '/work_dir'
-    result = build_fuzzers._get_docker_build_fuzzers_args_msan(work_dir)
-    expected_result = ['-e', 'MSAN_LIBS_PATH=/work_dir/msan']
+        host_repo_path)
+    expected_result = ['-v', '/host/repo:/host/repo']
     self.assertEqual(result, expected_result)
 
 
diff --git a/infra/cifuzz/cifuzz-base/Dockerfile b/infra/cifuzz/cifuzz-base/Dockerfile
index e0599db..bb1431d 100644
--- a/infra/cifuzz/cifuzz-base/Dockerfile
+++ b/infra/cifuzz/cifuzz-base/Dockerfile
@@ -14,19 +14,20 @@
 #
 ################################################################################
 
-# Don't bother with a slimmer base image.
-# When we pull base-builder to build project builder image we need to pull
-# ubuntu:16.04 anyway. So in the long run we probably would waste time if
-# we pulled something like alpine here instead.
-FROM ubuntu:16.04
+FROM gcr.io/oss-fuzz-base/base-runner
 
 RUN apt-get update && \
-    apt-get install ca-certificates wget python3 git-core --no-install-recommends -y && \
-    wget https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce-cli_20.10.5~3-0~ubuntu-xenial_amd64.deb -O /tmp/docker-ce.deb && \
-    dpkg -i /tmp/docker-ce.deb && rm /tmp/docker-ce.deb && \
-    apt-get remove wget -y --purge
-
+    apt-get install -y systemd && \
+    apt-get install -y --no-install-recommends nodejs npm && \
+    wget https://download.docker.com/linux/ubuntu/dists/focal/pool/stable/amd64/docker-ce-cli_20.10.8~3-0~ubuntu-focal_amd64.deb -O /tmp/docker-ce.deb && \
+    dpkg -i /tmp/docker-ce.deb && rm /tmp/docker-ce.deb
 
 ENV OSS_FUZZ_ROOT=/opt/oss-fuzz
 ADD . ${OSS_FUZZ_ROOT}
-RUN rm -rf ${OSS_FUZZ_ROOT}/infra
\ No newline at end of file
+RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt
+RUN npm install ${OSS_FUZZ_ROOT}/infra/cifuzz
+
+# Python file to execute when the docker container starts up.
+# We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var,
+# just expand to '/opt/oss-fuzz'.
+ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py"]
diff --git a/infra/cifuzz/cifuzz_combined_entrypoint.py b/infra/cifuzz/cifuzz_combined_entrypoint.py
new file mode 100644
index 0000000..008ce10
--- /dev/null
+++ b/infra/cifuzz/cifuzz_combined_entrypoint.py
@@ -0,0 +1,53 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Builds fuzzers and runs fuzzers. Entrypoint used for external users"""
+import logging
+import sys
+
+import build_fuzzers_entrypoint
+import run_fuzzers_entrypoint
+
+
+def main():
+  """Builds and runs fuzzers for CI tools.
+
+  NOTE: Any crash report will be in the filepath:
+  ${GITHUB_WORKSPACE}/out/testcase
+ This can be used with GitHub's upload-artifact action to surface the logs.
+
+  Required environment variables:
+    OSS_FUZZ_PROJECT_NAME: The name of OSS-Fuzz project.
+    GITHUB_REPOSITORY: The name of the Github repo that called this script.
+    GITHUB_SHA: The commit SHA that triggered this script.
+    GITHUB_EVENT_NAME: The name of the hook event that triggered this script.
+    GITHUB_EVENT_PATH:
+      The path to the file containing the POST payload of the webhook:
+      https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners#filesystems-on-github-hosted-runners
+    GITHUB_WORKSPACE: The shared volume directory where input artifacts are.
+    DRY_RUN: If true, no failures will surface.
+    SANITIZER: The sanitizer to use when running fuzzers.
+    FUZZ_SECONDS: The length of time in seconds that fuzzers are to be run.
+
+  Returns:
+    0 on success or 1 on failure.
+  """
+  logging.debug("Using cifuzz_combined_entrypoint.")
+  result = build_fuzzers_entrypoint.build_fuzzers_entrypoint()
+  if result != 0:
+    return result
+  return run_fuzzers_entrypoint.run_fuzzers_entrypoint()
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/infra/cifuzz/cifuzz_end_to_end_test.py b/infra/cifuzz/cifuzz_end_to_end_test.py
new file mode 100644
index 0000000..2a4234f
--- /dev/null
+++ b/infra/cifuzz/cifuzz_end_to_end_test.py
@@ -0,0 +1,46 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""End-to-End tests for CIFuzz."""
+import os
+import unittest
+
+import run_cifuzz
+import test_helpers
+
+CIFUZZ_DIR = os.path.dirname(os.path.abspath(__file__))
+EXTERNAL_PROJECT_PATH = os.path.join(CIFUZZ_DIR, 'test_data',
+                                     'external-project')
+
+
+# This test will fail if not run as root because the fuzzer build process
+# creates binaries that only root can write to.
+# Use a seperate env var to keep this seperate from integration tests which
+# don't have this annoying property.
+@unittest.skipIf(not os.getenv('END_TO_END_TESTS'),
+                 'END_TO_END_TESTS=1 not set')
+class EndToEndTest(unittest.TestCase):
+  """End-to-End tests for CIFuzz."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self, runner=True)
+
+  def test_simple(self):
+    """Simple end-to-end test using run_cifuzz.main()."""
+    os.environ['REPOSITORY'] = 'external-project'
+    os.environ['PROJECT_SRC_PATH'] = EXTERNAL_PROJECT_PATH
+
+    with test_helpers.docker_temp_dir() as temp_dir:
+      os.environ['WORKSPACE'] = temp_dir
+      # TODO(metzman): Verify the crash, affected fuzzers, and other things.
+      self.assertEqual(run_cifuzz.main(), 1)
diff --git a/infra/cifuzz/cloudbuild.yaml b/infra/cifuzz/cloudbuild.yaml
new file mode 100644
index 0000000..6f38cce
--- /dev/null
+++ b/infra/cifuzz/cloudbuild.yaml
@@ -0,0 +1,39 @@
+steps:
+- name: 'gcr.io/cloud-builders/docker'
+  args:
+  - build
+  - '-t'
+  - gcr.io/oss-fuzz-base/cifuzz-base
+  - '-t'
+  - gcr.io/oss-fuzz-base/cifuzz-base:v1
+  - '-f'
+  - infra/cifuzz/cifuzz-base/Dockerfile
+  - .
+- name: 'gcr.io/cloud-builders/docker'
+  args:
+  - build
+  - '-t'
+  - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers
+  - '-t'
+  - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:v1
+  - '-f'
+  - infra/build_fuzzers.Dockerfile
+  - infra
+- name: 'gcr.io/cloud-builders/docker'
+  args:
+  - build
+  - '-t'
+  - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers
+  - '-t'
+  - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:v1
+  - '-f'
+  - infra/run_fuzzers.Dockerfile
+  - infra
+images:
+- gcr.io/oss-fuzz-base/cifuzz-base
+- gcr.io/oss-fuzz-base/cifuzz-base:v1
+- gcr.io/oss-fuzz-base/cifuzz-run-fuzzers
+- gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:v1
+- gcr.io/oss-fuzz-base/cifuzz-build-fuzzers
+- gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:v1
+timeout: 1800s
diff --git a/infra/cifuzz/clusterfuzz_deployment.py b/infra/cifuzz/clusterfuzz_deployment.py
index 8c46e9d..fdc3738 100644
--- a/infra/cifuzz/clusterfuzz_deployment.py
+++ b/infra/cifuzz/clusterfuzz_deployment.py
@@ -11,15 +11,20 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-"""Module for interacting with the "ClusterFuzz deployment."""
+"""Module for interacting with the ClusterFuzz deployment."""
 import logging
 import os
 import sys
-import tempfile
-import time
 import urllib.error
 import urllib.request
-import zipfile
+
+import config_utils
+import continuous_integration
+import filestore
+import filestore_utils
+import http_utils
+import get_coverage
+import repo_manager
 
 # pylint: disable=wrong-import-position,import-error
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
@@ -29,13 +34,12 @@
 class BaseClusterFuzzDeployment:
   """Base class for ClusterFuzz deployments."""
 
-  CORPUS_DIR_NAME = 'cifuzz-corpus'
-  BUILD_DIR_NAME = 'cifuzz-latest-build'
-
-  def __init__(self, config):
+  def __init__(self, config, workspace):
     self.config = config
+    self.workspace = workspace
+    self.ci_system = continuous_integration.get_ci(config)
 
-  def download_latest_build(self, out_dir):
+  def download_latest_build(self):
     """Downloads the latest build from ClusterFuzz.
 
     Returns:
@@ -43,23 +47,167 @@
     """
     raise NotImplementedError('Child class must implement method.')
 
-  def download_corpus(self, target_name, out_dir):
-    """Downloads the corpus for |target_name| from ClusterFuzz to |out_dir|.
+  def upload_build(self, commit):
+    """Uploads the build with the given commit sha to the filestore."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def download_corpus(self, target_name, corpus_dir):
+    """Downloads the corpus for |target_name| from ClusterFuzz to |corpus_dir|.
 
     Returns:
       A path to where the OSS-Fuzz build was stored, or None if it wasn't.
     """
     raise NotImplementedError('Child class must implement method.')
 
+  def upload_crashes(self):
+    """Uploads crashes in |crashes_dir| to filestore."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def upload_corpus(self, target_name, corpus_dir, replace=False):  # pylint: disable=no-self-use,unused-argument
+    """Uploads the corpus for |target_name| to filestore."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def upload_coverage(self):
+    """Uploads the coverage report to the filestore."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def get_coverage(self, repo_path):
+    """Returns the project coverage object for the project."""
+    raise NotImplementedError('Child class must implement method.')
+
+
+def _make_empty_dir_if_nonexistent(path):
+  """Makes an empty directory at |path| if it does not exist."""
+  os.makedirs(path, exist_ok=True)
+
 
 class ClusterFuzzLite(BaseClusterFuzzDeployment):
   """Class representing a deployment of ClusterFuzzLite."""
 
-  def download_latest_build(self, out_dir):
-    logging.info('download_latest_build not implemented for ClusterFuzzLite.')
+  COVERAGE_NAME = 'latest'
+  LATEST_BUILD_WINDOW = 3
 
-  def download_corpus(self, target_name, out_dir):
-    logging.info('download_corpus not implemented for ClusterFuzzLite.')
+  def __init__(self, config, workspace):
+    super().__init__(config, workspace)
+    self.filestore = filestore_utils.get_filestore(self.config)
+
+  def download_latest_build(self):
+    if os.path.exists(self.workspace.clusterfuzz_build):
+      # This path is necessary because download_latest_build can be called
+      # multiple times.That is the case because it is called only when we need
+      # to see if a bug is novel, i.e. until we want to check a bug is novel we
+      # don't want to waste time calling this, but therefore this method can be
+      # called if multiple bugs are found.
+      return self.workspace.clusterfuzz_build
+
+    repo_dir = self.ci_system.repo_dir()
+    if not repo_dir:
+      raise RuntimeError('Repo checkout does not exist.')
+
+    _make_empty_dir_if_nonexistent(self.workspace.clusterfuzz_build)
+    repo = repo_manager.RepoManager(repo_dir)
+
+    # Builds are stored by commit, so try the latest |LATEST_BUILD_WINDOW|
+    # commits before the current.
+    # TODO(ochang): If API usage becomes an issue, this can be optimized by the
+    # filestore accepting a list of filenames to try.
+    for old_commit in repo.get_commit_list('HEAD^',
+                                           limit=self.LATEST_BUILD_WINDOW):
+      logging.info('Trying to downloading previous build %s.', old_commit)
+      build_name = self._get_build_name(old_commit)
+      try:
+        if self.filestore.download_build(build_name,
+                                         self.workspace.clusterfuzz_build):
+          logging.info('Done downloading previus build.')
+          return self.workspace.clusterfuzz_build
+
+        logging.info('Build for %s does not exist.', old_commit)
+      except Exception as err:  # pylint: disable=broad-except
+        logging.error('Could not download build for %s because of: %s',
+                      old_commit, err)
+
+    return None
+
+  def download_corpus(self, target_name, corpus_dir):
+    _make_empty_dir_if_nonexistent(corpus_dir)
+    logging.info('Downloading corpus for %s to %s.', target_name, corpus_dir)
+    corpus_name = self._get_corpus_name(target_name)
+    try:
+      self.filestore.download_corpus(corpus_name, corpus_dir)
+      logging.info('Done downloading corpus. Contains %d elements.',
+                   len(os.listdir(corpus_dir)))
+    except Exception as err:  # pylint: disable=broad-except
+      logging.error('Failed to download corpus for target: %s. Error: %s',
+                    target_name, str(err))
+    return corpus_dir
+
+  def _get_build_name(self, name):
+    return f'{self.config.sanitizer}-{name}'
+
+  def _get_corpus_name(self, target_name):  # pylint: disable=no-self-use
+    """Returns the name of the corpus artifact."""
+    return target_name
+
+  def _get_crashes_artifact_name(self):  # pylint: disable=no-self-use
+    """Returns the name of the crashes artifact."""
+    return 'current'
+
+  def upload_corpus(self, target_name, corpus_dir, replace=False):
+    """Upload the corpus produced by |target_name|."""
+    logging.info('Uploading corpus in %s for %s.', corpus_dir, target_name)
+    name = self._get_corpus_name(target_name)
+    try:
+      self.filestore.upload_corpus(name, corpus_dir, replace=replace)
+      logging.info('Done uploading corpus.')
+    except Exception as error:  # pylint: disable=broad-except
+      logging.error('Failed to upload corpus for target: %s. Error: %s.',
+                    target_name, error)
+
+  def upload_build(self, commit):
+    """Upload the build produced by CIFuzz as the latest build."""
+    logging.info('Uploading latest build in %s.', self.workspace.out)
+    build_name = self._get_build_name(commit)
+    try:
+      result = self.filestore.upload_build(build_name, self.workspace.out)
+      logging.info('Done uploading latest build.')
+      return result
+    except Exception as error:  # pylint: disable=broad-except
+      logging.error('Failed to upload latest build: %s. Error: %s',
+                    self.workspace.out, error)
+
+  def upload_crashes(self):
+    """Uploads crashes."""
+    if not os.listdir(self.workspace.artifacts):
+      logging.info('No crashes in %s. Not uploading.', self.workspace.artifacts)
+      return
+
+    crashes_artifact_name = self._get_crashes_artifact_name()
+
+    logging.info('Uploading crashes in %s.', self.workspace.artifacts)
+    try:
+      self.filestore.upload_crashes(crashes_artifact_name,
+                                    self.workspace.artifacts)
+      logging.info('Done uploading crashes.')
+    except Exception as error:  # pylint: disable=broad-except
+      logging.error('Failed to upload crashes. Error: %s', error)
+
+  def upload_coverage(self):
+    """Uploads the coverage report to the filestore."""
+    self.filestore.upload_coverage(self.COVERAGE_NAME,
+                                   self.workspace.coverage_report)
+
+  def get_coverage(self, repo_path):
+    """Returns the project coverage object for the project."""
+    try:
+      if not self.filestore.download_coverage(
+          self.COVERAGE_NAME, self.workspace.clusterfuzz_coverage):
+        logging.error('Could not download coverage.')
+        return None
+      return get_coverage.FilesystemCoverage(
+          repo_path, self.workspace.clusterfuzz_coverage)
+    except (get_coverage.CoverageError, filestore.FilestoreError):
+      logging.error('Could not get coverage.')
+      return None
 
 
 class OSSFuzz(BaseClusterFuzzDeployment):
@@ -68,9 +216,6 @@
   # Location of clusterfuzz builds on GCS.
   CLUSTERFUZZ_BUILDS = 'clusterfuzz-builds'
 
-  # Format string for the latest version of a project's build.
-  VERSION_STRING = '{project_name}-{sanitizer}-latest.version'
-
   # Zip file name containing the corpus.
   CORPUS_ZIP_NAME = 'public.zip'
 
@@ -80,139 +225,148 @@
     Returns:
       A string with the latest build version or None.
     """
-    version_file = self.VERSION_STRING.format(
-        project_name=self.config.project_name, sanitizer=self.config.sanitizer)
+    version_file = (
+        f'{self.config.oss_fuzz_project_name}-{self.config.sanitizer}'
+        '-latest.version')
     version_url = utils.url_join(utils.GCS_BASE_URL, self.CLUSTERFUZZ_BUILDS,
-                                 self.config.project_name, version_file)
+                                 self.config.oss_fuzz_project_name,
+                                 version_file)
     try:
       response = urllib.request.urlopen(version_url)
     except urllib.error.HTTPError:
       logging.error('Error getting latest build version for %s from: %s.',
-                    self.config.project_name, version_url)
+                    self.config.oss_fuzz_project_name, version_url)
       return None
     return response.read().decode()
 
-  def download_latest_build(self, out_dir):
+  def download_latest_build(self):
     """Downloads the latest OSS-Fuzz build from GCS.
 
     Returns:
       A path to where the OSS-Fuzz build was stored, or None if it wasn't.
     """
-    build_dir = os.path.join(out_dir, self.BUILD_DIR_NAME)
-    if os.path.exists(build_dir):
-      return build_dir
+    if os.path.exists(self.workspace.clusterfuzz_build):
+      # This function can be called multiple times, don't download the build
+      # again.
+      return self.workspace.clusterfuzz_build
 
-    os.makedirs(build_dir, exist_ok=True)
+    _make_empty_dir_if_nonexistent(self.workspace.clusterfuzz_build)
 
     latest_build_name = self.get_latest_build_name()
     if not latest_build_name:
       return None
 
+    logging.info('Downloading latest build.')
     oss_fuzz_build_url = utils.url_join(utils.GCS_BASE_URL,
                                         self.CLUSTERFUZZ_BUILDS,
-                                        self.config.project_name,
+                                        self.config.oss_fuzz_project_name,
                                         latest_build_name)
-    if download_and_unpack_zip(oss_fuzz_build_url, build_dir):
-      return build_dir
+    if http_utils.download_and_unpack_zip(oss_fuzz_build_url,
+                                          self.workspace.clusterfuzz_build):
+      logging.info('Done downloading latest build.')
+      return self.workspace.clusterfuzz_build
 
     return None
 
-  def download_corpus(self, target_name, out_dir):
+  def upload_build(self, commit):  # pylint: disable=no-self-use
+    """Noop Implementation of upload_build."""
+    logging.info('Not uploading latest build because on OSS-Fuzz.')
+
+  def upload_corpus(self, target_name, corpus_dir, replace=False):  # pylint: disable=no-self-use,unused-argument
+    """Noop Implementation of upload_corpus."""
+    logging.info('Not uploading corpus because on OSS-Fuzz.')
+
+  def upload_crashes(self):  # pylint: disable=no-self-use
+    """Noop Implementation of upload_crashes."""
+    logging.info('Not uploading crashes because on OSS-Fuzz.')
+
+  def download_corpus(self, target_name, corpus_dir):
     """Downloads the latest OSS-Fuzz corpus for the target.
 
     Returns:
       The local path to to corpus or None if download failed.
     """
-    corpus_dir = os.path.join(out_dir, self.CORPUS_DIR_NAME, target_name)
-    os.makedirs(corpus_dir, exist_ok=True)
-    # TODO(metzman): Clean up this code.
+    _make_empty_dir_if_nonexistent(corpus_dir)
     project_qualified_fuzz_target_name = target_name
-    qualified_name_prefix = self.config.project_name + '_'
-
+    qualified_name_prefix = self.config.oss_fuzz_project_name + '_'
     if not target_name.startswith(qualified_name_prefix):
       project_qualified_fuzz_target_name = qualified_name_prefix + target_name
 
-    corpus_url = utils.url_join(
-        utils.GCS_BASE_URL,
-        '{0}-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/'.format(
-            self.config.project_name), project_qualified_fuzz_target_name,
-        self.CORPUS_ZIP_NAME)
+    corpus_url = (f'{utils.GCS_BASE_URL}{self.config.oss_fuzz_project_name}'
+                  '-backup.clusterfuzz-external.appspot.com/corpus/'
+                  f'libFuzzer/{project_qualified_fuzz_target_name}/'
+                  f'{self.CORPUS_ZIP_NAME}')
 
-    if download_and_unpack_zip(corpus_url, corpus_dir):
-      return corpus_dir
+    if not http_utils.download_and_unpack_zip(corpus_url, corpus_dir):
+      logging.warning('Failed to download corpus for %s.', target_name)
+    return corpus_dir
 
-    return None
+  def upload_coverage(self):
+    """Noop Implementation of upload_coverage_report."""
+    logging.info('Not uploading coverage report because on OSS-Fuzz.')
 
-
-def download_url(url, filename, num_attempts=3):
-  """Downloads the file located at |url|, using HTTP to |filename|.
-
-  Args:
-    url: A url to a file to download.
-    filename: The path the file should be downloaded to.
-    num_retries: The number of times to retry the download on
-       ConnectionResetError.
-
-  Returns:
-    True on success.
-  """
-  sleep_time = 1
-
-  # Don't use retry wrapper since we don't want this to raise any exceptions.
-  for _ in range(num_attempts):
+  def get_coverage(self, repo_path):
+    """Returns the project coverage object for the project."""
     try:
-      urllib.request.urlretrieve(url, filename)
-      return True
-    except urllib.error.HTTPError:
-      # In these cases, retrying probably wont work since the error probably
-      # means there is nothing at the URL to download.
-      logging.error('Unable to download from: %s.', url)
-      return False
-    except ConnectionResetError:
-      # These errors are more likely to be transient. Retry.
-      pass
-    time.sleep(sleep_time)
-
-  logging.error('Failed to download %s, %d times.', url, num_attempts)
-
-  return False
+      return get_coverage.OSSFuzzCoverage(repo_path,
+                                          self.config.oss_fuzz_project_name)
+    except get_coverage.CoverageError:
+      return None
 
 
-def download_and_unpack_zip(url, extract_directory):
-  """Downloads and unpacks a zip file from an HTTP URL.
+class NoClusterFuzzDeployment(BaseClusterFuzzDeployment):
+  """ClusterFuzzDeployment implementation used when there is no deployment of
+  ClusterFuzz to use."""
 
-  Args:
-    url: A url to the zip file to be downloaded and unpacked.
-    out_dir: The path where the zip file should be extracted to.
+  def upload_build(self, commit):  # pylint: disable=no-self-use
+    """Noop Implementation of upload_build."""
+    logging.info('Not uploading latest build because no ClusterFuzz '
+                 'deployment.')
 
-  Returns:
-    True on success.
-  """
-  if not os.path.exists(extract_directory):
-    logging.error('Extract directory: %s does not exist.', extract_directory)
-    return False
+  def upload_corpus(self, target_name, corpus_dir, replace=False):  # pylint: disable=no-self-use,unused-argument
+    """Noop Implementation of upload_corpus."""
+    logging.info('Not uploading corpus because no ClusterFuzz deployment.')
 
-  # Gives the temporary zip file a unique identifier in the case that
-  # that download_and_unpack_zip is done in parallel.
-  with tempfile.NamedTemporaryFile(suffix='.zip') as tmp_file:
-    if not download_url(url, tmp_file.name):
-      return False
+  def upload_crashes(self):  # pylint: disable=no-self-use
+    """Noop Implementation of upload_crashes."""
+    logging.info('Not uploading crashes because no ClusterFuzz deployment.')
 
-    try:
-      with zipfile.ZipFile(tmp_file.name, 'r') as zip_file:
-        zip_file.extractall(extract_directory)
-    except zipfile.BadZipFile:
-      logging.error('Error unpacking zip from %s. Bad Zipfile.', url)
-      return False
+  def download_corpus(self, target_name, corpus_dir):
+    """Noop Implementation of download_corpus."""
+    logging.info('Not downloading corpus because no ClusterFuzz deployment.')
+    return _make_empty_dir_if_nonexistent(corpus_dir)
 
-  return True
+  def download_latest_build(self):  # pylint: disable=no-self-use
+    """Noop Implementation of download_latest_build."""
+    logging.info(
+        'Not downloading latest build because no ClusterFuzz deployment.')
+
+  def upload_coverage(self):
+    """Noop Implementation of upload_coverage."""
+    logging.info(
+        'Not uploading coverage report because no ClusterFuzz deployment.')
+
+  def get_coverage(self, repo_path):
+    """Noop Implementation of get_coverage."""
+    logging.info(
+        'Not getting project coverage because no ClusterFuzz deployment.')
 
 
-def get_clusterfuzz_deployment(config):
+_PLATFORM_CLUSTERFUZZ_DEPLOYMENT_MAPPING = {
+    config_utils.BaseConfig.Platform.INTERNAL_GENERIC_CI:
+        OSSFuzz,
+    config_utils.BaseConfig.Platform.INTERNAL_GITHUB:
+        OSSFuzz,
+    config_utils.BaseConfig.Platform.EXTERNAL_GENERIC_CI:
+        NoClusterFuzzDeployment,
+    config_utils.BaseConfig.Platform.EXTERNAL_GITHUB:
+        ClusterFuzzLite,
+}
+
+
+def get_clusterfuzz_deployment(config, workspace):
   """Returns object reprsenting deployment of ClusterFuzz used by |config|."""
-  if (config.platform == config.Platform.INTERNAL_GENERIC_CI or
-      config.platform == config.Platform.INTERNAL_GITHUB):
-    logging.info('Using OSS-Fuzz as ClusterFuzz deployment.')
-    return OSSFuzz(config)
-  logging.info('Using ClusterFuzzLite as ClusterFuzz deployment.')
-  return ClusterFuzzLite(config)
+  deployment_cls = _PLATFORM_CLUSTERFUZZ_DEPLOYMENT_MAPPING[config.platform]
+  result = deployment_cls(config, workspace)
+  logging.info('ClusterFuzzDeployment: %s.', result)
+  return result
diff --git a/infra/cifuzz/clusterfuzz_deployment_test.py b/infra/cifuzz/clusterfuzz_deployment_test.py
index 06ff784..2476785 100644
--- a/infra/cifuzz/clusterfuzz_deployment_test.py
+++ b/infra/cifuzz/clusterfuzz_deployment_test.py
@@ -16,12 +16,14 @@
 import os
 import unittest
 from unittest import mock
-import urllib.error
 
+import parameterized
 from pyfakefs import fake_filesystem_unittest
 
 import clusterfuzz_deployment
 import config_utils
+import test_helpers
+import workspace_utils
 
 # NOTE: This integration test relies on
 # https://github.com/google/oss-fuzz/tree/master/projects/example project.
@@ -30,62 +32,60 @@
 # An example fuzzer that triggers an error.
 EXAMPLE_FUZZER = 'example_crash_fuzzer'
 
+WORKSPACE = '/workspace'
+EXPECTED_LATEST_BUILD_PATH = os.path.join(WORKSPACE, 'cifuzz-prev-build')
+
+# pylint: disable=unused-argument
+
 
 def _create_config(**kwargs):
   """Creates a config object and then sets every attribute that is a key in
   |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an
   attribute of Config."""
-  defaults = {'is_github': True, 'project_name': EXAMPLE_PROJECT}
+  defaults = {
+      'is_github': True,
+      'oss_fuzz_project_name': EXAMPLE_PROJECT,
+      'workspace': WORKSPACE,
+  }
   for default_key, default_value in defaults.items():
     if default_key not in kwargs:
       kwargs[default_key] = default_value
 
-  with mock.patch('os.path.basename', return_value=None), mock.patch(
-      'config_utils.get_project_src_path',
-      return_value=None), mock.patch('config_utils._is_dry_run',
-                                     return_value=True):
-    config = config_utils.RunFuzzersConfig()
-
-  for key, value in kwargs.items():
-    assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
-    setattr(config, key, value)
-  return config
+  return test_helpers.create_run_config(**kwargs)
 
 
 def _create_deployment(**kwargs):
   config = _create_config(**kwargs)
-  return clusterfuzz_deployment.get_clusterfuzz_deployment(config)
+  workspace = workspace_utils.Workspace(config)
+  return clusterfuzz_deployment.get_clusterfuzz_deployment(config, workspace)
 
 
 class OSSFuzzTest(fake_filesystem_unittest.TestCase):
   """Tests OSSFuzz."""
 
-  OUT_DIR = '/out'
-
   def setUp(self):
     self.setUpPyfakefs()
     self.deployment = _create_deployment()
+    self.corpus_dir = os.path.join(self.deployment.workspace.corpora,
+                                   EXAMPLE_FUZZER)
 
-  @mock.patch('clusterfuzz_deployment.download_and_unpack_zip',
-              return_value=True)
-  def test_download_corpus(self, mocked_download_and_unpack_zip):
+  @mock.patch('http_utils.download_and_unpack_zip', return_value=True)
+  def test_download_corpus(self, mock_download_and_unpack_zip):
     """Tests that we can download a corpus for a valid project."""
-    result = self.deployment.download_corpus(EXAMPLE_FUZZER, self.OUT_DIR)
-    self.assertIsNotNone(result)
-    expected_corpus_dir = os.path.join(self.OUT_DIR, 'cifuzz-corpus',
-                                       EXAMPLE_FUZZER)
+    self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir)
     expected_url = ('https://storage.googleapis.com/example-backup.'
                     'clusterfuzz-external.appspot.com/corpus/libFuzzer/'
                     'example_crash_fuzzer/public.zip')
-    call_args, _ = mocked_download_and_unpack_zip.call_args
-    self.assertEqual(call_args, (expected_url, expected_corpus_dir))
+    call_args, _ = mock_download_and_unpack_zip.call_args
+    self.assertEqual(call_args, (expected_url, self.corpus_dir))
+    self.assertTrue(os.path.exists(self.corpus_dir))
 
-  @mock.patch('clusterfuzz_deployment.download_and_unpack_zip',
-              return_value=False)
-  def test_download_fail(self, _):
-    """Tests that when downloading fails, None is returned."""
-    corpus_path = self.deployment.download_corpus(EXAMPLE_FUZZER, self.OUT_DIR)
-    self.assertIsNone(corpus_path)
+  @mock.patch('http_utils.download_and_unpack_zip', return_value=False)
+  def test_download_corpus_fail(self, _):
+    """Tests that when downloading fails, an empty corpus directory is still
+    returned."""
+    self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir)
+    self.assertEqual(os.listdir(self.corpus_dir), [])
 
   def test_get_latest_build_name(self):
     """Tests that the latest build name can be retrieved from GCS."""
@@ -93,58 +93,170 @@
     self.assertTrue(latest_build_name.endswith('.zip'))
     self.assertTrue('address' in latest_build_name)
 
+  @parameterized.parameterized.expand([
+      ('upload_build', ('commit',),
+       'Not uploading latest build because on OSS-Fuzz.'),
+      ('upload_corpus', ('target', 'corpus-dir'),
+       'Not uploading corpus because on OSS-Fuzz.'),
+      ('upload_crashes', tuple(), 'Not uploading crashes because on OSS-Fuzz.'),
+  ])
+  def test_noop_methods(self, method, method_args, expected_message):
+    """Tests that certain methods are noops for OSS-Fuzz."""
+    with mock.patch('logging.info') as mock_info:
+      method = getattr(self.deployment, method)
+      self.assertIsNone(method(*method_args))
+      mock_info.assert_called_with(expected_message)
 
-class DownloadUrlTest(unittest.TestCase):
-  """Tests that download_url works."""
-  URL = 'example.com/file'
-  FILE_PATH = '/tmp/file'
+  @mock.patch('http_utils.download_and_unpack_zip', return_value=True)
+  def test_download_latest_build(self, mock_download_and_unpack_zip):
+    """Tests that downloading the latest build works as intended under normal
+    circumstances."""
+    self.assertEqual(self.deployment.download_latest_build(),
+                     EXPECTED_LATEST_BUILD_PATH)
+    expected_url = ('https://storage.googleapis.com/clusterfuzz-builds/example/'
+                    'example-address-202008030600.zip')
+    mock_download_and_unpack_zip.assert_called_with(expected_url,
+                                                    EXPECTED_LATEST_BUILD_PATH)
 
-  @mock.patch('time.sleep')
-  @mock.patch('urllib.request.urlretrieve', return_value=True)
-  def test_download_url_no_error(self, mocked_urlretrieve, _):
-    """Tests that download_url works when there is no error."""
-    self.assertTrue(
-        clusterfuzz_deployment.download_url(self.URL, self.FILE_PATH))
-    self.assertEqual(1, mocked_urlretrieve.call_count)
-
-  @mock.patch('time.sleep')
-  @mock.patch('logging.error')
-  @mock.patch('urllib.request.urlretrieve',
-              side_effect=urllib.error.HTTPError(None, None, None, None, None))
-  def test_download_url_http_error(self, mocked_urlretrieve, mocked_error, _):
-    """Tests that download_url doesn't retry when there is an HTTP error."""
-    self.assertFalse(
-        clusterfuzz_deployment.download_url(self.URL, self.FILE_PATH))
-    mocked_error.assert_called_with('Unable to download from: %s.', self.URL)
-    self.assertEqual(1, mocked_urlretrieve.call_count)
-
-  @mock.patch('time.sleep')
-  @mock.patch('logging.error')
-  @mock.patch('urllib.request.urlretrieve', side_effect=ConnectionResetError)
-  def test_download_url_connection_error(self, mocked_urlretrieve, mocked_error,
-                                         mocked_sleep):
-    """Tests that download_url doesn't retry when there is an HTTP error."""
-    self.assertFalse(
-        clusterfuzz_deployment.download_url(self.URL, self.FILE_PATH))
-    self.assertEqual(3, mocked_urlretrieve.call_count)
-    self.assertEqual(3, mocked_sleep.call_count)
-    mocked_error.assert_called_with('Failed to download %s, %d times.',
-                                    self.URL, 3)
+  @mock.patch('http_utils.download_and_unpack_zip', return_value=False)
+  def test_download_latest_build_fail(self, _):
+    """Tests that download_latest_build returns None when it fails to download a
+    build."""
+    self.assertIsNone(self.deployment.download_latest_build())
 
 
-class DownloadAndUnpackZipTest(fake_filesystem_unittest.TestCase):
-  """Tests download_and_unpack_zip."""
+class ClusterFuzzLiteTest(fake_filesystem_unittest.TestCase):
+  """Tests for ClusterFuzzLite."""
 
   def setUp(self):
     self.setUpPyfakefs()
+    self.deployment = _create_deployment(run_fuzzers_mode='batch',
+                                         oss_fuzz_project_name='',
+                                         is_github=True)
+    self.corpus_dir = os.path.join(self.deployment.workspace.corpora,
+                                   EXAMPLE_FUZZER)
 
-  @mock.patch('urllib.request.urlretrieve', return_value=True)
-  def test_bad_zip_download(self, _):
-    """Tests download_and_unpack_zip returns none when a bad zip is passed."""
-    self.fs.create_file('/url_tmp.zip', contents='Test file.')
-    self.assertFalse(
-        clusterfuzz_deployment.download_and_unpack_zip('/not/a/real/url',
-                                                       '/extract-directory'))
+  @mock.patch('filestore.github_actions.GithubActionsFilestore.download_corpus',
+              return_value=True)
+  def test_download_corpus(self, mock_download_corpus):
+    """Tests that download_corpus works for a valid project."""
+    self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir)
+    mock_download_corpus.assert_called_with('example_crash_fuzzer',
+                                            self.corpus_dir)
+    self.assertTrue(os.path.exists(self.corpus_dir))
+
+  @mock.patch('filestore.github_actions.GithubActionsFilestore.download_corpus',
+              side_effect=Exception)
+  def test_download_corpus_fail(self, _):
+    """Tests that when downloading fails, an empty corpus directory is still
+    returned."""
+    self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir)
+    self.assertEqual(os.listdir(self.corpus_dir), [])
+
+  @mock.patch('filestore.github_actions.GithubActionsFilestore.download_build',
+              side_effect=[False, True])
+  @mock.patch('repo_manager.RepoManager.get_commit_list',
+              return_value=['commit1', 'commit2'])
+  @mock.patch('continuous_integration.BaseCi.repo_dir',
+              return_value='/path/to/repo')
+  def test_download_latest_build(self, mock_repo_dir, mock_get_commit_list,
+                                 mock_download_build):
+    """Tests that downloading the latest build works as intended under normal
+    circumstances."""
+    self.assertEqual(self.deployment.download_latest_build(),
+                     EXPECTED_LATEST_BUILD_PATH)
+    expected_artifact_name = 'address-commit2'
+    mock_download_build.assert_called_with(expected_artifact_name,
+                                           EXPECTED_LATEST_BUILD_PATH)
+
+  @mock.patch('filestore.github_actions.GithubActionsFilestore.download_build',
+              side_effect=Exception)
+  @mock.patch('repo_manager.RepoManager.get_commit_list',
+              return_value=['commit1', 'commit2'])
+  @mock.patch('continuous_integration.BaseCi.repo_dir',
+              return_value='/path/to/repo')
+  def test_download_latest_build_fail(self, mock_repo_dir, mock_get_commit_list,
+                                      _):
+    """Tests that download_latest_build returns None when it fails to download a
+    build."""
+    self.assertIsNone(self.deployment.download_latest_build())
+
+  @mock.patch('filestore.github_actions.GithubActionsFilestore.upload_build')
+  def test_upload_build(self, mock_upload_build):
+    """Tests that upload_build works as intended."""
+    self.deployment.upload_build('commit')
+    mock_upload_build.assert_called_with('address-commit',
+                                         '/workspace/build-out')
+
+
+class NoClusterFuzzDeploymentTest(fake_filesystem_unittest.TestCase):
+  """Tests for NoClusterFuzzDeployment."""
+
+  def setUp(self):
+    self.setUpPyfakefs()
+    config = test_helpers.create_run_config(workspace=WORKSPACE,
+                                            is_github=False)
+    workspace = workspace_utils.Workspace(config)
+    self.deployment = clusterfuzz_deployment.get_clusterfuzz_deployment(
+        config, workspace)
+    self.corpus_dir = os.path.join(workspace.corpora, EXAMPLE_FUZZER)
+
+  @mock.patch('logging.info')
+  def test_download_corpus(self, mock_info):
+    """Tests that download corpus returns the path to the empty corpus
+    directory."""
+    self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir)
+    mock_info.assert_called_with(
+        'Not downloading corpus because no ClusterFuzz deployment.')
+    self.assertTrue(os.path.exists(self.corpus_dir))
+
+  @parameterized.parameterized.expand([
+      ('upload_build', ('commit',),
+       'Not uploading latest build because no ClusterFuzz deployment.'),
+      ('upload_corpus', ('target', 'corpus-dir'),
+       'Not uploading corpus because no ClusterFuzz deployment.'),
+      ('upload_crashes', tuple(),
+       'Not uploading crashes because no ClusterFuzz deployment.'),
+      ('download_latest_build', tuple(),
+       'Not downloading latest build because no ClusterFuzz deployment.')
+  ])
+  def test_noop_methods(self, method, method_args, expected_message):
+    """Tests that certain methods are noops for NoClusterFuzzDeployment."""
+    with mock.patch('logging.info') as mock_info:
+      method = getattr(self.deployment, method)
+      self.assertIsNone(method(*method_args))
+      mock_info.assert_called_with(expected_message)
+
+
+class GetClusterFuzzDeploymentTest(unittest.TestCase):
+  """Tests for get_clusterfuzz_deployment."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self)
+    os.environ['GITHUB_REPOSITORY'] = 'owner/myproject'
+
+  @parameterized.parameterized.expand([
+      (config_utils.BaseConfig.Platform.INTERNAL_GENERIC_CI,
+       clusterfuzz_deployment.OSSFuzz),
+      (config_utils.BaseConfig.Platform.INTERNAL_GITHUB,
+       clusterfuzz_deployment.OSSFuzz),
+      (config_utils.BaseConfig.Platform.EXTERNAL_GENERIC_CI,
+       clusterfuzz_deployment.NoClusterFuzzDeployment),
+      (config_utils.BaseConfig.Platform.EXTERNAL_GITHUB,
+       clusterfuzz_deployment.ClusterFuzzLite),
+  ])
+  def test_get_clusterfuzz_deployment(self, platform, expected_deployment_cls):
+    """Tests that get_clusterfuzz_deployment returns the correct value."""
+    with mock.patch('config_utils.BaseConfig.platform',
+                    return_value=platform,
+                    new_callable=mock.PropertyMock):
+      with mock.patch('filestore_utils.get_filestore', return_value=None):
+        config = _create_config()
+        workspace = workspace_utils.Workspace(config)
+
+        self.assertIsInstance(
+            clusterfuzz_deployment.get_clusterfuzz_deployment(
+                config, workspace), expected_deployment_cls)
 
 
 if __name__ == '__main__':
diff --git a/infra/cifuzz/config_utils.py b/infra/cifuzz/config_utils.py
index ad2cd36..bc73536 100644
--- a/infra/cifuzz/config_utils.py
+++ b/infra/cifuzz/config_utils.py
@@ -16,55 +16,44 @@
 import logging
 import enum
 import os
+import sys
 import json
 
 import environment
 
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
-def _get_project_repo_name():
-  return os.path.basename(environment.get('GITHUB_REPOSITORY', ''))
+import constants
+
+RUN_FUZZERS_MODES = ['batch', 'ci', 'coverage', 'prune']
+SANITIZERS = ['address', 'memory', 'undefined', 'coverage']
+
+# TODO(metzman): Set these on config objects so there's one source of truth.
+DEFAULT_ENGINE = 'libfuzzer'
+DEFAULT_ARCHITECTURE = 'x86_64'
+
+# This module deals a lot with env variables. Many of these will be set by users
+# and others beyond CIFuzz's control. Thus, you should be careful about using
+# the environment.py helpers for getting env vars, since it can cause values
+# that should be interpreted as strings to be returned as other types (bools or
+# ints for example). The environment.py helpers should not be used for values
+# that are supposed to be strings.
 
 
 def _get_pr_ref(event):
   if event == 'pull_request':
-    return environment.get('GITHUB_REF')
+    return os.getenv('GITHUB_REF')
   return None
 
 
 def _get_sanitizer():
-  return os.getenv('SANITIZER', 'address').lower()
-
-
-def _get_project_name():
-  # TODO(metzman): Remove OSS-Fuzz reference.
-  return os.getenv('OSS_FUZZ_PROJECT_NAME')
+  return os.getenv('SANITIZER', constants.DEFAULT_SANITIZER).lower()
 
 
 def _is_dry_run():
   """Returns True if configured to do a dry run."""
-  return environment.get_bool('DRY_RUN', 'false')
-
-
-def get_project_src_path(workspace):
-  """Returns the manually checked out path of the project's source if specified
-  or None."""
-  # TODO(metzman): Get rid of MANUAL_SRC_PATH when Skia switches to
-  # PROJECT_SRC_PATH.
-  path = os.getenv('PROJECT_SRC_PATH', os.getenv('MANUAL_SRC_PATH'))
-  if not path:
-    logging.debug('No PROJECT_SRC_PATH.')
-    return path
-
-  logging.debug('PROJECT_SRC_PATH set.')
-  if os.path.isabs(path):
-    return path
-
-  # If |src| is not absolute, assume we are running in GitHub actions.
-  # TODO(metzman): Don't make this assumption.
-  return os.path.join(workspace, path)
-
-
-DEFAULT_LANGUAGE = 'c++'
+  return environment.get_bool('DRY_RUN', False)
 
 
 def _get_language():
@@ -74,12 +63,114 @@
   # getting it from the project.yaml) is outweighed by the complexity in
   # implementing this. A lot of the complexity comes from our unittests not
   # setting a proper projet at this point.
-  return os.getenv('LANGUAGE', DEFAULT_LANGUAGE)
+  return os.getenv('LANGUAGE', constants.DEFAULT_LANGUAGE)
 
 
 # pylint: disable=too-few-public-methods,too-many-instance-attributes
 
 
+class BaseCiEnvironment:
+  """Base class for CiEnvironment subclasses."""
+
+  @property
+  def workspace(self):
+    """Returns the workspace."""
+    raise NotImplementedError('Child class must implment method.')
+
+  @property
+  def git_sha(self):
+    """Returns the Git SHA to diff against."""
+    raise NotImplementedError('Child class must implment method.')
+
+  @property
+  def token(self):
+    """Returns the CI API token."""
+    raise NotImplementedError('Child class must implment method.')
+
+  @property
+  def project_src_path(self):
+    """Returns the manually checked out path of the project's source if
+    specified or None."""
+
+    path = os.getenv('PROJECT_SRC_PATH')
+    if not path:
+      logging.debug('No PROJECT_SRC_PATH.')
+      return path
+
+    logging.debug('PROJECT_SRC_PATH set: %s.', path)
+    return path
+
+
+class GenericCiEnvironment(BaseCiEnvironment):
+  """CI Environment for generic CI systems."""
+
+  @property
+  def workspace(self):
+    """Returns the workspace."""
+    return os.getenv('WORKSPACE')
+
+  @property
+  def git_sha(self):
+    """Returns the Git SHA to diff against."""
+    return os.getenv('GIT_SHA')
+
+  @property
+  def token(self):
+    """Returns the CI API token."""
+    return os.getenv('TOKEN')
+
+  @property
+  def project_repo_owner_and_name(self):
+    """Returns a tuple containing the project repo owner and None."""
+    repository = os.getenv('REPOSITORY')
+    # Repo owner is a githubism.
+    return None, repository
+
+
+class GithubEnvironment(BaseCiEnvironment):
+  """CI environment for GitHub."""
+
+  @property
+  def workspace(self):
+    """Returns the workspace."""
+    return os.getenv('GITHUB_WORKSPACE')
+
+  @property
+  def git_sha(self):
+    """Returns the Git SHA to diff against."""
+    return os.getenv('GITHUB_SHA')
+
+  @property
+  def token(self):
+    """Returns the CI API token."""
+    return os.getenv('GITHUB_TOKEN')
+
+  @property
+  def project_src_path(self):
+    """Returns the manually checked out path of the project's source if
+    specified or None. The path returned is relative to |self.workspace| since
+    on github the checkout will be relative to there."""
+    # On GitHub, they don't know the absolute path, it is relative to
+    # |workspace|.
+    project_src_path = super().project_src_path
+    if project_src_path is None:
+      return project_src_path
+    return os.path.join(self.workspace, project_src_path)
+
+  @property
+  def project_repo_owner_and_name(self):
+    """Returns a tuple containing the project repo owner and the name of the
+    repo."""
+    # On GitHub this includes owner and repo name.
+    repository = os.getenv('GITHUB_REPOSITORY')
+    # Use os.path.split to split owner from repo.
+    return os.path.split(repository)
+
+
+class ConfigError(Exception):
+  """Error for invalid configuration."""
+
+
 class BaseConfig:
   """Object containing constant configuration for CIFuzz."""
 
@@ -88,66 +179,144 @@
     EXTERNAL_GITHUB = 0  # Non-OSS-Fuzz on GitHub actions.
     INTERNAL_GITHUB = 1  # OSS-Fuzz on GitHub actions.
     INTERNAL_GENERIC_CI = 2  # OSS-Fuzz on any CI.
+    EXTERNAL_GENERIC_CI = 3  # Non-OSS-Fuzz on any CI.
 
   def __init__(self):
-    self.workspace = os.getenv('GITHUB_WORKSPACE')
-    self.project_name = _get_project_name()
+    # Need to set these before calling self.platform.
+    self._github_event_path = os.getenv('GITHUB_EVENT_PATH')
+    self.is_github = bool(self._github_event_path)
+    logging.debug('Is github: %s.', self.is_github)
+    self.oss_fuzz_project_name = os.getenv('OSS_FUZZ_PROJECT_NAME')
+
+    self._ci_env = _get_ci_environment(self.platform)
+    self.workspace = self._ci_env.workspace
+
+    self.project_repo_owner, self.project_repo_name = (
+        self._ci_env.project_repo_owner_and_name)
+
     # Check if failures should not be reported.
     self.dry_run = _is_dry_run()
+
     self.sanitizer = _get_sanitizer()
-    self.build_integration_path = os.getenv('BUILD_INTEGRATION_PATH')
+
+    self.build_integration_path = (
+        constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH)
     self.language = _get_language()
-    event_path = os.getenv('GITHUB_EVENT_PATH')
-    self.is_github = bool(event_path)
-    logging.debug('Is github: %s.', self.is_github)
-    # TODO(metzman): Parse env like we do in ClusterFuzz.
-    self.low_disk_space = environment.get('LOW_DISK_SPACE', False)
+    self.low_disk_space = environment.get_bool('LOW_DISK_SPACE', False)
+
+    self.token = self._ci_env.token
+    self.git_store_repo = os.environ.get('GIT_STORE_REPO')
+    self.git_store_branch = os.environ.get('GIT_STORE_BRANCH')
+    self.git_store_branch_coverage = os.environ.get('GIT_STORE_BRANCH_COVERAGE',
+                                                    self.git_store_branch)
+    self.docker_in_docker = os.environ.get('DOCKER_IN_DOCKER')
+
+    # TODO(metzman): Fix tests to create valid configurations and get rid of
+    # CIFUZZ_TEST here and in presubmit.py.
+    if not os.getenv('CIFUZZ_TEST') and not self.validate():
+      raise ConfigError('Invalid Configuration.')
+
+  def validate(self):
+    """Returns False if the configuration is invalid."""
+    # Do validation here so that unittests don't need to make a fully-valid
+    # config.
+    if not self.workspace:
+      logging.error('Must set WORKSPACE.')
+      return False
+
+    if self.sanitizer not in SANITIZERS:
+      logging.error('Invalid SANITIZER: %s. Must be one of: %s.',
+                    self.sanitizer, SANITIZERS)
+      return False
+
+    if self.language not in constants.LANGUAGES:
+      logging.error('Invalid LANGUAGE: %s. Must be one of: %s.', self.language,
+                    constants.LANGUAGES)
+      return False
+
+    return True
 
   @property
   def is_internal(self):
     """Returns True if this is an OSS-Fuzz project."""
-    return not self.build_integration_path
+    return bool(self.oss_fuzz_project_name)
 
   @property
   def platform(self):
     """Returns the platform CIFuzz is runnning on."""
     if not self.is_internal:
+      if not self.is_github:
+        return self.Platform.EXTERNAL_GENERIC_CI
       return self.Platform.EXTERNAL_GITHUB
+
     if self.is_github:
       return self.Platform.INTERNAL_GITHUB
     return self.Platform.INTERNAL_GENERIC_CI
 
+  @property
+  def is_coverage(self):
+    """Returns True if this CIFuzz run (building fuzzers and running them) for
+    generating a coverage report."""
+    return self.sanitizer == 'coverage'
+
+
+_CI_ENVIRONMENT_MAPPING = {
+    BaseConfig.Platform.EXTERNAL_GITHUB: GithubEnvironment,
+    BaseConfig.Platform.INTERNAL_GITHUB: GithubEnvironment,
+    BaseConfig.Platform.INTERNAL_GENERIC_CI: GenericCiEnvironment,
+    BaseConfig.Platform.EXTERNAL_GENERIC_CI: GenericCiEnvironment,
+}
+
+
+def _get_ci_environment(platform):
+  """Returns the CI environment object for |platform|."""
+  return _CI_ENVIRONMENT_MAPPING[platform]()
+
 
 class RunFuzzersConfig(BaseConfig):
   """Class containing constant configuration for running fuzzers in CIFuzz."""
 
-  RUN_FUZZERS_MODES = {'batch', 'ci'}
-
   def __init__(self):
     super().__init__()
+    # TODO(metzman): Pick a better default for pruning.
     self.fuzz_seconds = int(os.environ.get('FUZZ_SECONDS', 600))
     self.run_fuzzers_mode = os.environ.get('RUN_FUZZERS_MODE', 'ci').lower()
-    if self.run_fuzzers_mode not in self.RUN_FUZZERS_MODES:
-      raise Exception(
-          ('Invalid RUN_FUZZERS_MODE %s not one of allowed choices: %s.' %
-           self.run_fuzzers_mode, self.RUN_FUZZERS_MODES))
+    if self.is_coverage:
+      self.run_fuzzers_mode = 'coverage'
+
+    self.report_unreproducible_crashes = environment.get_bool(
+        'REPORT_UNREPRODUCIBLE_CRASHES', False)
+
+    # TODO(metzman): Fix tests to create valid configurations and get rid of
+    # CIFUZZ_TEST here and in presubmit.py.
+    if not os.getenv('CIFUZZ_TEST') and not self._run_config_validate():
+      raise ConfigError('Invalid Run Configuration.')
+
+  def _run_config_validate(self):
+    """Do extra validation on RunFuzzersConfig.__init__(). Do not name this
+    validate or else it will be called when using the parent's __init__ and will
+    fail. Returns True if valid."""
+    if self.run_fuzzers_mode not in RUN_FUZZERS_MODES:
+      logging.error('Invalid RUN_FUZZERS_MODE: %s. Must be one of %s.',
+                    self.run_fuzzers_mode, RUN_FUZZERS_MODES)
+      return False
+
+    return True
 
 
 class BuildFuzzersConfig(BaseConfig):
   """Class containing constant configuration for building fuzzers in CIFuzz."""
 
   def _get_config_from_event_path(self, event):
-    event_path = os.getenv('GITHUB_EVENT_PATH')
-    if not event_path:
+    if not self._github_event_path:
       return
-    with open(event_path, encoding='utf-8') as file_handle:
+    with open(self._github_event_path, encoding='utf-8') as file_handle:
       event_data = json.load(file_handle)
     if event == 'push':
       self.base_commit = event_data['before']
       logging.debug('base_commit: %s', self.base_commit)
-    else:
-      self.pr_ref = 'refs/pull/{0}/merge'.format(
-          event_data['pull_request']['number'])
+    elif event == 'pull_request':
+      self.pr_ref = f'refs/pull/{event_data["pull_request"]["number"]}/merge'
       logging.debug('pr_ref: %s', self.pr_ref)
 
     self.git_url = event_data['repository']['html_url']
@@ -155,11 +324,8 @@
   def __init__(self):
     """Get the configuration from CIFuzz from the environment. These variables
     are set by GitHub or the user."""
-    # TODO(metzman): Some of this config is very CI-specific. Move it into the
-    # CI class.
     super().__init__()
-    self.project_repo_name = _get_project_repo_name()
-    self.commit_sha = os.getenv('GITHUB_SHA')
+    self.commit_sha = self._ci_env.git_sha
     event = os.getenv('GITHUB_EVENT_NAME')
 
     self.pr_ref = None
@@ -168,13 +334,21 @@
     self._get_config_from_event_path(event)
 
     self.base_ref = os.getenv('GITHUB_BASE_REF')
-    self.project_src_path = get_project_src_path(self.workspace)
+    self.project_src_path = self._ci_env.project_src_path
 
     self.allowed_broken_targets_percentage = os.getenv(
         'ALLOWED_BROKEN_TARGETS_PERCENTAGE')
-    self.bad_build_check = environment.get_bool('BAD_BUILD_CHECK', 'true')
+    self.bad_build_check = environment.get_bool('BAD_BUILD_CHECK', True)
+    # pylint: disable=consider-using-ternary
+    self.keep_unaffected_fuzz_targets = (
+        # Not from a commit or PR.
+        (not self.base_ref and not self.base_commit) or
+        environment.get_bool('KEEP_UNAFFECTED_FUZZERS'))
+    self.upload_build = environment.get_bool('UPLOAD_BUILD', False)
+    if self.upload_build:
+      logging.info('Keeping all fuzzers because we are uploading build.')
+      self.keep_unaffected_fuzz_targets = True
 
-    # TODO(metzman): Use better system for interpreting env vars. What if env
-    # var is set to '0'?
-    self.keep_unaffected_fuzz_targets = bool(
-        os.getenv('KEEP_UNAFFECTED_FUZZERS'))
+    if self.sanitizer == 'coverage':
+      self.keep_unaffected_fuzz_targets = True
+      self.bad_build_check = False
diff --git a/infra/cifuzz/config_utils_test.py b/infra/cifuzz/config_utils_test.py
index 6f87bd4..32499bf 100644
--- a/infra/cifuzz/config_utils_test.py
+++ b/infra/cifuzz/config_utils_test.py
@@ -14,11 +14,13 @@
 """Module for getting the configuration CIFuzz needs to run."""
 import os
 import unittest
+from unittest import mock
 
 import config_utils
+import constants
 import test_helpers
 
-# pylint: disable=no-self-use
+# pylint: disable=no-self-use,protected-access
 
 
 class BaseConfigTest(unittest.TestCase):
@@ -32,18 +34,66 @@
 
   def test_language_default(self):
     """Tests that the correct default language is set."""
-    os.environ['BUILD_INTEGRATION_PATH'] = '/path'
     config = self._create_config()
     self.assertEqual(config.language, 'c++')
 
   def test_language(self):
     """Tests that the correct language is set."""
-    os.environ['BUILD_INTEGRATION_PATH'] = '/path'
     language = 'python'
     os.environ['LANGUAGE'] = language
     config = self._create_config()
     self.assertEqual(config.language, language)
 
+  def test_is_coverage(self):
+    """Tests that is_coverage is set correctly."""
+    # Test it is set when it is supposed to be.
+    os.environ['SANITIZER'] = 'coverage'
+    config = self._create_config()
+    self.assertTrue(config.is_coverage)
+
+    # Test it is not set when it is not supposed to be.
+    os.environ['SANITIZER'] = 'address'
+    config = self._create_config()
+    self.assertFalse(config.is_coverage)
+
+  @mock.patch('logging.error')
+  def test_validate_no_workspace(self, mock_error):
+    """Tests that validate returns False if GITHUB_WORKSPACE isn't set."""
+    os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example'
+    config = self._create_config()
+    self.assertFalse(config.validate())
+    mock_error.assert_called_with('Must set WORKSPACE.')
+
+  @mock.patch('logging.error')
+  def test_validate_invalid_language(self, mock_error):
+    """Tests that validate returns False if GITHUB_WORKSPACE isn't set."""
+    os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example'
+    os.environ['WORKSPACE'] = '/workspace'
+    os.environ['LANGUAGE'] = 'invalid-language'
+    config = self._create_config()
+    self.assertFalse(config.validate())
+    mock_error.assert_called_with('Invalid LANGUAGE: %s. Must be one of: %s.',
+                                  os.environ['LANGUAGE'], constants.LANGUAGES)
+
+  @mock.patch('logging.error')
+  def test_validate_invalid_sanitizer(self, mock_error):
+    """Tests that validate returns False if GITHUB_WORKSPACE isn't set."""
+    os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example'
+    os.environ['WORKSPACE'] = '/workspace'
+    os.environ['SANITIZER'] = 'invalid-sanitizer'
+    config = self._create_config()
+    self.assertFalse(config.validate())
+    mock_error.assert_called_with('Invalid SANITIZER: %s. Must be one of: %s.',
+                                  os.environ['SANITIZER'],
+                                  config_utils.SANITIZERS)
+
+  def test_validate(self):
+    """Tests that validate returns True if config is valid."""
+    os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example'
+    os.environ['WORKSPACE'] = '/workspace'
+    config = self._create_config()
+    self.assertTrue(config.validate())
+
 
 class BuildFuzzersConfigTest(unittest.TestCase):
   """Tests for BuildFuzzersConfig."""
@@ -61,11 +111,151 @@
     config = self._create_config()
     self.assertEqual(config.base_ref, expected_base_ref)
 
-  def test_keep_unaffected_defaults_to_false(self):
-    """Tests that keep_unaffected_fuzz_targets defaults to false."""
+  def test_keep_unaffected_defaults_to_true(self):
+    """Tests that keep_unaffected_fuzz_targets defaults to true."""
+    config = self._create_config()
+    self.assertTrue(config.keep_unaffected_fuzz_targets)
+
+  def test_keep_unaffected_defaults_to_false_when_pr(self):
+    """Tests that keep_unaffected_fuzz_targets defaults to false when from a
+    pr."""
+    os.environ['GITHUB_BASE_REF'] = 'base-ref'
     config = self._create_config()
     self.assertFalse(config.keep_unaffected_fuzz_targets)
 
 
+class RunFuzzersConfigTest(unittest.TestCase):
+  """Tests for RunFuzzersConfig."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self)
+
+  def _create_config(self):
+    return config_utils.RunFuzzersConfig()
+
+  def test_coverage(self):
+    """Tests that run_fuzzers_mode is overriden properly based on
+    is_coverage."""
+    # Test that it is overriden when it is supposed to be.
+    os.environ['SANITIZER'] = 'coverage'
+    os.environ['RUN_FUZZERS_MODE'] = 'ci'
+    config = self._create_config()
+    self.assertEqual(config.run_fuzzers_mode, 'coverage')
+
+    # Test that it isn't overriden when it isn't supposed to be.
+    os.environ['SANITIZER'] = 'address'
+    run_fuzzers_mode = 'ci'
+    os.environ['RUN_FUZZERS_MODE'] = run_fuzzers_mode
+    config = self._create_config()
+    self.assertEqual(config.run_fuzzers_mode, run_fuzzers_mode)
+
+  def test_run_config_validate(self):
+    """Tests that _run_config_validate returns True when the config is valid."""
+    self.assertTrue(self._create_config()._run_config_validate())
+
+  @mock.patch('logging.error')
+  def test_run_config_invalid_mode(self, mock_error):
+    """Tests that _run_config_validate returns False when run_fuzzers_mode is
+    invalid."""
+    fake_mode = 'fake-mode'
+    os.environ['RUN_FUZZERS_MODE'] = fake_mode
+    self.assertFalse(self._create_config()._run_config_validate())
+    mock_error.assert_called_with(
+        'Invalid RUN_FUZZERS_MODE: %s. Must be one of %s.', fake_mode,
+        config_utils.RUN_FUZZERS_MODES)
+
+
+class GetProjectRepoOwnerAndNameTest(unittest.TestCase):
+  """Tests for BaseCiEnv.get_project_repo_owner_and_name."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self)
+    self.repo_owner = 'repo-owner'
+    self.repo_name = 'repo-name'
+    self.github_env = config_utils.GithubEnvironment()
+    self.generic_ci_env = config_utils.GenericCiEnvironment()
+
+  def test_unset_repository(self):
+    """Tests that the correct result is returned when repository is not set."""
+    self.assertEqual(self.generic_ci_env.project_repo_owner_and_name,
+                     (None, None))
+
+  def test_empty_repository(self):
+    """Tests that the correct result is returned when repository is an empty
+    string."""
+    os.environ['REPOSITORY'] = ''
+    self.assertEqual(self.generic_ci_env.project_repo_owner_and_name,
+                     (None, ''))
+
+  def test_github_repository(self):
+    """Tests that the correct result is returned when repository contains the
+    owner and repo name (as it does on GitHub)."""
+    os.environ['GITHUB_REPOSITORY'] = f'{self.repo_owner}/{self.repo_name}'
+    self.assertEqual(self.github_env.project_repo_owner_and_name,
+                     (self.repo_owner, self.repo_name))
+
+  def test_nongithub_repository(self):
+    """Tests that the correct result is returned when repository contains the
+    just the repo name (as it does outside of GitHub)."""
+    os.environ['REPOSITORY'] = self.repo_name
+    self.assertEqual(self.generic_ci_env.project_repo_owner_and_name,
+                     (None, self.repo_name))
+
+
+class GetSanitizerTest(unittest.TestCase):
+  """Tests for _get_sanitizer."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self)
+    self.sanitizer = 'memory'
+
+  def test_default_value(self):
+    """Tests that the default value returned by _get_sanitizer is correct."""
+    self.assertEqual(config_utils._get_sanitizer(), 'address')
+
+  def test_normal_case(self):
+    """Tests that _get_sanitizer returns the correct value in normal cases."""
+    os.environ['SANITIZER'] = self.sanitizer
+    self.assertEqual(config_utils._get_sanitizer(), self.sanitizer)
+
+  def test_capitalization(self):
+    """Tests that that _get_sanitizer handles capitalization properly."""
+    os.environ['SANITIZER'] = self.sanitizer.upper()
+    self.assertEqual(config_utils._get_sanitizer(), self.sanitizer)
+
+
+class ProjectSrcPathTest(unittest.TestCase):
+  """Tests for project_src_path."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self)
+    self.workspace = '/workspace'
+    os.environ['GITHUB_WORKSPACE'] = self.workspace
+
+    self.project_src_dir_name = 'project-src'
+
+  def test_unset(self):
+    """Tests that project_src_path returns None when no PROJECT_SRC_PATH is
+    set."""
+    github_env = config_utils.GithubEnvironment()
+    self.assertIsNone(github_env.project_src_path)
+
+  def test_github(self):
+    """Tests that project_src_path returns the correct result on GitHub."""
+    os.environ['PROJECT_SRC_PATH'] = self.project_src_dir_name
+    expected_project_src_path = os.path.join(self.workspace,
+                                             self.project_src_dir_name)
+    github_env = config_utils.GithubEnvironment()
+    self.assertEqual(github_env.project_src_path, expected_project_src_path)
+
+  def test_not_github(self):
+    """Tests that project_src_path returns the correct result not on
+    GitHub."""
+    project_src_path = os.path.join('/', self.project_src_dir_name)
+    os.environ['PROJECT_SRC_PATH'] = project_src_path
+    generic_ci_env = config_utils.GenericCiEnvironment()
+    self.assertEqual(generic_ci_env.project_src_path, project_src_path)
+
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/infra/cifuzz/continuous_integration.py b/infra/cifuzz/continuous_integration.py
index b2e8af2..47c4a7c 100644
--- a/infra/cifuzz/continuous_integration.py
+++ b/infra/cifuzz/continuous_integration.py
@@ -21,16 +21,21 @@
 # pylint: disable=wrong-import-position,import-error
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 import build_specified_commit
+import docker
 import helper
 import repo_manager
 import retry
 import utils
+import workspace_utils
 
 # pylint: disable=too-few-public-methods
 
 BuildPreparationResult = collections.namedtuple(
     'BuildPreparationResult', ['success', 'image_repo_path', 'repo_manager'])
 
+_IMAGE_BUILD_TRIES = 3
+_IMAGE_BUILD_BACKOFF = 2
+
 
 def fix_git_repo_for_diff(repo_manager_obj):
   """Fixes git repos cloned by the "checkout" action so that diffing works on
@@ -47,16 +52,34 @@
 
   def __init__(self, config):
     self.config = config
+    self.workspace = workspace_utils.Workspace(config)
+
+  def repo_dir(self):
+    """Returns the source repo path, if it has been checked out. None is
+    returned otherwise."""
+    if not os.path.exists(self.workspace.repo_storage):
+      return None
+
+    # Note: this assumes there is only one repo checked out here.
+    listing = os.listdir(self.workspace.repo_storage)
+    if len(listing) != 1:
+      raise RuntimeError('Invalid repo storage.')
+
+    repo_path = os.path.join(self.workspace.repo_storage, listing[0])
+    if not os.path.isdir(repo_path):
+      raise RuntimeError('Repo is not a directory.')
+
+    return repo_path
 
   def prepare_for_fuzzer_build(self):
     """Builds the fuzzer builder image and gets the source code we need to
     fuzz."""
-    raise NotImplementedError('Children must implement this method.')
+    raise NotImplementedError('Child class must implement method.')
 
   def get_diff_base(self):
     """Returns the base to diff against with git to get the change under
     test."""
-    raise NotImplementedError('Children must implement this method.')
+    raise NotImplementedError('Child class must implement method.')
 
   def get_changed_code_under_test(self, repo_manager_obj):
     """Returns the changed files that need to be tested."""
@@ -65,10 +88,38 @@
     logging.info('Diffing against %s.', base)
     return repo_manager_obj.get_git_diff(base)
 
+  def get_build_command(self, host_repo_path, image_repo_path):
+    """Returns the command for building the project that is run inside the
+    project builder container."""
+    raise NotImplementedError('Child class must implement method.')
+
+
+def get_build_command():
+  """Returns the command to build the project inside the project builder
+  container."""
+  return 'compile'
+
+
+def get_replace_repo_and_build_command(host_repo_path, image_repo_path):
+  """Returns the command to replace the repo located at |image_repo_path| with
+  |host_repo_path| and build the project inside the project builder
+  container."""
+  rm_path = os.path.join(image_repo_path, '*')
+  image_src_path = os.path.dirname(image_repo_path)
+  build_command = get_build_command()
+  command = (f'cd / && rm -rf {rm_path} && cp -r {host_repo_path} '
+             f'{image_src_path} && cd - && {build_command}')
+  return command
+
 
 def get_ci(config):
   """Determines what kind of CI is being used and returns the object
   representing that system."""
+
+  if config.platform == config.Platform.EXTERNAL_GENERIC_CI:
+    # Non-OSS-Fuzz projects must bring their own source and their own build
+    # integration (which is relative to that source).
+    return ExternalGeneric(config)
   if config.platform == config.Platform.EXTERNAL_GITHUB:
     # Non-OSS-Fuzz projects must bring their own source and their own build
     # integration (which is relative to that source).
@@ -127,27 +178,35 @@
     assert self.config.pr_ref or self.config.commit_sha
     # detect_main_repo builds the image as a side effect.
     inferred_url, image_repo_path = (build_specified_commit.detect_main_repo(
-        self.config.project_name, repo_name=self.config.project_repo_name))
+        self.config.oss_fuzz_project_name,
+        repo_name=self.config.project_repo_name))
 
     if not inferred_url or not image_repo_path:
-      logging.error('Could not detect repo from project %s.',
-                    self.config.project_name)
-      return BuildPreparationResult(False, None, None)
+      logging.error('Could not detect repo.')
+      return BuildPreparationResult(success=False,
+                                    image_repo_path=None,
+                                    repo_manager=None)
 
-    git_workspace = os.path.join(self.config.workspace, 'storage')
-    os.makedirs(git_workspace, exist_ok=True)
+    os.makedirs(self.workspace.repo_storage, exist_ok=True)
 
     # Use the same name used in the docker image so we can overwrite it.
     image_repo_name = os.path.basename(image_repo_path)
 
     # Checkout project's repo in the shared volume.
-    manager = repo_manager.clone_repo_and_get_manager(inferred_url,
-                                                      git_workspace,
-                                                      repo_name=image_repo_name)
+    manager = repo_manager.clone_repo_and_get_manager(
+        inferred_url, self.workspace.repo_storage, repo_name=image_repo_name)
     checkout_specified_commit(manager, self.config.pr_ref,
                               self.config.commit_sha)
 
-    return BuildPreparationResult(True, image_repo_path, manager)
+    return BuildPreparationResult(success=True,
+                                  image_repo_path=image_repo_path,
+                                  repo_manager=manager)
+
+  def get_build_command(self, host_repo_path, image_repo_path):  # pylint: disable=no-self-use
+    """Returns the command for building the project that is run inside the
+    project builder container. Command also replaces |image_repo_path| with
+    |host_repo_path|."""
+    return get_replace_repo_and_build_command(host_repo_path, image_repo_path)
 
 
 class InternalGeneric(BaseCi):
@@ -162,35 +221,71 @@
     logging.info('Building OSS-Fuzz project.')
     # detect_main_repo builds the image as a side effect.
     _, image_repo_path = (build_specified_commit.detect_main_repo(
-        self.config.project_name, repo_name=self.config.project_repo_name))
+        self.config.oss_fuzz_project_name,
+        repo_name=self.config.project_repo_name))
 
     if not image_repo_path:
-      logging.error('Could not detect repo from project %s.',
-                    self.config.project_name)
-      return BuildPreparationResult(False, None, None)
+      logging.error('Could not detect repo.')
+      return BuildPreparationResult(success=False,
+                                    image_repo_path=None,
+                                    repo_manager=None)
 
     manager = repo_manager.RepoManager(self.config.project_src_path)
-    return BuildPreparationResult(True, image_repo_path, manager)
+    return BuildPreparationResult(success=True,
+                                  image_repo_path=image_repo_path,
+                                  repo_manager=manager)
 
   def get_diff_base(self):
     return 'origin...'
 
-
-_IMAGE_BUILD_TRIES = 3
-_IMAGE_BUILD_BACKOFF = 2
+  def get_build_command(self, host_repo_path, image_repo_path):  # pylint: disable=no-self-use
+    """Returns the command for building the project that is run inside the
+    project builder container. Command also replaces |image_repo_path| with
+    |host_repo_path|."""
+    return get_replace_repo_and_build_command(host_repo_path, image_repo_path)
 
 
 @retry.wrap(_IMAGE_BUILD_TRIES, _IMAGE_BUILD_BACKOFF)
-def build_external_project_docker_image(project_name, project_src,
-                                        build_integration_path):
+def build_external_project_docker_image(project_src, build_integration_path):
   """Builds the project builder image for an external (non-OSS-Fuzz) project.
   Returns True on success."""
   dockerfile_path = os.path.join(build_integration_path, 'Dockerfile')
-  tag = 'gcr.io/oss-fuzz/{project_name}'.format(project_name=project_name)
-  command = ['-t', tag, '-f', dockerfile_path, project_src]
+  command = [
+      '-t', docker.EXTERNAL_PROJECT_IMAGE, '-f', dockerfile_path, project_src
+  ]
   return helper.docker_build(command)
 
 
+class ExternalGeneric(BaseCi):
+  """CI implementation for generic CI for external (non-OSS-Fuzz) projects."""
+
+  def get_diff_base(self):
+    return 'origin...'
+
+  def prepare_for_fuzzer_build(self):
+    logging.info('ExternalGeneric: preparing for fuzzer build.')
+    manager = repo_manager.RepoManager(self.config.project_src_path)
+    build_integration_abs_path = os.path.join(
+        manager.repo_dir, self.config.build_integration_path)
+    if not build_external_project_docker_image(manager.repo_dir,
+                                               build_integration_abs_path):
+      logging.error('Failed to build external project: %s.',
+                    self.config.oss_fuzz_project_name)
+      return BuildPreparationResult(success=False,
+                                    image_repo_path=None,
+                                    repo_manager=None)
+
+    image_repo_path = os.path.join('/src', self.config.project_repo_name)
+    return BuildPreparationResult(success=True,
+                                  image_repo_path=image_repo_path,
+                                  repo_manager=manager)
+
+  def get_build_command(self, host_repo_path, image_repo_path):  # pylint: disable=no-self-use
+    """Returns the command for building the project that is run inside the
+    project builder container."""
+    return get_build_command()
+
+
 class ExternalGithub(GithubCiMixin, BaseCi):
   """Class representing CI for a non-OSS-Fuzz project on Github Actions."""
 
@@ -200,24 +295,32 @@
     projects are expected to bring their own source code to CIFuzz. Returns True
     on success."""
     logging.info('Building external project.')
-    git_workspace = os.path.join(self.config.workspace, 'storage')
-    os.makedirs(git_workspace, exist_ok=True)
+    os.makedirs(self.workspace.repo_storage, exist_ok=True)
     # Checkout before building, so we don't need to rely on copying the source
     # into the image.
     # TODO(metzman): Figure out if we want second copy at all.
     manager = repo_manager.clone_repo_and_get_manager(
         self.config.git_url,
-        git_workspace,
+        self.workspace.repo_storage,
         repo_name=self.config.project_repo_name)
     checkout_specified_commit(manager, self.config.pr_ref,
                               self.config.commit_sha)
 
-    build_integration_path = os.path.join(manager.repo_dir,
-                                          self.config.build_integration_path)
-    if not build_external_project_docker_image(
-        self.config.project_name, manager.repo_dir, build_integration_path):
+    build_integration_abs_path = os.path.join(
+        manager.repo_dir, self.config.build_integration_path)
+    if not build_external_project_docker_image(manager.repo_dir,
+                                               build_integration_abs_path):
       logging.error('Failed to build external project.')
-      return BuildPreparationResult(False, None, None)
+      return BuildPreparationResult(success=False,
+                                    image_repo_path=None,
+                                    repo_manager=None)
 
     image_repo_path = os.path.join('/src', self.config.project_repo_name)
-    return BuildPreparationResult(True, image_repo_path, manager)
+    return BuildPreparationResult(success=True,
+                                  image_repo_path=image_repo_path,
+                                  repo_manager=manager)
+
+  def get_build_command(self, host_repo_path, image_repo_path):  # pylint: disable=no-self-use
+    """Returns the command for building the project that is run inside the
+    project builder container."""
+    return get_build_command()
diff --git a/infra/cifuzz/continuous_integration_test.py b/infra/cifuzz/continuous_integration_test.py
new file mode 100644
index 0000000..7c7e3ee
--- /dev/null
+++ b/infra/cifuzz/continuous_integration_test.py
@@ -0,0 +1,87 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for continuous_integration_module."""
+import os
+import sys
+import unittest
+from unittest import mock
+
+import continuous_integration
+
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import repo_manager
+
+# pylint: disable=no-self-use
+
+
+class FixGitRepoForDiffTest(unittest.TestCase):
+  """Tests for fix_git_repo_for_diff."""
+
+  @mock.patch('utils.execute')
+  def test_fix_git_repo_for_diff(self, mock_execute):
+    """Tests that fix_git_repo_for_diff works as intended."""
+    repo_dir = '/dir'
+    repo_manager_obj = repo_manager.RepoManager(repo_dir)
+    continuous_integration.fix_git_repo_for_diff(repo_manager_obj)
+    expected_command = [
+        'git', 'symbolic-ref', 'refs/remotes/origin/HEAD',
+        'refs/remotes/origin/master'
+    ]
+
+    mock_execute.assert_called_with(expected_command, location=repo_dir)
+
+
+class GetBuildCommand(unittest.TestCase):
+  """Tests for get_build_command."""
+
+  def test_build_command(self):
+    """Tests that get_build_command works as intended."""
+    self.assertEqual(continuous_integration.get_build_command(), 'compile')
+
+
+class GetReplaceRepoAndBuildCommand(unittest.TestCase):
+  """Tests for get_replace_repo_and_build_command."""
+
+  def test_get_replace_repo_and_build_command(self):
+    """Tests that get_replace_repo_and_build_command works as intended."""
+    host_repo_path = '/path/on/host/to/repo'
+    image_repo_path = '/src/repo'
+    command = continuous_integration.get_replace_repo_and_build_command(
+        host_repo_path, image_repo_path)
+    expected_command = ('cd / && rm -rf /src/repo/* && '
+                        'cp -r /path/on/host/to/repo /src && cd - '
+                        '&& compile')
+    self.assertEqual(command, expected_command)
+
+
+class BuildExternalProjetDockerImage(unittest.TestCase):
+  """Tests for build_external_project_docker_image."""
+
+  @mock.patch('helper.docker_build')
+  def test_build_external_project_docker_image(self, mock_docker_build):
+    """Tests that build_external_project_docker_image works as intended."""
+    build_integration_path = '.clusterfuzzlite'
+    project_src = '/path/to/project/src'
+    continuous_integration.build_external_project_docker_image(
+        project_src, build_integration_path)
+
+    mock_docker_build.assert_called_with([
+        '-t', 'external-project', '-f',
+        os.path.join('.clusterfuzzlite', 'Dockerfile'), project_src
+    ])
+
+
+# TODO(metzman): Write tests for the rest of continuous_integration.py.
diff --git a/infra/cifuzz/coverage.py b/infra/cifuzz/coverage.py
deleted file mode 100644
index 9a179c5..0000000
--- a/infra/cifuzz/coverage.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Module for determining coverage of fuzz targets."""
-import logging
-import os
-import sys
-import json
-import urllib.error
-import urllib.request
-
-# pylint: disable=wrong-import-position,import-error
-sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-import utils
-
-# The path to get project's latest report json file.
-LATEST_REPORT_INFO_PATH = 'oss-fuzz-coverage/latest_report_info/'
-
-
-class OssFuzzCoverageGetter:
-  """Gets coverage data for a project from OSS-Fuzz."""
-
-  def __init__(self, project_name, repo_path):
-    """Constructor for OssFuzzCoverageGetter. Callers should check that
-    fuzzer_stats_url is initialized."""
-    self.project_name = project_name
-    self.repo_path = _normalize_repo_path(repo_path)
-    self.fuzzer_stats_url = _get_fuzzer_stats_dir_url(self.project_name)
-
-  def get_target_coverage_report(self, target):
-    """Get the coverage report for a specific fuzz target.
-
-    Args:
-      target: The name of the fuzz target whose coverage is requested.
-
-    Returns:
-      The target's coverage json dict or None on failure.
-    """
-    if not self.fuzzer_stats_url:
-      return None
-
-    target_url = utils.url_join(self.fuzzer_stats_url, target + '.json')
-    return get_json_from_url(target_url)
-
-  def get_files_covered_by_target(self, target):
-    """Gets a list of source files covered by the specific fuzz target.
-
-    Args:
-      target: The name of the fuzz target whose coverage is requested.
-
-    Returns:
-      A list of files that the fuzz targets covers or None.
-    """
-    target_cov = self.get_target_coverage_report(target)
-    if not target_cov:
-      return None
-
-    coverage_per_file = get_coverage_per_file(target_cov)
-    if not coverage_per_file:
-      logging.info('No files found in coverage report.')
-      return None
-
-    affected_file_list = []
-    for file_cov in coverage_per_file:
-      norm_file_path = os.path.normpath(file_cov['filename'])
-      if not norm_file_path.startswith(self.repo_path):
-        # Exclude files outside of the main repo.
-        continue
-
-      if not is_file_covered(file_cov):
-        # Don't consider a file affected if code in it is never executed.
-        continue
-
-      # TODO(metzman): It's weird to me that we access file_cov['filename']
-      # again and not norm_file_path, figure out if this makes sense.
-      relative_path = utils.remove_prefix(file_cov['filename'], self.repo_path)
-      affected_file_list.append(relative_path)
-
-    return affected_file_list
-
-
-def is_file_covered(file_cov):
-  """Returns whether the file is covered."""
-  return file_cov['summary']['regions']['covered']
-
-
-def get_coverage_per_file(target_cov):
-  """Returns the coverage per file within |target_cov|."""
-  return target_cov['data'][0]['files']
-
-
-def _normalize_repo_path(repo_path):
-  """Normalizes and returns |repo_path| to make sure cases like /src/curl and
-  /src/curl/ are both handled."""
-  repo_path = os.path.normpath(repo_path)
-  if not repo_path.endswith('/'):
-    repo_path += '/'
-  return repo_path
-
-
-def _get_latest_cov_report_info(project_name):
-  """Gets and returns a dictionary containing the latest coverage report info
-  for |project|."""
-  latest_report_info_url = utils.url_join(utils.GCS_BASE_URL,
-                                          LATEST_REPORT_INFO_PATH,
-                                          project_name + '.json')
-  latest_cov_info = get_json_from_url(latest_report_info_url)
-  if latest_cov_info is None:
-    logging.error('Could not get the coverage report json from url: %s.',
-                  latest_report_info_url)
-    return None
-  return latest_cov_info
-
-
-def _get_fuzzer_stats_dir_url(project_name):
-  """Gets latest coverage report info for a specific OSS-Fuzz project from GCS.
-
-  Args:
-    project_name: The name of the relevant OSS-Fuzz project.
-
-  Returns:
-    The projects coverage report info in json dict or None on failure.
-  """
-  latest_cov_info = _get_latest_cov_report_info(project_name)
-
-  if not latest_cov_info:
-    return None
-
-  if 'fuzzer_stats_dir' not in latest_cov_info:
-    logging.error('fuzzer_stats_dir not in latest coverage info.')
-    return None
-
-  fuzzer_stats_dir_gs_url = latest_cov_info['fuzzer_stats_dir']
-  fuzzer_stats_dir_url = utils.gs_url_to_https(fuzzer_stats_dir_gs_url)
-  return fuzzer_stats_dir_url
-
-
-def get_json_from_url(url):
-  """Gets a json object from a specified HTTP URL.
-
-  Args:
-    url: The url of the json to be downloaded.
-
-  Returns:
-    A dictionary deserialized from JSON or None on failure.
-  """
-  try:
-    response = urllib.request.urlopen(url)
-  except urllib.error.HTTPError:
-    logging.error('HTTP error with url %s.', url)
-    return None
-
-  try:
-    # read().decode() fixes compatibility issue with urllib response object.
-    result_json = json.loads(response.read().decode())
-  except (ValueError, TypeError, json.JSONDecodeError) as err:
-    logging.error('Loading json from url %s failed with: %s.', url, str(err))
-    return None
-  return result_json
diff --git a/infra/cifuzz/coverage_test.py b/infra/cifuzz/coverage_test.py
deleted file mode 100644
index 1b24d79..0000000
--- a/infra/cifuzz/coverage_test.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Tests for coverage.py"""
-import os
-import json
-import unittest
-from unittest import mock
-
-import coverage
-
-# pylint: disable=protected-access
-
-TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                              'test_data')
-
-PROJECT_NAME = 'curl'
-REPO_PATH = '/src/curl'
-FUZZ_TARGET = 'curl_fuzzer'
-PROJECT_COV_JSON_FILENAME = 'example_curl_cov.json'
-FUZZ_TARGET_COV_JSON_FILENAME = 'example_curl_fuzzer_cov.json'
-INVALID_TARGET = 'not-a-fuzz-target'
-
-with open(os.path.join(TEST_DATA_PATH,
-                       PROJECT_COV_JSON_FILENAME),) as cov_file_handle:
-  PROJECT_COV_INFO = json.loads(cov_file_handle.read())
-
-
-class GetFuzzerStatsDirUrlTest(unittest.TestCase):
-  """Tests _get_fuzzer_stats_dir_url."""
-
-  @mock.patch('coverage.get_json_from_url',
-              return_value={
-                  'fuzzer_stats_dir':
-                      'gs://oss-fuzz-coverage/systemd/fuzzer_stats/20210303'
-              })
-  def test_get_valid_project(self, mocked_get_json_from_url):
-    """Tests that a project's coverage report can be downloaded and parsed.
-
-    NOTE: This test relies on the PROJECT_NAME repo's coverage report.
-    The "example" project was not used because it has no coverage reports.
-    """
-    result = coverage._get_fuzzer_stats_dir_url(PROJECT_NAME)
-    (url,), _ = mocked_get_json_from_url.call_args
-    self.assertEqual(
-        'https://storage.googleapis.com/oss-fuzz-coverage/'
-        'latest_report_info/curl.json', url)
-
-    expected_result = (
-        'https://storage.googleapis.com/oss-fuzz-coverage/systemd/fuzzer_stats/'
-        '20210303')
-    self.assertEqual(result, expected_result)
-
-  def test_get_invalid_project(self):
-    """Tests that passing a bad project returns None."""
-    self.assertIsNone(coverage._get_fuzzer_stats_dir_url('not-a-proj'))
-
-
-class GetTargetCoverageReportTest(unittest.TestCase):
-  """Tests get_target_coverage_report."""
-
-  def setUp(self):
-    with mock.patch('coverage._get_latest_cov_report_info',
-                    return_value=PROJECT_COV_INFO):
-      self.coverage_getter = coverage.OssFuzzCoverageGetter(
-          PROJECT_NAME, REPO_PATH)
-
-  @mock.patch('coverage.get_json_from_url', return_value={})
-  def test_valid_target(self, mocked_get_json_from_url):
-    """Tests that a target's coverage report can be downloaded and parsed."""
-    self.coverage_getter.get_target_coverage_report(FUZZ_TARGET)
-    (url,), _ = mocked_get_json_from_url.call_args
-    self.assertEqual(
-        'https://storage.googleapis.com/oss-fuzz-coverage/'
-        'curl/fuzzer_stats/20200226/curl_fuzzer.json', url)
-
-  def test_invalid_target(self):
-    """Tests that passing an invalid target coverage report returns None."""
-    self.assertIsNone(
-        self.coverage_getter.get_target_coverage_report(INVALID_TARGET))
-
-  @mock.patch('coverage._get_latest_cov_report_info', return_value=None)
-  def test_invalid_project_json(self, _):
-    """Tests an invalid project JSON results in None being returned."""
-    coverage_getter = coverage.OssFuzzCoverageGetter(PROJECT_NAME, REPO_PATH)
-    self.assertIsNone(coverage_getter.get_target_coverage_report(FUZZ_TARGET))
-
-
-class GetFilesCoveredByTargetTest(unittest.TestCase):
-  """Tests get_files_covered_by_target."""
-
-  def setUp(self):
-    with mock.patch('coverage._get_latest_cov_report_info',
-                    return_value=PROJECT_COV_INFO):
-      self.coverage_getter = coverage.OssFuzzCoverageGetter(
-          PROJECT_NAME, REPO_PATH)
-
-  def test_valid_target(self):
-    """Tests that covered files can be retrieved from a coverage report."""
-    with open(os.path.join(TEST_DATA_PATH,
-                           FUZZ_TARGET_COV_JSON_FILENAME),) as file_handle:
-      fuzzer_cov_info = json.loads(file_handle.read())
-
-    with mock.patch('coverage.OssFuzzCoverageGetter.get_target_coverage_report',
-                    return_value=fuzzer_cov_info):
-      file_list = self.coverage_getter.get_files_covered_by_target(FUZZ_TARGET)
-
-    curl_files_list_path = os.path.join(TEST_DATA_PATH,
-                                        'example_curl_file_list.json')
-    with open(curl_files_list_path) as file_handle:
-      expected_file_list = json.loads(file_handle.read())
-    self.assertCountEqual(file_list, expected_file_list)
-
-  def test_invalid_target(self):
-    """Tests passing invalid fuzz target returns None."""
-    self.assertIsNone(
-        self.coverage_getter.get_files_covered_by_target(INVALID_TARGET))
-
-
-class IsFileCoveredTest(unittest.TestCase):
-  """Tests for is_file_covered."""
-
-  def test_is_file_covered_covered(self):
-    """Tests that is_file_covered returns True for a covered file."""
-    file_coverage = {
-        'filename': '/src/systemd/src/basic/locale-util.c',
-        'summary': {
-            'regions': {
-                'count': 204,
-                'covered': 200,
-                'notcovered': 200,
-                'percent': 98.03
-            }
-        }
-    }
-    self.assertTrue(coverage.is_file_covered(file_coverage))
-
-  def test_is_file_covered_not_covered(self):
-    """Tests that is_file_covered returns False for a not covered file."""
-    file_coverage = {
-        'filename': '/src/systemd/src/basic/locale-util.c',
-        'summary': {
-            'regions': {
-                'count': 204,
-                'covered': 0,
-                'notcovered': 0,
-                'percent': 0
-            }
-        }
-    }
-    self.assertFalse(coverage.is_file_covered(file_coverage))
-
-
-class GetLatestCovReportInfo(unittest.TestCase):
-  """Tests that _get_latest_cov_report_info works as intended."""
-
-  PROJECT = 'project'
-  LATEST_REPORT_INFO_URL = ('https://storage.googleapis.com/oss-fuzz-coverage/'
-                            'latest_report_info/project.json')
-
-  @mock.patch('logging.error')
-  @mock.patch('coverage.get_json_from_url', return_value={'coverage': 1})
-  def test_get_latest_cov_report_info(self, mocked_get_json_from_url,
-                                      mocked_error):
-    """Tests that _get_latest_cov_report_info works as intended."""
-    result = coverage._get_latest_cov_report_info(self.PROJECT)
-    self.assertEqual(result, {'coverage': 1})
-    mocked_error.assert_not_called()
-    mocked_get_json_from_url.assert_called_with(self.LATEST_REPORT_INFO_URL)
-
-  @mock.patch('logging.error')
-  @mock.patch('coverage.get_json_from_url', return_value=None)
-  def test_get_latest_cov_report_info_fail(self, _, mocked_error):
-    """Tests that _get_latest_cov_report_info works as intended when we can't
-    get latest report info."""
-    result = coverage._get_latest_cov_report_info('project')
-    self.assertIsNone(result)
-    mocked_error.assert_called_with(
-        'Could not get the coverage report json from url: %s.',
-        self.LATEST_REPORT_INFO_URL)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/infra/cifuzz/docker.py b/infra/cifuzz/docker.py
index eb993e2..935773d 100644
--- a/infra/cifuzz/docker.py
+++ b/infra/cifuzz/docker.py
@@ -12,23 +12,52 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """Module for dealing with docker."""
+import logging
 import os
 import sys
 
 # pylint: disable=wrong-import-position,import-error
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
+import constants
 import utils
 
 BASE_BUILDER_TAG = 'gcr.io/oss-fuzz-base/base-builder'
-BASE_RUNNER_TAG = 'gcr.io/oss-fuzz-base/base-runner'
-MSAN_LIBS_BUILDER_TAG = 'gcr.io/oss-fuzz-base/msan-libs-builder'
 PROJECT_TAG_PREFIX = 'gcr.io/oss-fuzz/'
 
+# Default fuzz configuration.
+_DEFAULT_DOCKER_RUN_ARGS = [
+    '--cap-add', 'SYS_PTRACE', '-e',
+    'FUZZING_ENGINE=' + constants.DEFAULT_ENGINE, '-e',
+    'ARCHITECTURE=' + constants.DEFAULT_ARCHITECTURE, '-e', 'CIFUZZ=True'
+]
+
+EXTERNAL_PROJECT_IMAGE = 'external-project'
+
+_DEFAULT_DOCKER_RUN_COMMAND = [
+    'docker',
+    'run',
+    '--rm',
+    '--privileged',
+]
+
+
+def get_docker_env_vars(env_mapping):
+  """Returns a list of docker arguments that sets each key in |env_mapping| as
+  an env var and the value of that key in |env_mapping| as the value."""
+  env_var_args = []
+  for env_var, env_var_val in env_mapping.items():
+    env_var_args.extend(['-e', f'{env_var}={env_var_val}'])
+  return env_var_args
+
 
 def get_project_image_name(project):
   """Returns the name of the project builder image for |project_name|."""
-  return PROJECT_TAG_PREFIX + project
+  # TODO(ochang): We may need unique names to support parallel fuzzing.
+  if project:
+    return PROJECT_TAG_PREFIX + project
+
+  return EXTERNAL_PROJECT_IMAGE
 
 
 def delete_images(images):
@@ -36,3 +65,49 @@
   command = ['docker', 'rmi', '-f'] + images
   utils.execute(command)
   utils.execute(['docker', 'builder', 'prune', '-f'])
+
+
+def get_base_docker_run_args(workspace,
+                             sanitizer=constants.DEFAULT_SANITIZER,
+                             language=constants.DEFAULT_LANGUAGE,
+                             docker_in_docker=False):
+  """Returns arguments that should be passed to every invocation of 'docker
+  run'."""
+  docker_args = _DEFAULT_DOCKER_RUN_ARGS.copy()
+  env_mapping = {
+      'SANITIZER': sanitizer,
+      'FUZZING_LANGUAGE': language,
+      'OUT': workspace.out
+  }
+  docker_args += get_docker_env_vars(env_mapping)
+  docker_container = utils.get_container_name()
+  logging.info('Docker container: %s.', docker_container)
+  if docker_container and not docker_in_docker:
+    # Don't map specific volumes if in a docker container, it breaks when
+    # running a sibling container.
+    docker_args += ['--volumes-from', docker_container]
+  else:
+    docker_args += _get_args_mapping_host_path_to_container(workspace.workspace)
+  return docker_args, docker_container
+
+
+def get_base_docker_run_command(workspace,
+                                sanitizer=constants.DEFAULT_SANITIZER,
+                                language=constants.DEFAULT_LANGUAGE,
+                                docker_in_docker=False):
+  """Returns part of the command that should be used everytime 'docker run' is
+  invoked."""
+  docker_args, docker_container = get_base_docker_run_args(
+      workspace, sanitizer, language, docker_in_docker=docker_in_docker)
+  command = _DEFAULT_DOCKER_RUN_COMMAND.copy() + docker_args
+  return command, docker_container
+
+
+def _get_args_mapping_host_path_to_container(host_path, container_path=None):
+  """Get arguments to docker run that will map |host_path| a path on the host to
+  a path in the container. If |container_path| is specified, that path is mapped
+  to. If not, then |host_path| is mapped to itself in the container."""
+  # WARNING: Do not use this function when running in production (and
+  # --volumes-from) is used for mapping volumes. It will break production.
+  container_path = host_path if container_path is None else container_path
+  return ['-v', f'{host_path}:{container_path}']
diff --git a/infra/cifuzz/docker_test.py b/infra/cifuzz/docker_test.py
new file mode 100644
index 0000000..b356138
--- /dev/null
+++ b/infra/cifuzz/docker_test.py
@@ -0,0 +1,122 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests the functionality of the docker module."""
+import unittest
+from unittest import mock
+
+import docker
+import test_helpers
+import workspace_utils
+
+CONTAINER_NAME = 'example-container'
+config = test_helpers.create_run_config(oss_fuzz_project_name='project',
+                                        workspace='/workspace')
+config.workspace = '/workspace'
+WORKSPACE = workspace_utils.Workspace(config)
+SANITIZER = 'example-sanitizer'
+LANGUAGE = 'example-language'
+
+
+class GetProjectImageTest(unittest.TestCase):
+  """Tests for get_project_image."""
+
+  def test_get_project_image(self):
+    """Tests that get_project_image_name works as intended."""
+    project = 'my-project'
+    self.assertEqual(docker.get_project_image_name(project),
+                     'gcr.io/oss-fuzz/my-project')
+
+
+class GetDeleteImagesTest(unittest.TestCase):
+  """Tests for delete_images."""
+
+  @mock.patch('utils.execute')
+  def test_delete_images(self, mock_execute):  # pylint: disable=no-self-use
+    """Tests that get_project_image_name works as intended."""
+    images = ['image']
+    docker.delete_images(images)
+    expected_calls = [
+        mock.call(['docker', 'rmi', '-f'] + images),
+        mock.call(['docker', 'builder', 'prune', '-f'])
+    ]
+
+    mock_execute.assert_has_calls(expected_calls)
+
+
+class GetBaseDockerRunArgsTest(unittest.TestCase):
+  """Tests get_base_docker_run_args."""
+
+  @mock.patch('utils.get_container_name', return_value=CONTAINER_NAME)
+  def test_get_base_docker_run_args_container(self, _):
+    """Tests that get_base_docker_run_args works as intended when inside a
+    container."""
+    docker_args, docker_container = docker.get_base_docker_run_args(
+        WORKSPACE, SANITIZER, LANGUAGE)
+    self.assertEqual(docker_container, CONTAINER_NAME)
+    expected_docker_args = []
+    expected_docker_args = [
+        '--cap-add',
+        'SYS_PTRACE',
+        '-e',
+        'FUZZING_ENGINE=libfuzzer',
+        '-e',
+        'ARCHITECTURE=x86_64',
+        '-e',
+        'CIFUZZ=True',
+        '-e',
+        f'SANITIZER={SANITIZER}',
+        '-e',
+        f'FUZZING_LANGUAGE={LANGUAGE}',
+        '-e',
+        f'OUT={WORKSPACE.out}',
+        '--volumes-from',
+        CONTAINER_NAME,
+    ]
+    self.assertEqual(docker_args, expected_docker_args)
+
+  @mock.patch('utils.get_container_name', return_value=None)
+  def test_get_base_docker_run_args_no_container(self, _):
+    """Tests that get_base_docker_run_args works as intended when not inside a
+    container."""
+    docker_args, docker_container = docker.get_base_docker_run_args(
+        WORKSPACE, SANITIZER, LANGUAGE)
+    self.assertEqual(docker_container, None)
+    expected_docker_args = [
+        '--cap-add', 'SYS_PTRACE', '-e', 'FUZZING_ENGINE=libfuzzer', '-e',
+        'ARCHITECTURE=x86_64', '-e', 'CIFUZZ=True', '-e',
+        f'SANITIZER={SANITIZER}', '-e', f'FUZZING_LANGUAGE={LANGUAGE}', '-e',
+        f'OUT={WORKSPACE.out}', '-v',
+        f'{WORKSPACE.workspace}:{WORKSPACE.workspace}'
+    ]
+    self.assertEqual(docker_args, expected_docker_args)
+
+
+class GetBaseDockerRunCommandTest(unittest.TestCase):
+  """Tests get_base_docker_run_args."""
+
+  @mock.patch('utils.get_container_name', return_value=None)
+  def test_get_base_docker_run_command_no_container(self, _):
+    """Tests that get_base_docker_run_args works as intended when not inside a
+    container."""
+    docker_args, docker_container = docker.get_base_docker_run_command(
+        WORKSPACE, SANITIZER, LANGUAGE)
+    self.assertEqual(docker_container, None)
+    expected_docker_command = [
+        'docker', 'run', '--rm', '--privileged', '--cap-add', 'SYS_PTRACE',
+        '-e', 'FUZZING_ENGINE=libfuzzer', '-e', 'ARCHITECTURE=x86_64', '-e',
+        'CIFUZZ=True', '-e', f'SANITIZER={SANITIZER}', '-e',
+        f'FUZZING_LANGUAGE={LANGUAGE}', '-e', f'OUT={WORKSPACE.out}', '-v',
+        f'{WORKSPACE.workspace}:{WORKSPACE.workspace}'
+    ]
+    self.assertEqual(docker_args, expected_docker_command)
diff --git a/infra/cifuzz/environment.py b/infra/cifuzz/environment.py
index 4cc0f84..e99a679 100644
--- a/infra/cifuzz/environment.py
+++ b/infra/cifuzz/environment.py
@@ -46,9 +46,6 @@
   lower_value = value.lower()
   allowed_values = {'true', 'false'}
   if lower_value not in allowed_values:
-    raise Exception(('Bool env var {env_var} value {value} is invalid. '
-                     'Must be one of {allowed_values}').format(
-                         env_var=env_var,
-                         value=value,
-                         allowed_values=allowed_values))
+    raise Exception(f'Bool env var {env_var} value {value} is invalid. '
+                    f'Must be one of {allowed_values}.')
   return lower_value == 'true'
diff --git a/infra/cifuzz/external-actions/build_fuzzers/action.yml b/infra/cifuzz/external-actions/build_fuzzers/action.yml
new file mode 100644
index 0000000..f45d02e
--- /dev/null
+++ b/infra/cifuzz/external-actions/build_fuzzers/action.yml
@@ -0,0 +1,63 @@
+# action.yml
+name: 'build-fuzzers'
+description: "Builds an OSS-Fuzz project's fuzzers."
+inputs:
+  language:
+    description: 'Programming language project is written in.'
+    required: false
+    default: 'c++'
+  dry-run:
+    description: 'If set, run the action without actually reporting a failure.'
+    default: false
+  allowed-broken-targets-percentage:
+    description: 'The percentage of broken targets allowed in bad_build_check.'
+    required: false
+  sanitizer:
+    description: 'The sanitizer to build the fuzzers with.'
+    default: 'address'
+  project-src-path:
+    description: "The path to the project's source code checkout."
+    required: false
+  bad-build-check:
+    description: "Whether or not OSS-Fuzz's check for bad builds should be done."
+    required: false
+    default: true
+  storage-repo:
+    description: |
+      The git repo to use for storing certain artifacts from fuzzing.
+    required: false
+  storage-repo-branch:
+    description: |
+      The branch of the git repo to use for storing certain artifacts from
+      fuzzing.
+    required: false
+  storage-repo-branch-coverage:
+    description: |
+      The branch of the git repo to use for storing coverage reports.
+    required: false
+  upload-build:
+    description: |
+      If set, will upload the build.
+    default: false
+  github-token:
+    description: |
+      Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET
+      You should use "secrets.GITHUB_TOKEN" in your workflow file, do not
+      hardcode the token.
+      TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361):
+      Document locking this down.
+    required: false
+runs:
+  using: 'docker'
+  image: '../../../build_fuzzers.Dockerfile'
+  env:
+    OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }}
+    LANGUAGE: ${{ inputs.language }}
+    DRY_RUN: ${{ inputs.dry-run}}
+    ALLOWED_BROKEN_TARGETS_PERCENTAGE: ${{ inputs.allowed-broken-targets-percentage}}
+    SANITIZER: ${{ inputs.sanitizer }}
+    PROJECT_SRC_PATH: ${{ inputs.project-src-path }}
+    GITHUB_TOKEN: ${{ inputs.github-token }}
+    LOW_DISK_SPACE: 'True'
+    BAD_BUILD_CHECK: ${{ inputs.bad-build-check }}
+    UPLOAD_BUILD: ${{ inputs.upload-build }}
diff --git a/infra/cifuzz/external-actions/run_fuzzers/action.yml b/infra/cifuzz/external-actions/run_fuzzers/action.yml
new file mode 100644
index 0000000..cdefb56
--- /dev/null
+++ b/infra/cifuzz/external-actions/run_fuzzers/action.yml
@@ -0,0 +1,69 @@
+# action.yml
+name: 'run-fuzzers'
+description: 'Runs fuzz target binaries for a specified length of time.'
+inputs:
+  language:
+    description: 'Programming language project is written in.'
+    required: false
+    default: 'c++'
+  fuzz-seconds:
+    description: 'The total time allotted for fuzzing in seconds.'
+    required: true
+    default: 600
+  dry-run:
+    description: 'If set, run the action without actually reporting a failure.'
+    default: false
+  sanitizer:
+    description: 'The sanitizer to run the fuzzers with.'
+    default: 'address'
+  run-fuzzers-mode:
+    description: |
+      The mode to run the fuzzers with ("ci" or "batch").
+      "ci" is for fuzzing a pull request or commit.
+      "batch" is for non-interactive fuzzing of an entire project.
+      "batch" is in alpha and should not be used in production.
+    required: false
+    default: 'ci'
+  github-token:
+    description: |
+      Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET
+      You should use "secrets.GITHUB_TOKEN" in your workflow file, do not
+      hardcode the token.
+      TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361):
+      Document locking this down.
+    required: true
+  storage-repo:
+    description: |
+      The git repo to use for storing certain artifacts from fuzzing.
+    required: false
+  storage-repo-branch:
+    description: |
+      The branch of the git repo to use for storing certain artifacts from
+      fuzzing.
+    default: main
+    required: false
+  storage-repo-branch-coverage:
+    description: |
+      The branch of the git repo to use for storing coverage reports.
+    default: gh-pages
+    required: false
+  report-unreproducible-crashes:
+    description: 'If True, then unreproducible crashes will be reported by CIFuzz.'
+    required: false
+    default: false
+runs:
+  using: 'docker'
+  image: '../../../run_fuzzers.Dockerfile'
+  env:
+    OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }}
+    LANGUAGE: ${{ inputs.language }}
+    FUZZ_SECONDS: ${{ inputs.fuzz-seconds }}
+    DRY_RUN: ${{ inputs.dry-run}}
+    SANITIZER: ${{ inputs.sanitizer }}
+    RUN_FUZZERS_MODE: ${{ inputs.run-fuzzers-mode }}
+    GITHUB_TOKEN: ${{ inputs.github-token }}
+    LOW_DISK_SPACE: 'True'
+    GIT_STORE_REPO: ${{ inputs.storage-repo }}
+    GIT_STORE_BRANCH: ${{ inputs.storage-repo-branch }}
+    GIT_STORE_BRANCH_COVERAGE: ${{ inputs.storage-repo-branch-coverage }}
+    REPORT_UNREPRODUCIBLE_CRASHES: ${{ inputs.report-unreproducible-crashes }}
diff --git a/infra/cifuzz/filestore/__init__.py b/infra/cifuzz/filestore/__init__.py
new file mode 100644
index 0000000..d112f7b
--- /dev/null
+++ b/infra/cifuzz/filestore/__init__.py
@@ -0,0 +1,54 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Module for a generic filestore."""
+
+
+class FilestoreError(Exception):
+  """Error using the filestore."""
+
+
+# pylint: disable=unused-argument,no-self-use
+class BaseFilestore:
+  """Base class for a filestore."""
+
+  def __init__(self, config):
+    self.config = config
+
+  def upload_crashes(self, name, directory):
+    """Uploads the crashes at |directory| to |name|."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def upload_corpus(self, name, directory, replace=False):
+    """Uploads the corpus at |directory| to |name|."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def upload_build(self, name, directory):
+    """Uploads the build at |directory| to |name|."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def upload_coverage(self, name, directory):
+    """Uploads the coverage report at |directory| to |name|."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def download_corpus(self, name, dst_directory):
+    """Downloads the corpus located at |name| to |dst_directory|."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def download_build(self, name, dst_directory):
+    """Downloads the build with |name| to |dst_directory|."""
+    raise NotImplementedError('Child class must implement method.')
+
+  def download_coverage(self, dst_directory):
+    """Downloads the latest project coverage report."""
+    raise NotImplementedError('Child class must implement method.')
diff --git a/infra/cifuzz/filestore/git/__init__.py b/infra/cifuzz/filestore/git/__init__.py
new file mode 100644
index 0000000..5414003
--- /dev/null
+++ b/infra/cifuzz/filestore/git/__init__.py
@@ -0,0 +1,159 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Module for a git based filestore."""
+
+from distutils import dir_util
+import logging
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import filestore
+
+# pylint: disable=wrong-import-position
+INFRA_DIR = os.path.dirname(
+    os.path.dirname(os.path.dirname(os.path.dirname(
+        os.path.abspath(__file__)))))
+sys.path.append(INFRA_DIR)
+
+import retry
+
+_PUSH_RETRIES = 3
+_PUSH_BACKOFF = 1
+_GIT_EMAIL = 'cifuzz@clusterfuzz.com'
+_GIT_NAME = 'CIFuzz'
+_CORPUS_DIR = 'corpus'
+_COVERAGE_DIR = 'coverage'
+
+
+def git_runner(repo_path):
+  """Returns a gits runner for the repo_path."""
+
+  def func(*args):
+    return subprocess.check_call(('git', '-C', repo_path) + args)
+
+  return func
+
+
+# pylint: disable=unused-argument,no-self-use
+class GitFilestore(filestore.BaseFilestore):
+  """Generic git filestore. This still relies on another filestore provided by
+  the CI for larger artifacts or artifacts which make sense to be included as
+  the result of a workflow run."""
+
+  def __init__(self, config, ci_filestore):
+    super().__init__(config)
+    self.repo_path = tempfile.mkdtemp()
+    self._git = git_runner(self.repo_path)
+    self._clone(self.config.git_store_repo)
+
+    self._ci_filestore = ci_filestore
+
+  def __del__(self):
+    shutil.rmtree(self.repo_path)
+
+  def _clone(self, repo_url):
+    """Clones repo URL."""
+    self._git('clone', repo_url, '.')
+    self._git('config', '--local', 'user.email', _GIT_EMAIL)
+    self._git('config', '--local', 'user.name', _GIT_NAME)
+
+  def _reset_git(self, branch):
+    """Resets the git repo."""
+    self._git('fetch', 'origin')
+    try:
+      self._git('checkout', '-B', branch, 'origin/' + branch)
+      self._git('reset', '--hard', 'HEAD')
+    except subprocess.CalledProcessError:
+      self._git('checkout', '--orphan', branch)
+
+    self._git('clean', '-fxd')
+
+  # pylint: disable=too-many-arguments
+  @retry.wrap(_PUSH_RETRIES, _PUSH_BACKOFF)
+  def _upload_to_git(self,
+                     message,
+                     branch,
+                     upload_path,
+                     local_path,
+                     replace=False):
+    """Uploads a directory to git. If `replace` is True, then existing contents
+    in the upload_path is deleted."""
+    self._reset_git(branch)
+
+    full_repo_path = os.path.join(self.repo_path, upload_path)
+    if replace and os.path.exists(full_repo_path):
+      shutil.rmtree(full_repo_path)
+
+    dir_util.copy_tree(local_path, full_repo_path)
+    self._git('add', '.')
+    try:
+      self._git('commit', '-m', message)
+    except subprocess.CalledProcessError:
+      logging.debug('No changes, skipping git push.')
+      return
+
+    self._git('push', 'origin', branch)
+
+  def upload_crashes(self, name, directory):
+    """Uploads the crashes at |directory| to |name|."""
+    return self._ci_filestore.upload_crashes(name, directory)
+
+  def upload_corpus(self, name, directory, replace=False):
+    """Uploads the corpus at |directory| to |name|."""
+    self._upload_to_git('Corpus upload',
+                        self.config.git_store_branch,
+                        os.path.join(_CORPUS_DIR, name),
+                        directory,
+                        replace=replace)
+
+  def upload_build(self, name, directory):
+    """Uploads the build at |directory| to |name|."""
+    return self._ci_filestore.upload_build(name, directory)
+
+  def upload_coverage(self, name, directory):
+    """Uploads the coverage report at |directory| to |name|."""
+    self._upload_to_git('Coverage upload',
+                        self.config.git_store_branch_coverage,
+                        os.path.join(_COVERAGE_DIR, name),
+                        directory,
+                        replace=True)
+
+  def download_corpus(self, name, dst_directory):
+    """Downloads the corpus located at |name| to |dst_directory|."""
+    self._reset_git(self.config.git_store_branch)
+    path = os.path.join(self.repo_path, _CORPUS_DIR, name)
+    if not os.path.exists(path):
+      logging.debug('Corpus does not exist at %s.', path)
+      return False
+
+    dir_util.copy_tree(path, dst_directory)
+    return True
+
+  def download_build(self, name, dst_directory):
+    """Downloads the build with |name| to |dst_directory|."""
+    return self._ci_filestore.download_build(name, dst_directory)
+
+  def download_coverage(self, name, dst_directory):
+    """Downloads the latest project coverage report."""
+    self._reset_git(self.config.git_store_branch_coverage)
+    path = os.path.join(self.repo_path, _COVERAGE_DIR, name)
+    if not os.path.exists(path):
+      logging.debug('Coverage does not exist at %s.', path)
+      return False
+
+    dir_util.copy_tree(path, dst_directory)
+    return True
diff --git a/infra/cifuzz/filestore/git/git_test.py b/infra/cifuzz/filestore/git/git_test.py
new file mode 100644
index 0000000..56be23b
--- /dev/null
+++ b/infra/cifuzz/filestore/git/git_test.py
@@ -0,0 +1,122 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for git."""
+import filecmp
+import os
+import tempfile
+import subprocess
+import sys
+import unittest
+from unittest import mock
+
+# pylint: disable=wrong-import-position
+INFRA_DIR = os.path.dirname(
+    os.path.dirname(os.path.dirname(os.path.dirname(
+        os.path.abspath(__file__)))))
+sys.path.append(INFRA_DIR)
+
+from filestore import git
+import test_helpers
+
+# pylint: disable=protected-access,no-self-use
+
+
+class GitFilestoreTest(unittest.TestCase):
+  """Tests for GitFilestore."""
+
+  def setUp(self):
+    self.git_dir = tempfile.TemporaryDirectory()
+    self.addCleanup(self.git_dir.cleanup)
+
+    self.local_dir = tempfile.TemporaryDirectory()
+    self.addCleanup(self.local_dir.cleanup)
+
+    self.download_dir = tempfile.TemporaryDirectory()
+    self.addCleanup(self.download_dir.cleanup)
+
+    with open(os.path.join(self.local_dir.name, 'a'), 'w') as handle:
+      handle.write('')
+
+    os.makedirs(os.path.join(self.local_dir.name, 'b'))
+
+    with open(os.path.join(self.local_dir.name, 'b', 'c'), 'w') as handle:
+      handle.write('')
+
+    self.git_repo = git.git_runner(self.git_dir.name)
+    self.git_repo('init', '--bare')
+
+    self.config = test_helpers.create_run_config(
+        git_store_repo='file://' + self.git_dir.name,
+        git_store_branch='main',
+        git_store_branch_coverage='cov-branch')
+
+    self.mock_ci_filestore = mock.MagicMock()
+    self.git_store = git.GitFilestore(self.config, self.mock_ci_filestore)
+
+  def assert_dirs_same(self, first, second):
+    """Asserts two dirs are the same."""
+    dcmp = filecmp.dircmp(first, second)
+    if dcmp.diff_files or dcmp.left_only or dcmp.right_only:
+      return False
+
+    return all(
+        self.assert_dirs_same(os.path.join(first, subdir),
+                              os.path.join(second, subdir))
+        for subdir in dcmp.common_dirs)
+
+  def get_repo_filelist(self, branch):
+    """Get files in repo."""
+    return subprocess.check_output([
+        'git', '-C', self.git_dir.name, 'ls-tree', '-r', '--name-only', branch
+    ]).decode().splitlines()
+
+  def test_upload_download_corpus(self):
+    """Tests uploading and downloading corpus."""
+    self.git_store.upload_corpus('target', self.local_dir.name)
+    self.git_store.download_corpus('target', self.download_dir.name)
+    self.assert_dirs_same(self.local_dir.name, self.download_dir.name)
+
+    self.assertCountEqual([
+        'corpus/target/a',
+        'corpus/target/b/c',
+    ], self.get_repo_filelist('main'))
+
+  def test_upload_download_coverage(self):
+    """Tests uploading and downloading corpus."""
+    self.git_store.upload_coverage('latest', self.local_dir.name)
+    self.git_store.download_coverage('latest', self.download_dir.name)
+    self.assert_dirs_same(self.local_dir.name, self.download_dir.name)
+
+    self.assertCountEqual([
+        'coverage/latest/a',
+        'coverage/latest/b/c',
+    ], self.get_repo_filelist('cov-branch'))
+
+  def test_upload_crashes(self):
+    """Tests uploading crashes."""
+    self.git_store.upload_crashes('current', self.local_dir.name)
+    self.mock_ci_filestore.upload_crashes.assert_called_with(
+        'current', self.local_dir.name)
+
+  def test_upload_build(self):
+    """Tests uploading build."""
+    self.git_store.upload_build('sanitizer', self.local_dir.name)
+    self.mock_ci_filestore.upload_build.assert_called_with(
+        'sanitizer', self.local_dir.name)
+
+  def test_download_build(self):
+    """Tests downloading build."""
+    self.git_store.download_build('sanitizer', self.download_dir.name)
+    self.mock_ci_filestore.download_build.assert_called_with(
+        'sanitizer', self.download_dir.name)
diff --git a/infra/cifuzz/filestore/github_actions/__init__.py b/infra/cifuzz/filestore/github_actions/__init__.py
new file mode 100644
index 0000000..3b03f9c
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/__init__.py
@@ -0,0 +1,177 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Implementation of a filestore using Github actions artifacts."""
+import logging
+import os
+import shutil
+import sys
+import tarfile
+import tempfile
+
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(
+    os.path.join(os.path.pardir, os.path.pardir, os.path.pardir,
+                 os.path.dirname(os.path.abspath(__file__))))
+
+import utils
+import http_utils
+import filestore
+from filestore.github_actions import github_api
+
+UPLOAD_JS = os.path.join(os.path.dirname(__file__), 'upload.js')
+
+
+def tar_directory(directory, archive_path):
+  """Tars a |directory| and stores archive at |archive_path|. |archive_path|
+  must end in .tar"""
+  assert archive_path.endswith('.tar')
+  # Do this because make_archive will append the extension to archive_path.
+  archive_path = os.path.splitext(archive_path)[0]
+
+  root_directory = os.path.abspath(directory)
+  shutil.make_archive(archive_path,
+                      'tar',
+                      root_dir=root_directory,
+                      base_dir='./')
+
+
+class GithubActionsFilestore(filestore.BaseFilestore):
+  """Implementation of BaseFilestore using Github actions artifacts. Relies on
+  github_actions_toolkit for using the GitHub actions API and the github_api
+  module for using GitHub's standard API. We need to use both because the GitHub
+  actions API is the only way to upload an artifact but it does not support
+  downloading artifacts from other runs. The standard GitHub API does support
+  this however."""
+
+  ARTIFACT_PREFIX = 'cifuzz-'
+  BUILD_PREFIX = 'build-'
+  CRASHES_PREFIX = 'crashes-'
+  CORPUS_PREFIX = 'corpus-'
+  COVERAGE_PREFIX = 'coverage-'
+
+  def __init__(self, config):
+    super().__init__(config)
+    self.github_api_http_headers = github_api.get_http_auth_headers(config)
+
+  def _get_artifact_name(self, name):
+    """Returns |name| prefixed with |self.ARITFACT_PREFIX| if it isn't already
+    prefixed. Otherwise returns |name|."""
+    if name.startswith(self.ARTIFACT_PREFIX):
+      return name
+    return f'{self.ARTIFACT_PREFIX}{name}'
+
+  def _upload_directory(self, name, directory):  # pylint: disable=no-self-use
+    """Uploads |directory| as artifact with |name|."""
+    name = self._get_artifact_name(name)
+    with tempfile.TemporaryDirectory() as temp_dir:
+      archive_path = os.path.join(temp_dir, name + '.tar')
+      tar_directory(directory, archive_path)
+      _raw_upload_directory(name, temp_dir)
+
+  def upload_crashes(self, name, directory):
+    """Uploads the crashes at |directory| to |name|."""
+    return _raw_upload_directory(self.CRASHES_PREFIX + name, directory)
+
+  def upload_corpus(self, name, directory, replace=False):
+    """Uploads the corpus at |directory| to |name|."""
+    # Not applicable as the the entire corpus is uploaded under a single
+    # artifact name.
+    del replace
+    return self._upload_directory(self.CORPUS_PREFIX + name, directory)
+
+  def upload_build(self, name, directory):
+    """Uploads the build at |directory| to |name|."""
+    return self._upload_directory(self.BUILD_PREFIX + name, directory)
+
+  def upload_coverage(self, name, directory):
+    """Uploads the coverage report at |directory| to |name|."""
+    return self._upload_directory(self.COVERAGE_PREFIX + name, directory)
+
+  def download_corpus(self, name, dst_directory):  # pylint: disable=unused-argument,no-self-use
+    """Downloads the corpus located at |name| to |dst_directory|."""
+    return self._download_artifact(self.CORPUS_PREFIX + name, dst_directory)
+
+  def _find_artifact(self, name):
+    """Finds an artifact using the GitHub API and returns it."""
+    logging.debug('Listing artifacts.')
+    artifacts = self._list_artifacts()
+    artifact = github_api.find_artifact(name, artifacts)
+    logging.debug('Artifact: %s.', artifact)
+    return artifact
+
+  def _download_artifact(self, name, dst_directory):
+    """Downloads artifact with |name| to |dst_directory|. Returns True on
+    success."""
+    name = self._get_artifact_name(name)
+
+    with tempfile.TemporaryDirectory() as temp_dir:
+      if not self._raw_download_artifact(name, temp_dir):
+        logging.warning('Could not download artifact: %s.', name)
+        return False
+
+      artifact_tarfile_path = os.path.join(temp_dir, name + '.tar')
+      if not os.path.exists(artifact_tarfile_path):
+        logging.error('Artifact zip did not contain a tarfile.')
+        return False
+
+      # TODO(jonathanmetzman): Replace this with archive.unpack from
+      # libClusterFuzz so we can avoid path traversal issues.
+      with tarfile.TarFile(artifact_tarfile_path) as artifact_tarfile:
+        artifact_tarfile.extractall(dst_directory)
+    return True
+
+  def _raw_download_artifact(self, name, dst_directory):
+    """Downloads the artifact with |name| to |dst_directory|. Returns True on
+    success. Does not do any untarring or adding prefix to |name|."""
+    artifact = self._find_artifact(name)
+    if not artifact:
+      logging.warning('Could not find artifact: %s.', name)
+      return False
+    download_url = artifact['archive_download_url']
+    return http_utils.download_and_unpack_zip(
+        download_url, dst_directory, headers=self.github_api_http_headers)
+
+  def _list_artifacts(self):
+    """Returns a list of artifacts."""
+    return github_api.list_artifacts(self.config.project_repo_owner,
+                                     self.config.project_repo_name,
+                                     self.github_api_http_headers)
+
+  def download_build(self, name, dst_directory):
+    """Downloads the build with name |name| to |dst_directory|."""
+    return self._download_artifact(self.BUILD_PREFIX + name, dst_directory)
+
+  def download_coverage(self, name, dst_directory):
+    """Downloads the latest project coverage report."""
+    return self._download_artifact(self.COVERAGE_PREFIX + name, dst_directory)
+
+
+def _upload_artifact_with_upload_js(name, artifact_paths, directory):
+  """Uploads the artifacts in |artifact_paths| that are located in |directory|
+  to |name|, using the upload.js script."""
+  command = [UPLOAD_JS, name, directory] + artifact_paths
+  _, _, retcode = utils.execute(command)
+  return retcode == 0
+
+
+def _raw_upload_directory(name, directory):
+  """Uploads the artifacts located in |directory| to |name|. Does not do any
+  tarring or adding prefixes to |name|."""
+  # Get file paths.
+  artifact_paths = []
+  for root, _, curr_file_paths in os.walk(directory):
+    for file_path in curr_file_paths:
+      artifact_paths.append(os.path.join(root, file_path))
+  logging.debug('Artifact paths: %s.', artifact_paths)
+  return _upload_artifact_with_upload_js(name, artifact_paths, directory)
diff --git a/infra/cifuzz/filestore/github_actions/github_actions_test.py b/infra/cifuzz/filestore/github_actions/github_actions_test.py
new file mode 100644
index 0000000..7745065
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/github_actions_test.py
@@ -0,0 +1,281 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for github_actions."""
+import os
+import shutil
+import sys
+import tarfile
+import tempfile
+import unittest
+from unittest import mock
+
+from pyfakefs import fake_filesystem_unittest
+
+# pylint: disable=wrong-import-position
+INFRA_DIR = os.path.dirname(
+    os.path.dirname(os.path.dirname(os.path.dirname(
+        os.path.abspath(__file__)))))
+sys.path.append(INFRA_DIR)
+
+from filestore import github_actions
+import test_helpers
+
+# pylint: disable=protected-access,no-self-use
+
+
+class GithubActionsFilestoreTest(fake_filesystem_unittest.TestCase):
+  """Tests for GithubActionsFilestore."""
+
+  def setUp(self):
+    test_helpers.patch_environ(self)
+    self.token = 'example githubtoken'
+    self.owner = 'exampleowner'
+    self.repo = 'examplerepo'
+    os.environ['GITHUB_REPOSITORY'] = f'{self.owner}/{self.repo}'
+    os.environ['GITHUB_EVENT_PATH'] = '/fake'
+    self.config = test_helpers.create_run_config(token=self.token)
+    self.local_dir = '/local-dir'
+    self.testcase = os.path.join(self.local_dir, 'testcase')
+
+  def _get_expected_http_headers(self):
+    return {
+        'Authorization': f'token {self.token}',
+        'Accept': 'application/vnd.github.v3+json',
+    }
+
+  @mock.patch('filestore.github_actions.github_api.list_artifacts')
+  def test_list_artifacts(self, mock_list_artifacts):
+    """Tests that _list_artifacts works as intended."""
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    filestore._list_artifacts()
+    mock_list_artifacts.assert_called_with(self.owner, self.repo,
+                                           self._get_expected_http_headers())
+
+  @mock.patch('logging.warning')
+  @mock.patch('filestore.github_actions.GithubActionsFilestore._list_artifacts',
+              return_value=None)
+  @mock.patch('filestore.github_actions.github_api.find_artifact',
+              return_value=None)
+  def test_download_build_no_artifact(self, _, __, mock_warning):
+    """Tests that download_build returns None and doesn't exception when
+    find_artifact can't find an artifact."""
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    name = 'name'
+    build_dir = 'build-dir'
+    self.assertFalse(filestore.download_build(name, build_dir))
+    mock_warning.assert_called_with('Could not download artifact: %s.',
+                                    'cifuzz-build-' + name)
+
+  @mock.patch('logging.warning')
+  @mock.patch('filestore.github_actions.GithubActionsFilestore._list_artifacts',
+              return_value=None)
+  @mock.patch('filestore.github_actions.github_api.find_artifact',
+              return_value=None)
+  def test_download_corpus_no_artifact(self, _, __, mock_warning):
+    """Tests that download_corpus_build returns None and doesn't exception when
+    find_artifact can't find an artifact."""
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    name = 'name'
+    dst_dir = 'local-dir'
+    self.assertFalse(filestore.download_corpus(name, dst_dir))
+    mock_warning.assert_called_with('Could not download artifact: %s.',
+                                    'cifuzz-corpus-' + name)
+
+  @mock.patch('filestore.github_actions.tar_directory')
+  @mock.patch('filestore.github_actions._upload_artifact_with_upload_js')
+  def test_upload_corpus(self, mock_upload_artifact, mock_tar_directory):
+    """Test uploading corpus."""
+    self._create_local_dir()
+
+    def mock_tar_directory_impl(_, archive_path):
+      self.fs.create_file(archive_path)
+
+    mock_tar_directory.side_effect = mock_tar_directory_impl
+
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    filestore.upload_corpus('target', self.local_dir)
+    self.assert_upload(mock_upload_artifact, mock_tar_directory,
+                       'corpus-target')
+
+  @mock.patch('filestore.github_actions._upload_artifact_with_upload_js')
+  def test_upload_crashes(self, mock_upload_artifact):
+    """Test uploading crashes."""
+    self._create_local_dir()
+
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    filestore.upload_crashes('current', self.local_dir)
+    mock_upload_artifact.assert_has_calls(
+        [mock.call('crashes-current', ['/local-dir/testcase'], '/local-dir')])
+
+  @mock.patch('filestore.github_actions.tar_directory')
+  @mock.patch('filestore.github_actions._upload_artifact_with_upload_js')
+  def test_upload_build(self, mock_upload_artifact, mock_tar_directory):
+    """Test uploading build."""
+    self._create_local_dir()
+
+    def mock_tar_directory_impl(_, archive_path):
+      self.fs.create_file(archive_path)
+
+    mock_tar_directory.side_effect = mock_tar_directory_impl
+
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    filestore.upload_build('sanitizer', self.local_dir)
+    self.assert_upload(mock_upload_artifact, mock_tar_directory,
+                       'build-sanitizer')
+
+  @mock.patch('filestore.github_actions.tar_directory')
+  @mock.patch('filestore.github_actions._upload_artifact_with_upload_js')
+  def test_upload_coverage(self, mock_upload_artifact, mock_tar_directory):
+    """Test uploading coverage."""
+    self._create_local_dir()
+
+    def mock_tar_directory_impl(_, archive_path):
+      self.fs.create_file(archive_path)
+
+    mock_tar_directory.side_effect = mock_tar_directory_impl
+
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    filestore.upload_coverage('latest', self.local_dir)
+    self.assert_upload(mock_upload_artifact, mock_tar_directory,
+                       'coverage-latest')
+
+  def assert_upload(self, mock_upload_artifact, mock_tar_directory,
+                    expected_artifact_name):
+    """Tests that upload_directory invokes tar_directory and
+    artifact_client.upload_artifact properly."""
+    # Don't assert what second argument will be since it's a temporary
+    # directory.
+    self.assertEqual(mock_tar_directory.call_args_list[0][0][0], self.local_dir)
+
+    # Don't assert what second and third arguments will be since they are
+    # temporary directories.
+    expected_artifact_name = 'cifuzz-' + expected_artifact_name
+    self.assertEqual(mock_upload_artifact.call_args_list[0][0][0],
+                     expected_artifact_name)
+
+    # Assert artifacts list contains one tarfile.
+    artifacts_list = mock_upload_artifact.call_args_list[0][0][1]
+    self.assertEqual(len(artifacts_list), 1)
+    self.assertEqual(os.path.basename(artifacts_list[0]),
+                     expected_artifact_name + '.tar')
+
+  def _create_local_dir(self):
+    """Sets up pyfakefs and creates a corpus directory containing
+    self.testcase."""
+    self.setUpPyfakefs()
+    self.fs.create_file(self.testcase, contents='hi')
+
+  @mock.patch('filestore.github_actions.GithubActionsFilestore._find_artifact')
+  @mock.patch('http_utils.download_and_unpack_zip')
+  def test_download_artifact(self, mock_download_and_unpack_zip,
+                             mock_find_artifact):
+    """Tests that _download_artifact works as intended."""
+    artifact_download_url = 'http://example.com/download'
+    artifact_listing = {
+        'expired': False,
+        'name': 'corpus',
+        'archive_download_url': artifact_download_url
+    }
+    mock_find_artifact.return_value = artifact_listing
+
+    self._create_local_dir()
+    with tempfile.TemporaryDirectory() as temp_dir:
+      # Create a tarball.
+      archive_path = os.path.join(temp_dir, 'cifuzz-corpus.tar')
+      github_actions.tar_directory(self.local_dir, archive_path)
+
+      artifact_download_dst_dir = os.path.join(temp_dir, 'dst')
+      os.mkdir(artifact_download_dst_dir)
+
+      def mock_download_and_unpack_zip_impl(url, download_artifact_temp_dir,
+                                            headers):
+        self.assertEqual(url, artifact_download_url)
+        self.assertEqual(headers, self._get_expected_http_headers())
+        shutil.copy(
+            archive_path,
+            os.path.join(download_artifact_temp_dir,
+                         os.path.basename(archive_path)))
+        return True
+
+      mock_download_and_unpack_zip.side_effect = (
+          mock_download_and_unpack_zip_impl)
+      filestore = github_actions.GithubActionsFilestore(self.config)
+      self.assertTrue(
+          filestore._download_artifact('corpus', artifact_download_dst_dir))
+      mock_find_artifact.assert_called_with('cifuzz-corpus')
+      self.assertTrue(
+          os.path.exists(
+              os.path.join(artifact_download_dst_dir,
+                           os.path.basename(self.testcase))))
+
+  @mock.patch('filestore.github_actions.github_api.list_artifacts')
+  def test_find_artifact(self, mock_list_artifacts):
+    """Tests that _find_artifact works as intended."""
+    artifact_listing_1 = {
+        'expired': False,
+        'name': 'other',
+        'archive_download_url': 'http://download1'
+    }
+    artifact_listing_2 = {
+        'expired': False,
+        'name': 'artifact',
+        'archive_download_url': 'http://download2'
+    }
+    artifact_listing_3 = {
+        'expired': True,
+        'name': 'artifact',
+        'archive_download_url': 'http://download3'
+    }
+    artifact_listing_4 = {
+        'expired': False,
+        'name': 'artifact',
+        'archive_download_url': 'http://download4'
+    }
+    artifacts = [
+        artifact_listing_1, artifact_listing_2, artifact_listing_3,
+        artifact_listing_4
+    ]
+    mock_list_artifacts.return_value = artifacts
+    filestore = github_actions.GithubActionsFilestore(self.config)
+    # Test that find_artifact will return the most recent unexpired artifact
+    # with the correct name.
+    self.assertEqual(filestore._find_artifact('artifact'), artifact_listing_2)
+    mock_list_artifacts.assert_called_with(self.owner, self.repo,
+                                           self._get_expected_http_headers())
+
+
+class TarDirectoryTest(unittest.TestCase):
+  """Tests for tar_directory."""
+
+  def test_tar_directory(self):
+    """Tests that tar_directory writes the archive to the correct location and
+    archives properly."""
+    with tempfile.TemporaryDirectory() as temp_dir:
+      archive_path = os.path.join(temp_dir, 'myarchive.tar')
+      archived_dir = os.path.join(temp_dir, 'toarchive')
+      os.mkdir(archived_dir)
+      archived_filename = 'file1'
+      archived_file_path = os.path.join(archived_dir, archived_filename)
+      with open(archived_file_path, 'w') as file_handle:
+        file_handle.write('hi')
+      github_actions.tar_directory(archived_dir, archive_path)
+      self.assertTrue(os.path.exists(archive_path))
+
+      # Now check it archives correctly.
+      unpacked_directory = os.path.join(temp_dir, 'unpacked')
+      with tarfile.TarFile(archive_path) as artifact_tarfile:
+        artifact_tarfile.extractall(unpacked_directory)
+      unpacked_archived_file_path = os.path.join(unpacked_directory,
+                                                 archived_filename)
+      self.assertTrue(os.path.exists(unpacked_archived_file_path))
diff --git a/infra/cifuzz/filestore/github_actions/github_api.py b/infra/cifuzz/filestore/github_actions/github_api.py
new file mode 100644
index 0000000..191b750
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/github_api.py
@@ -0,0 +1,108 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Module for dealing with the GitHub API. This is different from
+github_actions_toolkit which only deals with the actions API. We need to use
+both."""
+import logging
+import os
+import sys
+
+import requests
+
+import filestore
+
+# pylint: disable=wrong-import-position,import-error
+
+sys.path.append(
+    os.path.join(__file__, os.path.pardir, os.path.pardir, os.path.pardir,
+                 os.path.pardir))
+import retry
+
+_MAX_ITEMS_PER_PAGE = 100
+
+_GET_ATTEMPTS = 3
+_GET_BACKOFF = 1
+
+
+def get_http_auth_headers(config):
+  """Returns HTTP headers for authentication to the API."""
+  authorization = f'token {config.token}'
+  return {
+      'Authorization': authorization,
+      'Accept': 'application/vnd.github.v3+json'
+  }
+
+
+def _get_artifacts_list_api_url(repo_owner, repo_name):
+  """Returns the artifacts_api_url for |repo_name| owned by |repo_owner|."""
+  return (f'https://api.github.com/repos/{repo_owner}/'
+          f'{repo_name}/actions/artifacts')
+
+
+@retry.wrap(_GET_ATTEMPTS, _GET_BACKOFF)
+def _do_get_request(*args, **kwargs):
+  """Wrapped version of requests.get that does retries."""
+  return requests.get(*args, **kwargs)
+
+
+def _get_items(url, headers):
+  """Generator that gets and yields items from a GitHub API endpoint (specified
+  by |URL|) sending |headers| with the get request."""
+  # Github API response pages are 1-indexed.
+  page_counter = 1
+
+  # Set to infinity so we run loop at least once.
+  total_num_items = float('inf')
+
+  item_num = 0
+  while item_num < total_num_items:
+    params = {'per_page': _MAX_ITEMS_PER_PAGE, 'page': str(page_counter)}
+    response = _do_get_request(url, params=params, headers=headers)
+    response_json = response.json()
+    if not response.status_code == 200:
+      # Check that request was successful.
+      logging.error('Request to %s failed. Code: %d. Response: %s',
+                    response.request.url, response.status_code, response_json)
+      raise filestore.FilestoreError('Github API request failed.')
+
+    if total_num_items == float('inf'):
+      # Set proper total_num_items
+      total_num_items = response_json['total_count']
+
+    # Get the key for the items we are after.
+    keys = [key for key in response_json.keys() if key != 'total_count']
+    assert len(keys) == 1, keys
+    items_key = keys[0]
+
+    for item in response_json[items_key]:
+      yield item
+      item_num += 1
+
+    page_counter += 1
+
+
+def find_artifact(artifact_name, artifacts):
+  """Find the artifact with the name |artifact_name| in |artifacts|."""
+  for artifact in artifacts:
+    # TODO(metzman): Handle multiple by making sure we download the latest.
+    if artifact['name'] == artifact_name and not artifact['expired']:
+      return artifact
+  return None
+
+
+def list_artifacts(owner, repo, headers):
+  """Returns a generator of all the artifacts for |owner|/|repo|."""
+  url = _get_artifacts_list_api_url(owner, repo)
+  logging.debug('Getting artifacts from: %s', url)
+  return _get_items(url, headers)
diff --git a/infra/cifuzz/filestore/github_actions/github_api_test.py b/infra/cifuzz/filestore/github_actions/github_api_test.py
new file mode 100644
index 0000000..c7cad6d
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/github_api_test.py
@@ -0,0 +1,33 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for github_api."""
+import unittest
+
+from filestore.github_actions import github_api
+import test_helpers
+
+
+class GetHttpAuthHeaders(unittest.TestCase):
+  """Tests for get_http_auth_headers."""
+
+  def test_get_http_auth_headers(self):
+    """Tests that get_http_auth_headers returns the correct result."""
+    token = 'example githubtoken'
+    run_config = test_helpers.create_run_config(token=token)
+    expected_headers = {
+        'Authorization': f'token {token}',
+        'Accept': 'application/vnd.github.v3+json',
+    }
+    self.assertEqual(expected_headers,
+                     github_api.get_http_auth_headers(run_config))
diff --git a/infra/cifuzz/filestore/github_actions/upload.js b/infra/cifuzz/filestore/github_actions/upload.js
new file mode 100755
index 0000000..cd025e5
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/upload.js
@@ -0,0 +1,33 @@
+#!/usr/bin/env node
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Script for uploading an artifact. Returns 0 on success.
+// Usage: upload.js <aritfactName> <rootDirectory> <file 1>...<file N>
+
+const fs = require('fs');
+const artifact = require('@actions/artifact');
+const artifactClient = artifact.create()
+const artifactName = process.argv[2];
+const rootDirectory = process.argv[3]
+const files = process.argv.slice(4);
+const options = {
+    continueOnError: true
+}
+
+const uploadResult = artifactClient.uploadArtifact(artifactName, files, rootDirectory, options)
+console.log(uploadResult);
+if (uploadResult['failedItems']) {
+  return 1;
+}
+return 0;
diff --git a/infra/cifuzz/filestore_utils.py b/infra/cifuzz/filestore_utils.py
new file mode 100644
index 0000000..d3aaecd
--- /dev/null
+++ b/infra/cifuzz/filestore_utils.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""External filestore interface. Cannot be depended on by filestore code."""
+import filestore
+import filestore.git
+import filestore.github_actions
+
+
+def get_filestore(config):
+  """Returns the correct filestore based on the platform in |config|.
+  Raises an exception if there is no correct filestore for the platform."""
+  # TODO(metzman): Force specifying of filestore.
+  if config.platform == config.Platform.EXTERNAL_GITHUB:
+    ci_filestore = filestore.github_actions.GithubActionsFilestore(config)
+    if not config.git_store_repo:
+      return ci_filestore
+
+    return filestore.git.GitFilestore(config, ci_filestore)
+
+  raise filestore.FilestoreError('Filestore doesn\'t support platform.')
diff --git a/infra/cifuzz/filestore_utils_test.py b/infra/cifuzz/filestore_utils_test.py
new file mode 100644
index 0000000..db5fc5b
--- /dev/null
+++ b/infra/cifuzz/filestore_utils_test.py
@@ -0,0 +1,50 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for filestore_utils."""
+import unittest
+from unittest import mock
+
+import parameterized
+
+import config_utils
+import filestore
+from filestore import github_actions
+import filestore_utils
+import test_helpers
+
+
+class GetFilestoreTest(unittest.TestCase):
+  """Tests for get_filestore."""
+
+  @parameterized.parameterized.expand([
+      ({
+          'is_github': True,
+      }, github_actions.GithubActionsFilestore),
+  ])
+  def test_get_filestore(self, config_kwargs, filestore_cls):
+    """Tests that get_filestore returns the right filestore given a certain
+    platform."""
+    run_config = test_helpers.create_run_config(**config_kwargs)
+    filestore_impl = filestore_utils.get_filestore(run_config)
+    self.assertIsInstance(filestore_impl, filestore_cls)
+
+  @mock.patch('config_utils.BaseConfig.platform', return_value='other')
+  @mock.patch('config_utils._get_ci_environment',
+              return_value=config_utils.GenericCiEnvironment())
+  def test_get_filestore_unsupported_platform(self, _, __):
+    """Tests that get_filestore exceptions given a platform it doesn't
+    support."""
+    run_config = test_helpers.create_run_config()
+    with self.assertRaises(filestore.FilestoreError):
+      filestore_utils.get_filestore(run_config)
diff --git a/infra/cifuzz/fuzz_target.py b/infra/cifuzz/fuzz_target.py
index c623bf6..ae92b14 100644
--- a/infra/cifuzz/fuzz_target.py
+++ b/infra/cifuzz/fuzz_target.py
@@ -15,17 +15,13 @@
 import collections
 import logging
 import os
-import re
 import shutil
 import stat
-import subprocess
-import sys
 
-import docker
+import clusterfuzz.environment
+import clusterfuzz.fuzz
 
-# pylint: disable=wrong-import-position,import-error
-sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-import utils
+import config_utils
 
 logging.basicConfig(
     format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
@@ -33,46 +29,59 @@
 
 # Use a fixed seed for determinism. Use len_control=0 since we don't have enough
 # time fuzzing for len_control to make sense (probably).
-LIBFUZZER_OPTIONS = '-seed=1337 -len_control=0'
+LIBFUZZER_OPTIONS = ['-seed=1337', '-len_control=0']
 
 # The number of reproduce attempts for a crash.
 REPRODUCE_ATTEMPTS = 10
 
+REPRODUCE_TIME_SECONDS = 30
+
 # Seconds on top of duration until a timeout error is raised.
 BUFFER_TIME = 10
 
 # Log message if we can't check if crash reproduces on an recent build.
-COULD_NOT_TEST_ON_RECENT_MESSAGE = (
-    'Crash is reproducible. Could not run recent build of '
-    'target to determine if this code change (pr/commit) introduced crash. '
-    'Assuming this code change introduced crash.')
+COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE = (
+    'Could not run previous build of target to determine if this code change '
+    '(pr/commit) introduced crash. Assuming crash was newly introduced.')
 
-FuzzResult = collections.namedtuple('FuzzResult', ['testcase', 'stacktrace'])
+FuzzResult = collections.namedtuple('FuzzResult',
+                                    ['testcase', 'stacktrace', 'corpus_path'])
 
 
 class ReproduceError(Exception):
   """Error for when we can't attempt to reproduce a crash."""
 
 
-class FuzzTarget:
+def get_fuzz_target_corpus_dir(workspace, target_name):
+  """Returns the directory for storing |target_name|'s corpus in |workspace|."""
+  return os.path.join(workspace.corpora, target_name)
+
+
+def get_fuzz_target_pruned_corpus_dir(workspace, target_name):
+  """Returns the directory for storing |target_name|'s puned corpus in
+  |workspace|."""
+  return os.path.join(workspace.pruned_corpora, target_name)
+
+
+class FuzzTarget:  # pylint: disable=too-many-instance-attributes
   """A class to manage a single fuzz target.
 
   Attributes:
     target_name: The name of the fuzz target.
     duration: The length of time in seconds that the target should run.
     target_path: The location of the fuzz target binary.
-    out_dir: The location of where output artifacts are stored.
+    workspace: The workspace for storing things related to fuzzing.
   """
 
   # pylint: disable=too-many-arguments
-  def __init__(self, target_path, duration, out_dir, clusterfuzz_deployment,
+  def __init__(self, target_path, duration, workspace, clusterfuzz_deployment,
                config):
     """Represents a single fuzz target.
 
     Args:
       target_path: The location of the fuzz target binary.
       duration: The length of time  in seconds the target should run.
-      out_dir: The location of where the output from crashes should be stored.
+      workspace: The path used for storing things needed for fuzzing.
       clusterfuzz_deployment: The object representing the ClusterFuzz
           deployment.
       config: The config of this project.
@@ -80,10 +89,39 @@
     self.target_path = target_path
     self.target_name = os.path.basename(self.target_path)
     self.duration = int(duration)
-    self.out_dir = out_dir
+    self.workspace = workspace
     self.clusterfuzz_deployment = clusterfuzz_deployment
     self.config = config
-    self.latest_corpus_path = None
+    self.latest_corpus_path = get_fuzz_target_corpus_dir(
+        self.workspace, self.target_name)
+    os.makedirs(self.latest_corpus_path, exist_ok=True)
+    self.pruned_corpus_path = get_fuzz_target_pruned_corpus_dir(
+        self.workspace, self.target_name)
+    os.makedirs(self.pruned_corpus_path, exist_ok=True)
+
+  def _download_corpus(self):
+    """Downloads the corpus for the target from ClusterFuzz and returns the path
+    to the corpus. An empty directory is provided if the corpus can't be
+    downloaded or is empty."""
+    self.clusterfuzz_deployment.download_corpus(self.target_name,
+                                                self.latest_corpus_path)
+    return self.latest_corpus_path
+
+  def prune(self):
+    """Prunes the corpus and returns the result."""
+    self._download_corpus()
+    with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
+                                             self.config.sanitizer,
+                                             self.target_path,
+                                             interactive=True):
+      engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE)
+      result = engine_impl.minimize_corpus(self.target_path, [],
+                                           [self.latest_corpus_path],
+                                           self.pruned_corpus_path,
+                                           self.workspace.artifacts,
+                                           self.duration)
+
+    return FuzzResult(None, result.logs, self.pruned_corpus_path)
 
   def fuzz(self):
     """Starts the fuzz target run for the length of time specified by duration.
@@ -91,85 +129,65 @@
     Returns:
       FuzzResult namedtuple with stacktrace and testcase if applicable.
     """
-    logging.info('Fuzzer %s, started.', self.target_name)
-    docker_container = utils.get_container_name()
-    command = ['docker', 'run', '--rm', '--privileged']
-    if docker_container:
-      command += [
-          '--volumes-from', docker_container, '-e', 'OUT=' + self.out_dir
-      ]
-    else:
-      command += ['-v', '%s:%s' % (self.out_dir, '/out')]
+    logging.info('Running fuzzer: %s.', self.target_name)
 
-    command += [
-        '-e', 'FUZZING_ENGINE=libfuzzer', '-e',
-        'SANITIZER=' + self.config.sanitizer, '-e', 'CIFUZZ=True', '-e',
-        'RUN_FUZZER_MODE=interactive', docker.BASE_RUNNER_TAG, 'bash', '-c'
-    ]
+    self._download_corpus()
+    corpus_path = self.latest_corpus_path
 
-    run_fuzzer_command = 'run_fuzzer {fuzz_target} {options}'.format(
-        fuzz_target=self.target_name,
-        options=LIBFUZZER_OPTIONS + ' -max_total_time=' + str(self.duration))
+    logging.info('Starting fuzzing')
+    with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
+                                             self.config.sanitizer,
+                                             self.target_path,
+                                             interactive=True) as env:
+      engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE)
+      options = engine_impl.prepare(corpus_path, env.target_path, env.build_dir)
+      options.merge_back_new_testcases = False
+      options.analyze_dictionary = False
+      options.arguments.extend(LIBFUZZER_OPTIONS)
 
-    # If corpus can be downloaded use it for fuzzing.
-    self.latest_corpus_path = self.clusterfuzz_deployment.download_corpus(
-        self.target_name, self.out_dir)
-    if self.latest_corpus_path:
-      run_fuzzer_command = run_fuzzer_command + ' ' + self.latest_corpus_path
-    command.append(run_fuzzer_command)
-
-    logging.info('Running command: %s', ' '.join(command))
-    process = subprocess.Popen(command,
-                               stdout=subprocess.PIPE,
-                               stderr=subprocess.PIPE)
-
-    try:
-      _, stderr = process.communicate(timeout=self.duration + BUFFER_TIME)
-    except subprocess.TimeoutExpired:
-      logging.error('Fuzzer %s timed out, ending fuzzing.', self.target_name)
-      return FuzzResult(None, None)
+      result = engine_impl.fuzz(self.target_path, options,
+                                self.workspace.artifacts, self.duration)
 
     # Libfuzzer timeout was reached.
-    if not process.returncode:
+    if not result.crashes:
       logging.info('Fuzzer %s finished with no crashes discovered.',
                    self.target_name)
-      return FuzzResult(None, None)
+      return FuzzResult(None, None, self.latest_corpus_path)
 
-    # Crash was discovered.
-    logging.info('Fuzzer %s, ended before timeout.', self.target_name)
-    testcase = self.get_testcase(stderr)
-    if not testcase:
-      logging.error(b'No testcase found in stacktrace: %s.', stderr)
-      return FuzzResult(None, None)
+    # Only report first crash.
+    crash = result.crashes[0]
+    logging.info('Fuzzer: %s. Detected bug:\n%s', self.target_name,
+                 crash.stacktrace)
 
-    utils.binary_print(b'Fuzzer: %s. Detected bug:\n%s' %
-                       (self.target_name.encode(), stderr))
-    if self.is_crash_reportable(testcase):
+    if self.is_crash_reportable(crash.input_path):
       # We found a bug in the fuzz target and we will report it.
-      return FuzzResult(testcase, stderr)
+      return FuzzResult(crash.input_path, result.logs, self.latest_corpus_path)
 
     # We found a bug but we won't report it.
-    return FuzzResult(None, None)
+    return FuzzResult(None, None, self.latest_corpus_path)
 
-  def free_disk_if_needed(self):
+  def free_disk_if_needed(self, delete_fuzz_target=True):
     """Deletes things that are no longer needed from fuzzing this fuzz target to
     save disk space if needed."""
     if not self.config.low_disk_space:
+      logging.info('Not freeing disk space after running fuzz target.')
       return
-    logging.info(
-        'Deleting corpus, seed corpus and fuzz target of %s to save disk.',
-        self.target_name)
+    logging.info('Deleting corpus and seed corpus of %s to save disk.',
+                 self.target_name)
 
     # Delete the seed corpus, corpus, and fuzz target.
-    if self.latest_corpus_path and os.path.exists(self.latest_corpus_path):
+    for corpus_path in [self.latest_corpus_path, self.pruned_corpus_path]:
       # Use ignore_errors=True to fix
       # https://github.com/google/oss-fuzz/issues/5383.
-      shutil.rmtree(self.latest_corpus_path, ignore_errors=True)
+      shutil.rmtree(corpus_path, ignore_errors=True)
 
-    os.remove(self.target_path)
     target_seed_corpus_path = self.target_path + '_seed_corpus.zip'
     if os.path.exists(target_seed_corpus_path):
       os.remove(target_seed_corpus_path)
+
+    if delete_fuzz_target:
+      logging.info('Deleting fuzz target: %s.', self.target_name)
+      os.remove(self.target_path)
     logging.info('Done deleting.')
 
   def is_reproducible(self, testcase, target_path):
@@ -186,41 +204,31 @@
       Raises:
         ReproduceError if we can't attempt to reproduce the crash.
     """
-
     if not os.path.exists(target_path):
-      raise ReproduceError('Target %s not found.' % target_path)
+      logging.info('Target: %s does not exist.', target_path)
+      raise ReproduceError(f'Target {target_path} not found.')
 
     os.chmod(target_path, stat.S_IRWXO)
 
-    target_dirname = os.path.dirname(target_path)
-    command = ['docker', 'run', '--rm', '--privileged']
-    container = utils.get_container_name()
-    if container:
-      command += [
-          '--volumes-from', container, '-e', 'OUT=' + target_dirname, '-e',
-          'TESTCASE=' + testcase
-      ]
-    else:
-      command += [
-          '-v',
-          '%s:/out' % target_dirname, '-v',
-          '%s:/testcase' % testcase
-      ]
+    logging.info('Trying to reproduce crash using: %s.', testcase)
+    with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
+                                             self.config.sanitizer,
+                                             target_path,
+                                             interactive=True):
+      for _ in range(REPRODUCE_ATTEMPTS):
+        engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE)
+        result = engine_impl.reproduce(target_path,
+                                       testcase,
+                                       arguments=[],
+                                       max_time=REPRODUCE_TIME_SECONDS)
 
-    command += [
-        '-t', docker.BASE_RUNNER_TAG, 'reproduce', self.target_name, '-runs=100'
-    ]
+        if result.return_code != 0:
+          logging.info('Reproduce command returned: %s. Reproducible on %s.',
+                       result.return_code, target_path)
 
-    logging.info('Running reproduce command: %s.', ' '.join(command))
-    for _ in range(REPRODUCE_ATTEMPTS):
-      _, _, returncode = utils.execute(command)
-      if returncode != 0:
-        logging.info('Reproduce command returned: %s. Reproducible on %s.',
-                     returncode, target_path)
+          return True
 
-        return True
-
-    logging.info('Reproduce command returned 0. Not reproducible on %s.',
+    logging.info('Reproduce command returned: 0. Not reproducible on %s.',
                  target_path)
     return False
 
@@ -239,60 +247,52 @@
       ReproduceError if we can't attempt to reproduce the crash on the PR build.
     """
     if not os.path.exists(testcase):
-      raise ReproduceError('Testcase %s not found.' % testcase)
+      raise ReproduceError(f'Testcase {testcase} not found.')
 
     try:
       reproducible_on_code_change = self.is_reproducible(
           testcase, self.target_path)
     except ReproduceError as error:
-      logging.error('Could not run target when checking for reproducibility.'
+      logging.error('Could not check for crash reproducibility.'
                     'Please file an issue:'
                     'https://github.com/google/oss-fuzz/issues/new.')
       raise error
 
     if not reproducible_on_code_change:
-      logging.info('Failed to reproduce the crash using the obtained testcase.')
-      return False
+      logging.info('Crash is not reproducible.')
+      return self.config.report_unreproducible_crashes
 
-    clusterfuzz_build_dir = self.clusterfuzz_deployment.download_latest_build(
-        self.out_dir)
+    logging.info('Crash is reproducible.')
+    return self.is_crash_novel(testcase)
+
+  def is_crash_novel(self, testcase):
+    """Returns whether or not the crash is new. A crash is considered new if it
+    can't be reproduced on an older ClusterFuzz build of the target."""
+    if not os.path.exists(testcase):
+      raise ReproduceError('Testcase %s not found.' % testcase)
+    clusterfuzz_build_dir = self.clusterfuzz_deployment.download_latest_build()
     if not clusterfuzz_build_dir:
       # Crash is reproducible on PR build and we can't test on a recent
       # ClusterFuzz/OSS-Fuzz build.
-      logging.info(COULD_NOT_TEST_ON_RECENT_MESSAGE)
+      logging.info(COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE)
       return True
 
     clusterfuzz_target_path = os.path.join(clusterfuzz_build_dir,
                                            self.target_name)
+
     try:
       reproducible_on_clusterfuzz_build = self.is_reproducible(
           testcase, clusterfuzz_target_path)
     except ReproduceError:
       # This happens if the project has ClusterFuzz builds, but the fuzz target
       # is not in it (e.g. because the fuzz target is new).
-      logging.info(COULD_NOT_TEST_ON_RECENT_MESSAGE)
+      logging.info(COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE)
       return True
 
-    if not reproducible_on_clusterfuzz_build:
-      logging.info('The crash is reproducible. The crash doesn\'t reproduce '
-                   'on old builds. This code change probably introduced the '
-                   'crash.')
-      return True
-
-    logging.info('The crash is reproducible on old builds '
-                 '(without the current code change).')
-    return False
-
-  def get_testcase(self, error_bytes):
-    """Gets the file from a fuzzer run stacktrace.
-
-    Args:
-      error_bytes: The bytes containing the output from the fuzzer.
-
-    Returns:
-      The path to the testcase or None if not found.
-    """
-    match = re.search(rb'\bTest unit written to \.\/([^\s]+)', error_bytes)
-    if match:
-      return os.path.join(self.out_dir, match.group(1).decode('utf-8'))
-    return None
+    if reproducible_on_clusterfuzz_build:
+      logging.info('The crash is reproducible on previous build. '
+                   'Code change (pr/commit) did not introduce crash.')
+      return False
+    logging.info('The crash is not reproducible on previous build. '
+                 'Code change (pr/commit) introduced crash.')
+    return True
diff --git a/infra/cifuzz/fuzz_target_test.py b/infra/cifuzz/fuzz_target_test.py
index 8bec234..ecea6fb 100644
--- a/infra/cifuzz/fuzz_target_test.py
+++ b/infra/cifuzz/fuzz_target_test.py
@@ -18,12 +18,18 @@
 import unittest
 from unittest import mock
 
+import certifi
+# Importing this later causes import failures with pytest for some reason.
+# TODO(ochang): Figure out why.
 import parameterized
+import google.cloud.ndb  # pylint: disable=unused-import
 from pyfakefs import fake_filesystem_unittest
+from clusterfuzz.fuzz import engine
 
 import clusterfuzz_deployment
-import config_utils
 import fuzz_target
+import test_helpers
+import workspace_utils
 
 # NOTE: This integration test relies on
 # https://github.com/google/oss-fuzz/tree/master/projects/example project.
@@ -32,153 +38,118 @@
 # An example fuzzer that triggers an error.
 EXAMPLE_FUZZER = 'example_crash_fuzzer'
 
-# The return value of a successful call to utils.execute.
-EXECUTE_SUCCESS_RETVAL = ('', '', 0)
-
-# The return value of a failed call to utils.execute.
-EXECUTE_FAILURE_RETVAL = ('', '', 1)
+# Mock return values for engine_impl.reproduce.
+EXECUTE_SUCCESS_RESULT = engine.ReproduceResult([], 0, 0, '')
+EXECUTE_FAILURE_RESULT = engine.ReproduceResult([], 1, 0, '')
 
 
 def _create_config(**kwargs):
   """Creates a config object and then sets every attribute that is a key in
   |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an
   attribute of Config."""
-  defaults = {'is_github': True, 'project_name': EXAMPLE_PROJECT}
+  defaults = {
+      'is_github': True,
+      'oss_fuzz_project_name': EXAMPLE_PROJECT,
+      'workspace': '/workspace'
+  }
   for default_key, default_value in defaults.items():
     if default_key not in kwargs:
       kwargs[default_key] = default_value
 
-  with mock.patch('os.path.basename', return_value=None), mock.patch(
-      'config_utils.get_project_src_path',
-      return_value=None), mock.patch('config_utils._is_dry_run',
-                                     return_value=True):
-    config = config_utils.RunFuzzersConfig()
-
-  for key, value in kwargs.items():
-    assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
-    setattr(config, key, value)
-  return config
+  return test_helpers.create_run_config(**kwargs)
 
 
 def _create_deployment(**kwargs):
   config = _create_config(**kwargs)
-  return clusterfuzz_deployment.get_clusterfuzz_deployment(config)
+  workspace = workspace_utils.Workspace(config)
+  return clusterfuzz_deployment.get_clusterfuzz_deployment(config, workspace)
 
 
-# TODO(metzman): Use patch from test_libs/helpers.py in clusterfuzz so that we
-# don't need to accept this as an argument in every test method.
 @mock.patch('utils.get_container_name', return_value='container')
 class IsReproducibleTest(fake_filesystem_unittest.TestCase):
   """Tests the is_reproducible method in the fuzz_target.FuzzTarget class."""
 
   def setUp(self):
     """Sets up example fuzz target to test is_reproducible method."""
-    self.fuzz_target_path = '/example/path'
-    self.testcase_path = '/testcase'
+    self.fuzz_target_name = 'fuzz-target'
     deployment = _create_deployment()
-    self.test_target = fuzz_target.FuzzTarget(self.fuzz_target_path,
-                                              fuzz_target.REPRODUCE_ATTEMPTS,
-                                              '/example/outdir', deployment,
-                                              deployment.config)
+    self.config = deployment.config
+    self.workspace = deployment.workspace
+    self.fuzz_target_path = os.path.join(self.workspace.out,
+                                         self.fuzz_target_name)
+    self.setUpPyfakefs()
+    self.fs.create_file(self.fuzz_target_path)
+    self.testcase_path = '/testcase'
+    self.fs.create_file(self.testcase_path)
+
+    self.target = fuzz_target.FuzzTarget(self.fuzz_target_path,
+                                         fuzz_target.REPRODUCE_ATTEMPTS,
+                                         self.workspace, deployment,
+                                         deployment.config)
+
+    # ClusterFuzz requires ROOT_DIR.
+    root_dir = os.environ['ROOT_DIR']
+    test_helpers.patch_environ(self, empty=True)
+    os.environ['ROOT_DIR'] = root_dir
 
   def test_reproducible(self, _):
     """Tests that is_reproducible returns True if crash is detected and that
     is_reproducible uses the correct command to reproduce a crash."""
-    self._set_up_fakefs()
-    all_repro = [EXECUTE_FAILURE_RETVAL] * fuzz_target.REPRODUCE_ATTEMPTS
-    with mock.patch('utils.execute', side_effect=all_repro) as mocked_execute:
-      result = self.test_target.is_reproducible(self.testcase_path,
-                                                self.fuzz_target_path)
-      mocked_execute.assert_called_once_with([
-          'docker', 'run', '--rm', '--privileged', '--volumes-from',
-          'container', '-e', 'OUT=/example', '-e',
-          'TESTCASE=' + self.testcase_path, '-t',
-          'gcr.io/oss-fuzz-base/base-runner', 'reproduce', 'path', '-runs=100'
-      ])
-      self.assertTrue(result)
-      self.assertEqual(1, mocked_execute.call_count)
+    all_repro = [EXECUTE_FAILURE_RESULT] * fuzz_target.REPRODUCE_ATTEMPTS
+    with mock.patch('clusterfuzz.fuzz.get_engine') as mock_get_engine:
+      mock_get_engine().reproduce.side_effect = all_repro
 
-  def _set_up_fakefs(self):
-    """Helper to setup pyfakefs and add important files to the fake
-    filesystem."""
-    self.setUpPyfakefs()
-    self.fs.create_file(self.fuzz_target_path)
-    self.fs.create_file(self.testcase_path)
+      result = self.target.is_reproducible(self.testcase_path,
+                                           self.fuzz_target_path)
+      mock_get_engine().reproduce.assert_called_once_with(
+          '/workspace/build-out/fuzz-target',
+          '/testcase',
+          arguments=[],
+          max_time=30)
+      self.assertTrue(result)
+      self.assertEqual(1, mock_get_engine().reproduce.call_count)
 
   def test_flaky(self, _):
     """Tests that is_reproducible returns True if crash is detected on the last
     attempt."""
-    self._set_up_fakefs()
-    last_time_repro = [EXECUTE_SUCCESS_RETVAL] * 9 + [EXECUTE_FAILURE_RETVAL]
-    with mock.patch('utils.execute',
-                    side_effect=last_time_repro) as mocked_execute:
+    last_time_repro = [EXECUTE_SUCCESS_RESULT] * 9 + [EXECUTE_FAILURE_RESULT]
+    with mock.patch('clusterfuzz.fuzz.get_engine') as mock_get_engine:
+      mock_get_engine().reproduce.side_effect = last_time_repro
       self.assertTrue(
-          self.test_target.is_reproducible(self.testcase_path,
-                                           self.fuzz_target_path))
+          self.target.is_reproducible(self.testcase_path,
+                                      self.fuzz_target_path))
       self.assertEqual(fuzz_target.REPRODUCE_ATTEMPTS,
-                       mocked_execute.call_count)
+                       mock_get_engine().reproduce.call_count)
 
   def test_nonexistent_fuzzer(self, _):
     """Tests that is_reproducible raises an error if it could not attempt
     reproduction because the fuzzer doesn't exist."""
     with self.assertRaises(fuzz_target.ReproduceError):
-      self.test_target.is_reproducible(self.testcase_path, '/non-existent-path')
+      self.target.is_reproducible(self.testcase_path, '/non-existent-path')
 
   def test_unreproducible(self, _):
     """Tests that is_reproducible returns False for a crash that did not
     reproduce."""
-    all_unrepro = [EXECUTE_SUCCESS_RETVAL] * fuzz_target.REPRODUCE_ATTEMPTS
-    self._set_up_fakefs()
-    with mock.patch('utils.execute', side_effect=all_unrepro):
-      result = self.test_target.is_reproducible(self.testcase_path,
-                                                self.fuzz_target_path)
+    all_unrepro = [EXECUTE_SUCCESS_RESULT] * fuzz_target.REPRODUCE_ATTEMPTS
+    with mock.patch('clusterfuzz.fuzz.get_engine') as mock_get_engine:
+      mock_get_engine().reproduce.side_effect = all_unrepro
+      result = self.target.is_reproducible(self.testcase_path,
+                                           self.fuzz_target_path)
       self.assertFalse(result)
 
 
-class GetTestCaseTest(unittest.TestCase):
-  """Tests get_testcase."""
-
-  def setUp(self):
-    """Sets up example fuzz target to test get_testcase method."""
-    deployment = _create_deployment()
-    self.test_target = fuzz_target.FuzzTarget('/example/path', 10,
-                                              '/example/outdir', deployment,
-                                              deployment.config)
-
-  def test_valid_error_string(self):
-    """Tests that get_testcase returns the correct testcase give an error."""
-    testcase_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                                 'test_data', 'example_crash_fuzzer_output.txt')
-    with open(testcase_path, 'rb') as test_fuzz_output:
-      parsed_testcase = self.test_target.get_testcase(test_fuzz_output.read())
-    self.assertEqual(
-        parsed_testcase,
-        '/example/outdir/crash-ad6700613693ef977ff3a8c8f4dae239c3dde6f5')
-
-  def test_invalid_error_string(self):
-    """Tests that get_testcase returns None with a bad error string."""
-    self.assertIsNone(self.test_target.get_testcase(b''))
-    self.assertIsNone(self.test_target.get_testcase(b' Example crash string.'))
-
-  def test_encoding(self):
-    """Tests that get_testcase accepts bytes and returns a string."""
-    fuzzer_output = b'\x8fTest unit written to ./crash-1'
-    result = self.test_target.get_testcase(fuzzer_output)
-    self.assertTrue(isinstance(result, str))
-
-
 class IsCrashReportableTest(fake_filesystem_unittest.TestCase):
   """Tests the is_crash_reportable method of FuzzTarget."""
 
   def setUp(self):
     """Sets up example fuzz target to test is_crash_reportable method."""
+    self.setUpPyfakefs()
     self.fuzz_target_path = '/example/do_stuff_fuzzer'
     deployment = _create_deployment()
-    self.test_target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100,
-                                              '/example/outdir', deployment,
-                                              deployment.config)
+    self.target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100,
+                                         deployment.workspace, deployment,
+                                         deployment.config)
     self.oss_fuzz_build_path = '/oss-fuzz-build'
-    self.setUpPyfakefs()
     self.fs.create_file(self.fuzz_target_path)
     self.oss_fuzz_target_path = os.path.join(
         self.oss_fuzz_build_path, os.path.basename(self.fuzz_target_path))
@@ -186,18 +157,20 @@
     self.testcase_path = '/testcase'
     self.fs.create_file(self.testcase_path, contents='')
 
+    # Do this to prevent pyfakefs from messing with requests.
+    self.fs.add_real_directory(os.path.dirname(certifi.__file__))
+
   @mock.patch('fuzz_target.FuzzTarget.is_reproducible',
               side_effect=[True, False])
   @mock.patch('logging.info')
-  def test_new_reproducible_crash(self, mocked_info, _):
+  def test_new_reproducible_crash(self, mock_info, _):
     """Tests that a new reproducible crash returns True."""
     with tempfile.TemporaryDirectory() as tmp_dir:
-      self.test_target.out_dir = tmp_dir
-      self.assertTrue(self.test_target.is_crash_reportable(self.testcase_path))
-    mocked_info.assert_called_with(
-        'The crash is reproducible. The crash doesn\'t reproduce '
-        'on old builds. This code change probably introduced the '
-        'crash.')
+      self.target.out_dir = tmp_dir
+      self.assertTrue(self.target.is_crash_reportable(self.testcase_path))
+    mock_info.assert_called_with(
+        'The crash is not reproducible on previous build. '
+        'Code change (pr/commit) introduced crash.')
 
   # yapf: disable
   @parameterized.parameterized.expand([
@@ -218,12 +191,11 @@
                     side_effect=is_reproducible_retvals):
       with mock.patch('clusterfuzz_deployment.OSSFuzz.download_latest_build',
                       return_value=self.oss_fuzz_build_path):
-        self.assertFalse(
-            self.test_target.is_crash_reportable(self.testcase_path))
+        self.assertFalse(self.target.is_crash_reportable(self.testcase_path))
 
   @mock.patch('logging.info')
   @mock.patch('fuzz_target.FuzzTarget.is_reproducible', return_value=[True])
-  def test_reproducible_no_oss_fuzz_target(self, _, mocked_info):
+  def test_reproducible_no_oss_fuzz_target(self, _, mock_info):
     """Tests that is_crash_reportable returns True when a crash reproduces on
     the PR build but the target is not in the OSS-Fuzz build (usually because it
     is new)."""
@@ -236,17 +208,16 @@
 
     with mock.patch(
         'fuzz_target.FuzzTarget.is_reproducible',
-        side_effect=is_reproducible_side_effect) as mocked_is_reproducible:
+        side_effect=is_reproducible_side_effect) as mock_is_reproducible:
       with mock.patch('clusterfuzz_deployment.OSSFuzz.download_latest_build',
                       return_value=self.oss_fuzz_build_path):
-        self.assertTrue(self.test_target.is_crash_reportable(
-            self.testcase_path))
-    mocked_is_reproducible.assert_any_call(self.testcase_path,
-                                           self.oss_fuzz_target_path)
-    mocked_info.assert_called_with(
-        'Crash is reproducible. Could not run recent build of '
-        'target to determine if this code change (pr/commit) introduced crash. '
-        'Assuming this code change introduced crash.')
+        self.assertTrue(self.target.is_crash_reportable(self.testcase_path))
+    mock_is_reproducible.assert_any_call(self.testcase_path,
+                                         self.oss_fuzz_target_path)
+    mock_info.assert_called_with(
+        'Could not run previous build of target to determine if this code '
+        'change (pr/commit) introduced crash. Assuming crash was newly '
+        'introduced.')
 
 
 if __name__ == '__main__':
diff --git a/infra/cifuzz/generate_coverage_report.py b/infra/cifuzz/generate_coverage_report.py
new file mode 100644
index 0000000..9901c45
--- /dev/null
+++ b/infra/cifuzz/generate_coverage_report.py
@@ -0,0 +1,48 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Module for generating coverage reports."""
+import os
+
+import base_runner_utils
+import fuzz_target
+import utils
+
+
+def run_coverage_command(config, workspace):
+  """Runs the coverage command in base-runner to generate a coverage report."""
+  env = base_runner_utils.get_env(config, workspace)
+  env['HTTP_PORT'] = ''
+  env['COVERAGE_EXTRA_ARGS'] = ''
+  env['CORPUS_DIR'] = workspace.corpora
+  env['COVERAGE_OUTPUT_DIR'] = workspace.coverage_report
+  command = 'coverage'
+  return utils.execute(command, env=env)
+
+
+def download_corpora(fuzz_target_paths, clusterfuzz_deployment):
+  """Downloads corpora for fuzz targets in |fuzz_target_paths| using
+  |clusterfuzz_deployment| to download corpora from ClusterFuzz/OSS-Fuzz."""
+  for target_path in fuzz_target_paths:
+    target_name = os.path.basename(target_path)
+    corpus_dir = fuzz_target.get_fuzz_target_corpus_dir(
+        clusterfuzz_deployment.workspace, target_name)
+    clusterfuzz_deployment.download_corpus(target_name, corpus_dir)
+
+
+def generate_coverage_report(fuzz_target_paths, workspace,
+                             clusterfuzz_deployment, config):
+  """Generates a coverage report using Clang's source based coverage."""
+  download_corpora(fuzz_target_paths, clusterfuzz_deployment)
+  run_coverage_command(config, workspace)
+  clusterfuzz_deployment.upload_coverage()
diff --git a/infra/cifuzz/generate_coverage_report_test.py b/infra/cifuzz/generate_coverage_report_test.py
new file mode 100644
index 0000000..df2c9b2
--- /dev/null
+++ b/infra/cifuzz/generate_coverage_report_test.py
@@ -0,0 +1,71 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for generate_coverage_report."""
+
+import unittest
+from unittest import mock
+
+import generate_coverage_report
+import test_helpers
+
+OUT_DIR = '/outdir'
+PROJECT = 'example-project'
+SANITIZER = 'coverage'
+
+
+class TestRunCoverageCommand(unittest.TestCase):
+  """Tests run_coverage_command"""
+
+  def setUp(self):
+    test_helpers.patch_environ(self, empty=True)
+
+  @mock.patch('utils.execute')
+  def test_run_coverage_command(self, mock_execute):  # pylint: disable=no-self-use
+    """Tests that run_coverage_command works as intended."""
+    config = test_helpers.create_run_config(oss_fuzz_project_name=PROJECT,
+                                            sanitizer=SANITIZER)
+    workspace = test_helpers.create_workspace()
+    generate_coverage_report.run_coverage_command(config, workspace)
+    expected_command = 'coverage'
+    expected_env = {
+        'SANITIZER': config.sanitizer,
+        'FUZZING_LANGUAGE': config.language,
+        'OUT': workspace.out,
+        'CIFUZZ': 'True',
+        'FUZZING_ENGINE': 'libfuzzer',
+        'ARCHITECTURE': 'x86_64',
+        'FUZZER_ARGS': '-rss_limit_mb=2560 -timeout=25',
+        'HTTP_PORT': '',
+        'COVERAGE_EXTRA_ARGS': '',
+        'CORPUS_DIR': workspace.corpora,
+        'COVERAGE_OUTPUT_DIR': workspace.coverage_report
+    }
+    mock_execute.assert_called_with(expected_command, env=expected_env)
+
+
+class DownloadCorporaTest(unittest.TestCase):
+  """Tests for download_corpora."""
+
+  def test_download_corpora(self):  # pylint: disable=no-self-use
+    """Tests that download_corpora works as intended."""
+    clusterfuzz_deployment = mock.Mock()
+    clusterfuzz_deployment.workspace = test_helpers.create_workspace()
+    fuzz_target_paths = ['/path/to/fuzzer1', '/path/to/fuzzer2']
+    expected_calls = [
+        mock.call('fuzzer1', '/workspace/cifuzz-corpus/fuzzer1'),
+        mock.call('fuzzer2', '/workspace/cifuzz-corpus/fuzzer2')
+    ]
+    generate_coverage_report.download_corpora(fuzz_target_paths,
+                                              clusterfuzz_deployment)
+    clusterfuzz_deployment.download_corpus.assert_has_calls(expected_calls)
diff --git a/infra/cifuzz/get_coverage.py b/infra/cifuzz/get_coverage.py
new file mode 100644
index 0000000..b4b2d25
--- /dev/null
+++ b/infra/cifuzz/get_coverage.py
@@ -0,0 +1,204 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Module for determining coverage of fuzz targets."""
+import json
+import logging
+import os
+import sys
+
+import http_utils
+
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import utils
+
+# The path to get OSS-Fuzz project's latest report json file.`
+OSS_FUZZ_LATEST_COVERAGE_INFO_PATH = 'oss-fuzz-coverage/latest_report_info/'
+
+
+# pylint: disable=too-few-public-methods
+class CoverageError(Exception):
+  """Exceptions for project coverage."""
+
+
+class BaseCoverage:
+  """Gets coverage data for a project."""
+
+  def __init__(self, repo_path):
+    self.repo_path = _normalize_repo_path(repo_path)
+
+  def get_files_covered_by_target(self, target):
+    """Returns a list of source files covered by the specific fuzz target.
+
+    Args:
+      target: The name of the fuzz target whose coverage is requested.
+
+    Returns:
+      A list of files that the fuzz target covers or None.
+    """
+    target_cov = self.get_target_coverage(target)
+    if not target_cov:
+      logging.info('No coverage available for %s', target)
+      return None
+
+    coverage_per_file = get_coverage_per_file(target_cov)
+    if not coverage_per_file:
+      logging.info('No files found in coverage report.')
+      return None
+
+    affected_file_list = []
+    for file_cov in coverage_per_file:
+      norm_file_path = os.path.normpath(file_cov['filename'])
+      if not norm_file_path.startswith(self.repo_path):
+        # Exclude files outside of the main repo.
+        continue
+
+      if not is_file_covered(file_cov):
+        # Don't consider a file affected if code in it is never executed.
+        continue
+
+      # TODO(metzman): It's weird to me that we access file_cov['filename']
+      # again and not norm_file_path, figure out if this makes sense.
+      relative_path = utils.remove_prefix(file_cov['filename'], self.repo_path)
+      affected_file_list.append(relative_path)
+
+    return affected_file_list
+
+  def get_target_coverage(self, target):
+    """Get the coverage report for a specific fuzz target.
+
+    Args:
+      target: The name of the fuzz target whose coverage is requested.
+
+    Returns:
+      The target's coverage json dict or None on failure.
+    """
+    raise NotImplementedError('Child class must implement method.')
+
+
+class OSSFuzzCoverage(BaseCoverage):
+  """Gets coverage data for a project from OSS-Fuzz."""
+
+  def __init__(self, repo_path, oss_fuzz_project_name):
+    """Constructor for OSSFuzzCoverage."""
+    super().__init__(repo_path)
+    self.oss_fuzz_project_name = oss_fuzz_project_name
+    self.fuzzer_stats_url = _get_oss_fuzz_fuzzer_stats_dir_url(
+        self.oss_fuzz_project_name)
+    if self.fuzzer_stats_url is None:
+      raise CoverageError('Could not get latest coverage.')
+
+  def get_target_coverage(self, target):
+    """Get the coverage report for a specific fuzz target.
+
+    Args:
+      target: The name of the fuzz target whose coverage is requested.
+
+    Returns:
+      The target's coverage json dict or None on failure.
+    """
+    if not self.fuzzer_stats_url:
+      return None
+
+    target_url = utils.url_join(self.fuzzer_stats_url, target + '.json')
+    return http_utils.get_json_from_url(target_url)
+
+
+def _get_oss_fuzz_latest_cov_report_info(oss_fuzz_project_name):
+  """Gets and returns a dictionary containing the latest coverage report info
+  for |project|."""
+  latest_report_info_url = utils.url_join(utils.GCS_BASE_URL,
+                                          OSS_FUZZ_LATEST_COVERAGE_INFO_PATH,
+                                          oss_fuzz_project_name + '.json')
+  latest_cov_info = http_utils.get_json_from_url(latest_report_info_url)
+  if latest_cov_info is None:
+    logging.error('Could not get the coverage report json from url: %s.',
+                  latest_report_info_url)
+    return None
+  return latest_cov_info
+
+
+def _get_oss_fuzz_fuzzer_stats_dir_url(oss_fuzz_project_name):
+  """Gets latest coverage report info for a specific OSS-Fuzz project from
+  GCS.
+
+  Args:
+    oss_fuzz_project_name: The name of the project.
+
+  Returns:
+    The projects coverage report info in json dict or None on failure.
+  """
+  latest_cov_info = _get_oss_fuzz_latest_cov_report_info(oss_fuzz_project_name)
+
+  if not latest_cov_info:
+    return None
+
+  if 'fuzzer_stats_dir' not in latest_cov_info:
+    logging.error('fuzzer_stats_dir not in latest coverage info.')
+    return None
+
+  fuzzer_stats_dir_gs_url = latest_cov_info['fuzzer_stats_dir']
+  fuzzer_stats_dir_url = utils.gs_url_to_https(fuzzer_stats_dir_gs_url)
+  return fuzzer_stats_dir_url
+
+
+class FilesystemCoverage(BaseCoverage):
+  """Class that gets a project's coverage from the filesystem."""
+
+  def __init__(self, repo_path, project_coverage_dir):
+    super().__init__(repo_path)
+    self.project_coverage_dir = project_coverage_dir
+
+  def get_target_coverage(self, target):
+    """Get the coverage report for a specific fuzz target.
+
+    Args:
+      target: The name of the fuzz target whose coverage is requested.
+
+    Returns:
+      The target's coverage json dict or None on failure.
+    """
+    logging.info('Getting coverage for %s from filesystem.', target)
+    fuzzer_stats_json_path = os.path.join(self.project_coverage_dir,
+                                          'fuzzer_stats', target + '.json')
+    if not os.path.exists(fuzzer_stats_json_path):
+      logging.warning('%s does not exist.', fuzzer_stats_json_path)
+      return None
+
+    with open(fuzzer_stats_json_path) as fuzzer_stats_json_file_handle:
+      try:
+        return json.load(fuzzer_stats_json_file_handle)
+      except json.decoder.JSONDecodeError as err:
+        logging.error('Could not decode: %s. Error: %s.',
+                      fuzzer_stats_json_path, err)
+        return None
+
+
+def is_file_covered(file_cov):
+  """Returns whether the file is covered."""
+  return file_cov['summary']['regions']['covered']
+
+
+def get_coverage_per_file(target_cov):
+  """Returns the coverage per file within |target_cov|."""
+  return target_cov['data'][0]['files']
+
+
+def _normalize_repo_path(repo_path):
+  """Normalizes and returns |repo_path| to make sure cases like /src/curl and
+  /src/curl/ are both handled."""
+  repo_path = os.path.normpath(repo_path)
+  if not repo_path.endswith('/'):
+    repo_path += '/'
+  return repo_path
diff --git a/infra/cifuzz/get_coverage_test.py b/infra/cifuzz/get_coverage_test.py
new file mode 100644
index 0000000..fcfc9bd
--- /dev/null
+++ b/infra/cifuzz/get_coverage_test.py
@@ -0,0 +1,239 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for get_coverage.py"""
+import os
+import json
+import unittest
+from unittest import mock
+
+from pyfakefs import fake_filesystem_unittest
+import pytest
+
+import get_coverage
+
+# pylint: disable=protected-access
+
+TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                              'test_data')
+
+PROJECT_NAME = 'curl'
+REPO_PATH = '/src/curl'
+FUZZ_TARGET = 'curl_fuzzer'
+PROJECT_COV_JSON_FILENAME = 'example_curl_cov.json'
+FUZZ_TARGET_COV_JSON_FILENAME = 'example_curl_fuzzer_cov.json'
+INVALID_TARGET = 'not-a-fuzz-target'
+
+with open(os.path.join(TEST_DATA_PATH,
+                       PROJECT_COV_JSON_FILENAME),) as cov_file_handle:
+  PROJECT_COV_INFO = json.loads(cov_file_handle.read())
+
+
+class GetOssFuzzFuzzerStatsDirUrlTest(unittest.TestCase):
+  """Tests _get_oss_fuzz_fuzzer_stats_dir_url."""
+
+  @mock.patch('http_utils.get_json_from_url',
+              return_value={
+                  'fuzzer_stats_dir':
+                      'gs://oss-fuzz-coverage/systemd/fuzzer_stats/20210303'
+              })
+  def test_get_valid_project(self, mock_get_json_from_url):
+    """Tests that a project's coverage report can be downloaded and parsed.
+
+    NOTE: This test relies on the PROJECT_NAME repo's coverage report.
+    The "example" project was not used because it has no coverage reports.
+    """
+    result = get_coverage._get_oss_fuzz_fuzzer_stats_dir_url(PROJECT_NAME)
+    (url,), _ = mock_get_json_from_url.call_args
+    self.assertEqual(
+        'https://storage.googleapis.com/oss-fuzz-coverage/'
+        'latest_report_info/curl.json', url)
+
+    expected_result = (
+        'https://storage.googleapis.com/oss-fuzz-coverage/systemd/fuzzer_stats/'
+        '20210303')
+    self.assertEqual(result, expected_result)
+
+  def test_get_invalid_project(self):
+    """Tests that passing a bad project returns None."""
+    self.assertIsNone(
+        get_coverage._get_oss_fuzz_fuzzer_stats_dir_url('not-a-proj'))
+
+
+class OSSFuzzCoverageGetTargetCoverageTest(unittest.TestCase):
+  """Tests OSSFuzzCoverage.get_target_coverage."""
+
+  def setUp(self):
+    with mock.patch('get_coverage._get_oss_fuzz_latest_cov_report_info',
+                    return_value=PROJECT_COV_INFO):
+      self.oss_fuzz_coverage = get_coverage.OSSFuzzCoverage(
+          REPO_PATH, PROJECT_NAME)
+
+  @mock.patch('http_utils.get_json_from_url', return_value={})
+  def test_valid_target(self, mock_get_json_from_url):
+    """Tests that a target's coverage report can be downloaded and parsed."""
+    self.oss_fuzz_coverage.get_target_coverage(FUZZ_TARGET)
+    (url,), _ = mock_get_json_from_url.call_args
+    self.assertEqual(
+        'https://storage.googleapis.com/oss-fuzz-coverage/'
+        'curl/fuzzer_stats/20200226/curl_fuzzer.json', url)
+
+  def test_invalid_target(self):
+    """Tests that passing an invalid target coverage report returns None."""
+    self.assertIsNone(
+        self.oss_fuzz_coverage.get_target_coverage(INVALID_TARGET))
+
+  @mock.patch('get_coverage._get_oss_fuzz_latest_cov_report_info',
+              return_value=None)
+  def test_invalid_project_json(self, _):  # pylint: disable=no-self-use
+    """Tests an invalid project JSON results in None being returned."""
+    with pytest.raises(get_coverage.CoverageError):
+      get_coverage.OSSFuzzCoverage(REPO_PATH, PROJECT_NAME)
+
+
+def _get_expected_curl_covered_file_list():
+  """Returns the expected covered file list for
+  FUZZ_TARGET_COV_JSON_FILENAME."""
+  curl_files_list_path = os.path.join(TEST_DATA_PATH,
+                                      'example_curl_file_list.json')
+  with open(curl_files_list_path) as file_handle:
+    return json.loads(file_handle.read())
+
+
+def _get_example_curl_coverage():
+  """Returns the contents of the fuzzer stats JSON file for
+  FUZZ_TARGET_COV_JSON_FILENAME."""
+  with open(os.path.join(TEST_DATA_PATH,
+                         FUZZ_TARGET_COV_JSON_FILENAME)) as file_handle:
+    return json.loads(file_handle.read())
+
+
+class OSSFuzzCoverageGetFilesCoveredByTargetTest(unittest.TestCase):
+  """Tests OSSFuzzCoverage.get_files_covered_by_target."""
+
+  def setUp(self):
+    with mock.patch('get_coverage._get_oss_fuzz_latest_cov_report_info',
+                    return_value=PROJECT_COV_INFO):
+      self.oss_fuzz_coverage = get_coverage.OSSFuzzCoverage(
+          REPO_PATH, PROJECT_NAME)
+
+  def test_valid_target(self):
+    """Tests that covered files can be retrieved from a coverage report."""
+    fuzzer_cov_data = _get_example_curl_coverage()
+    with mock.patch('get_coverage.OSSFuzzCoverage.get_target_coverage',
+                    return_value=fuzzer_cov_data):
+      file_list = self.oss_fuzz_coverage.get_files_covered_by_target(
+          FUZZ_TARGET)
+
+    expected_file_list = _get_expected_curl_covered_file_list()
+    self.assertCountEqual(file_list, expected_file_list)
+
+  def test_invalid_target(self):
+    """Tests passing invalid fuzz target returns None."""
+    self.assertIsNone(
+        self.oss_fuzz_coverage.get_files_covered_by_target(INVALID_TARGET))
+
+
+class FilesystemCoverageGetFilesCoveredByTargetTest(
+    fake_filesystem_unittest.TestCase):
+  """Tests FilesystemCoverage.get_files_covered_by_target."""
+
+  def setUp(self):
+    _fuzzer_cov_data = _get_example_curl_coverage()
+    self._expected_file_list = _get_expected_curl_covered_file_list()
+    self.coverage_path = '/coverage'
+    self.filesystem_coverage = get_coverage.FilesystemCoverage(
+        REPO_PATH, self.coverage_path)
+    self.setUpPyfakefs()
+    self.fs.create_file(os.path.join(self.coverage_path, 'fuzzer_stats',
+                                     FUZZ_TARGET + '.json'),
+                        contents=json.dumps(_fuzzer_cov_data))
+
+  def test_valid_target(self):
+    """Tests that covered files can be retrieved from a coverage report."""
+    file_list = self.filesystem_coverage.get_files_covered_by_target(
+        FUZZ_TARGET)
+    self.assertCountEqual(file_list, self._expected_file_list)
+
+  def test_invalid_target(self):
+    """Tests passing invalid fuzz target returns None."""
+    self.assertIsNone(
+        self.filesystem_coverage.get_files_covered_by_target(INVALID_TARGET))
+
+
+class IsFileCoveredTest(unittest.TestCase):
+  """Tests for is_file_covered."""
+
+  def test_is_file_covered_covered(self):
+    """Tests that is_file_covered returns True for a covered file."""
+    file_coverage = {
+        'filename': '/src/systemd/src/basic/locale-util.c',
+        'summary': {
+            'regions': {
+                'count': 204,
+                'covered': 200,
+                'notcovered': 200,
+                'percent': 98.03
+            }
+        }
+    }
+    self.assertTrue(get_coverage.is_file_covered(file_coverage))
+
+  def test_is_file_covered_not_covered(self):
+    """Tests that is_file_covered returns False for a not covered file."""
+    file_coverage = {
+        'filename': '/src/systemd/src/basic/locale-util.c',
+        'summary': {
+            'regions': {
+                'count': 204,
+                'covered': 0,
+                'notcovered': 0,
+                'percent': 0
+            }
+        }
+    }
+    self.assertFalse(get_coverage.is_file_covered(file_coverage))
+
+
+class GetOssFuzzLatestCovReportInfo(unittest.TestCase):
+  """Tests that _get_oss_fuzz_latest_cov_report_info works as
+  intended."""
+
+  PROJECT = 'project'
+  LATEST_REPORT_INFO_URL = ('https://storage.googleapis.com/oss-fuzz-coverage/'
+                            'latest_report_info/project.json')
+
+  @mock.patch('logging.error')
+  @mock.patch('http_utils.get_json_from_url', return_value={'coverage': 1})
+  def test_get_oss_fuzz_latest_cov_report_info(self, mock_get_json_from_url,
+                                               mock_error):
+    """Tests that _get_oss_fuzz_latest_cov_report_info works as intended."""
+    result = get_coverage._get_oss_fuzz_latest_cov_report_info(self.PROJECT)
+    self.assertEqual(result, {'coverage': 1})
+    mock_error.assert_not_called()
+    mock_get_json_from_url.assert_called_with(self.LATEST_REPORT_INFO_URL)
+
+  @mock.patch('logging.error')
+  @mock.patch('http_utils.get_json_from_url', return_value=None)
+  def test_get_oss_fuzz_latest_cov_report_info_fail(self, _, mock_error):
+    """Tests that _get_oss_fuzz_latest_cov_report_info works as intended when we
+    can't get latest report info."""
+    result = get_coverage._get_oss_fuzz_latest_cov_report_info('project')
+    self.assertIsNone(result)
+    mock_error.assert_called_with(
+        'Could not get the coverage report json from url: %s.',
+        self.LATEST_REPORT_INFO_URL)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/infra/cifuzz/http_utils.py b/infra/cifuzz/http_utils.py
new file mode 100644
index 0000000..9311835
--- /dev/null
+++ b/infra/cifuzz/http_utils.py
@@ -0,0 +1,117 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Utility module for HTTP."""
+import json
+import logging
+import os
+import sys
+import tempfile
+import zipfile
+
+import requests
+
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import retry
+
+_DOWNLOAD_URL_RETRIES = 3
+_DOWNLOAD_URL_BACKOFF = 1
+
+
+def download_and_unpack_zip(url, extract_directory, headers=None):
+  """Downloads and unpacks a zip file from an HTTP URL.
+
+  Args:
+    url: A url to the zip file to be downloaded and unpacked.
+    extract_directory: The path where the zip file should be extracted to.
+    headers: (Optional) HTTP headers to send with the download request.
+
+  Returns:
+    True on success.
+  """
+  if headers is None:
+    headers = {}
+
+  if not os.path.exists(extract_directory):
+    logging.error('Extract directory: %s does not exist.', extract_directory)
+    return False
+
+  # Gives the temporary zip file a unique identifier in the case that
+  # that download_and_unpack_zip is done in parallel.
+  with tempfile.NamedTemporaryFile(suffix='.zip') as tmp_file:
+    if not download_url(url, tmp_file.name, headers=headers):
+      return False
+
+    try:
+      with zipfile.ZipFile(tmp_file.name, 'r') as zip_file:
+        zip_file.extractall(extract_directory)
+    except zipfile.BadZipFile:
+      logging.error('Error unpacking zip from %s. Bad Zipfile.', url)
+      return False
+
+  return True
+
+
+def download_url(*args, **kwargs):
+  """Wrapper around _download_url that returns False if _download_url
+  exceptions."""
+  try:
+    return _download_url(*args, **kwargs)
+  except Exception:  # pylint: disable=broad-except
+    return False
+
+
+def get_json_from_url(url):
+  """Gets a json object from a specified HTTP URL.
+
+  Args:
+    url: The url of the json to be downloaded.
+
+  Returns:
+    A dictionary deserialized from JSON or None on failure.
+  """
+  response = requests.get(url)
+  try:
+    return response.json()
+  except (ValueError, TypeError, json.JSONDecodeError) as err:
+    logging.error('Loading json from url %s failed with: %s.', url, str(err))
+    return None
+
+
+@retry.wrap(_DOWNLOAD_URL_RETRIES, _DOWNLOAD_URL_BACKOFF)
+def _download_url(url, filename, headers=None):
+  """Downloads the file located at |url|, using HTTP to |filename|.
+
+  Args:
+    url: A url to a file to download.
+    filename: The path the file should be downloaded to.
+    headers: (Optional) HTTP headers to send with the download request.
+
+  Returns:
+    True on success.
+  """
+  if headers is None:
+    headers = {}
+
+  response = requests.get(url, headers=headers)
+
+  if response.status_code != 200:
+    logging.error('Unable to download from: %s. Code: %d. Content: %s.', url,
+                  response.status_code, response.content)
+    return False
+
+  with open(filename, 'wb') as file_handle:
+    file_handle.write(response.content)
+
+  return True
diff --git a/infra/cifuzz/http_utils_test.py b/infra/cifuzz/http_utils_test.py
new file mode 100644
index 0000000..64d0598
--- /dev/null
+++ b/infra/cifuzz/http_utils_test.py
@@ -0,0 +1,71 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Tests for http_utils.py"""
+
+import unittest
+from unittest import mock
+
+from pyfakefs import fake_filesystem_unittest
+
+import http_utils
+
+mock_get_response = mock.MagicMock(status_code=200, content=b'')
+
+
+class DownloadUrlTest(unittest.TestCase):
+  """Tests that download_url works."""
+  URL = 'https://example.com/file'
+  FILE_PATH = '/tmp/file'
+
+  @mock.patch('time.sleep')
+  @mock.patch('requests.get', return_value=mock_get_response)
+  def test_download_url_no_error(self, mock_urlretrieve, _):
+    """Tests that download_url works when there is no error."""
+    self.assertTrue(http_utils.download_url(self.URL, self.FILE_PATH))
+    self.assertEqual(1, mock_urlretrieve.call_count)
+
+  @mock.patch('time.sleep')
+  @mock.patch('logging.error')
+  @mock.patch('requests.get',
+              return_value=mock.MagicMock(status_code=404, content=b''))
+  def test_download_url_http_error(self, mock_get, mock_error, _):
+    """Tests that download_url doesn't retry when there is an HTTP error."""
+    self.assertFalse(http_utils.download_url(self.URL, self.FILE_PATH))
+    mock_error.assert_called_with(
+        'Unable to download from: %s. Code: %d. Content: %s.', self.URL, 404,
+        b'')
+    self.assertEqual(1, mock_get.call_count)
+
+  @mock.patch('time.sleep')
+  @mock.patch('requests.get', side_effect=ConnectionResetError)
+  def test_download_url_connection_error(self, mock_get, mock_sleep):
+    """Tests that download_url doesn't retry when there is an HTTP error."""
+    self.assertFalse(http_utils.download_url(self.URL, self.FILE_PATH))
+    self.assertEqual(4, mock_get.call_count)
+    self.assertEqual(3, mock_sleep.call_count)
+
+
+class DownloadAndUnpackZipTest(fake_filesystem_unittest.TestCase):
+  """Tests download_and_unpack_zip."""
+
+  def setUp(self):
+    self.setUpPyfakefs()
+
+  @mock.patch('requests.get', return_value=mock_get_response)
+  def test_bad_zip_download(self, _):
+    """Tests download_and_unpack_zip returns none when a bad zip is passed."""
+    self.fs.create_file('/url_tmp.zip', contents='Test file.')
+    self.assertFalse(
+        http_utils.download_and_unpack_zip('/not/a/real/url',
+                                           '/extract-directory'))
diff --git a/infra/cifuzz/package-lock.json b/infra/cifuzz/package-lock.json
new file mode 100644
index 0000000..9ee5840
--- /dev/null
+++ b/infra/cifuzz/package-lock.json
@@ -0,0 +1,316 @@
+{
+  "name": "cifuzz",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "version": "1.0.0",
+      "license": "Apache2",
+      "dependencies": {
+        "@actions/artifact": "^0.5.2"
+      }
+    },
+    "node_modules/@actions/artifact": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-0.5.2.tgz",
+      "integrity": "sha512-q/r8WSqyxBJ0ffLCRrtjCBTGnAYqP+ID4yG7f7YSlhrQ4thNg/d+Tq9f1YkLPKX46ZR97OWtGDY+oU/nxcqvLw==",
+      "dependencies": {
+        "@actions/core": "^1.2.6",
+        "@actions/http-client": "^1.0.11",
+        "@types/tmp": "^0.1.0",
+        "tmp": "^0.1.0",
+        "tmp-promise": "^2.0.2"
+      }
+    },
+    "node_modules/@actions/core": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
+      "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
+      "dependencies": {
+        "@actions/http-client": "^1.0.11"
+      }
+    },
+    "node_modules/@actions/http-client": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
+      "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
+      "dependencies": {
+        "tunnel": "0.0.6"
+      }
+    },
+    "node_modules/@types/tmp": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.1.0.tgz",
+      "integrity": "sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA=="
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+    },
+    "node_modules/glob": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "node_modules/minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      }
+    },
+    "node_modules/tmp": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
+      "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
+      "dependencies": {
+        "rimraf": "^2.6.3"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tmp-promise": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.1.1.tgz",
+      "integrity": "sha512-Z048AOz/w9b6lCbJUpevIJpRpUztENl8zdv1bmAKVHimfqRFl92ROkmT9rp7TVBnrEw2gtMTol/2Cp2S2kJa4Q==",
+      "dependencies": {
+        "tmp": "0.1.0"
+      }
+    },
+    "node_modules/tunnel": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+      "engines": {
+        "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+    }
+  },
+  "dependencies": {
+    "@actions/artifact": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-0.5.2.tgz",
+      "integrity": "sha512-q/r8WSqyxBJ0ffLCRrtjCBTGnAYqP+ID4yG7f7YSlhrQ4thNg/d+Tq9f1YkLPKX46ZR97OWtGDY+oU/nxcqvLw==",
+      "requires": {
+        "@actions/core": "^1.2.6",
+        "@actions/http-client": "^1.0.11",
+        "@types/tmp": "^0.1.0",
+        "tmp": "^0.1.0",
+        "tmp-promise": "^2.0.2"
+      }
+    },
+    "@actions/core": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
+      "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
+      "requires": {
+        "@actions/http-client": "^1.0.11"
+      }
+    },
+    "@actions/http-client": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
+      "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
+      "requires": {
+        "tunnel": "0.0.6"
+      }
+    },
+    "@types/tmp": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.1.0.tgz",
+      "integrity": "sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA=="
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+    },
+    "glob": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+    },
+    "rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "tmp": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
+      "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
+      "requires": {
+        "rimraf": "^2.6.3"
+      }
+    },
+    "tmp-promise": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.1.1.tgz",
+      "integrity": "sha512-Z048AOz/w9b6lCbJUpevIJpRpUztENl8zdv1bmAKVHimfqRFl92ROkmT9rp7TVBnrEw2gtMTol/2Cp2S2kJa4Q==",
+      "requires": {
+        "tmp": "0.1.0"
+      }
+    },
+    "tunnel": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+      "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+    }
+  }
+}
diff --git a/infra/cifuzz/package.json b/infra/cifuzz/package.json
new file mode 100644
index 0000000..5823747
--- /dev/null
+++ b/infra/cifuzz/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "cifuzz",
+  "version": "1.0.0",
+  "description": "",
+  "author": "Google",
+  "license": "Apache2",
+  "dependencies": {
+    "@actions/artifact": "^0.5.2"
+  }
+}
diff --git a/infra/cifuzz/requirements.txt b/infra/cifuzz/requirements.txt
new file mode 100644
index 0000000..270c155
--- /dev/null
+++ b/infra/cifuzz/requirements.txt
@@ -0,0 +1,2 @@
+clusterfuzz==2.5.6
+requests==2.25.1
diff --git a/infra/cifuzz/run_cifuzz.py b/infra/cifuzz/run_cifuzz.py
new file mode 100644
index 0000000..0382d78
--- /dev/null
+++ b/infra/cifuzz/run_cifuzz.py
@@ -0,0 +1,88 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Script for running CIFuzz end-to-end. This is meant to work outside any
+docker image. This cannot depend on any CIFuzz code or third party packages."""
+import os
+import subprocess
+import sys
+import tempfile
+import logging
+
+INFRA_DIR = os.path.dirname(os.path.dirname(__file__))
+DEFAULT_ENVS = [('DRY_RUN', '0'), ('SANITIZER', 'address')]
+BASE_CIFUZZ_DOCKER_TAG = 'gcr.io/oss-fuzz-base'
+
+
+def set_default_env_var_if_unset(env_var, default_value):
+  """Sets the value of |env_var| in the environment to |default_value| if it was
+  not already set."""
+  if env_var not in os.environ:
+    os.environ[env_var] = default_value
+
+
+def docker_run(name, workspace, project_src_path):
+  """Runs a CIFuzz docker container with |name|."""
+  command = [
+      'docker', 'run', '--name', name, '--rm', '-e', 'PROJECT_SRC_PATH', '-e',
+      'OSS_FUZZ_PROJECT_NAME', '-e', 'WORKSPACE', '-e', 'REPOSITORY', '-e',
+      'DRY_RUN', '-e', 'CI', '-e', 'SANITIZER', '-e', 'GIT_SHA'
+  ]
+  if project_src_path:
+    command += ['-v', f'{project_src_path}:{project_src_path}']
+  command += [
+      '-v', '/var/run/docker.sock:/var/run/docker.sock', '-v',
+      f'{workspace}:{workspace}', f'{BASE_CIFUZZ_DOCKER_TAG}/{name}'
+  ]
+  print('Running docker command:', command)
+  subprocess.run(command, check=True)
+
+
+def docker_build(image):
+  """Builds the CIFuzz |image|. Only suitable for building CIFuzz images."""
+  command = [
+      'docker', 'build', '-t', f'{BASE_CIFUZZ_DOCKER_TAG}/{image}', '--file',
+      f'{image}.Dockerfile', '.'
+  ]
+  subprocess.run(command, check=True, cwd=INFRA_DIR)
+
+
+def main():
+  """Builds and runs fuzzers using CIFuzz."""
+  for env_var, default_value in DEFAULT_ENVS:
+    set_default_env_var_if_unset(env_var, default_value)
+
+  repository = os.getenv('REPOSITORY')
+  assert repository
+
+  project_src_path = os.getenv('PROJECT_SRC_PATH')
+
+  with tempfile.TemporaryDirectory() as temp_dir:
+    if 'WORKSPACE' not in os.environ:
+      os.environ['WORKSPACE'] = temp_dir
+
+    workspace = os.environ['WORKSPACE']
+
+    docker_build('build_fuzzers')
+    docker_run('build_fuzzers', workspace, project_src_path)
+    docker_build('run_fuzzers')
+    try:
+      docker_run('run_fuzzers', workspace, project_src_path)
+    except subprocess.CalledProcessError:
+      logging.error('run_fuzzers failed.')
+      return 1
+    return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/infra/cifuzz/run_fuzzers.py b/infra/cifuzz/run_fuzzers.py
index 513cfb6..67c4c66 100644
--- a/infra/cifuzz/run_fuzzers.py
+++ b/infra/cifuzz/run_fuzzers.py
@@ -21,7 +21,9 @@
 
 import clusterfuzz_deployment
 import fuzz_target
+import generate_coverage_report
 import stack_parser
+import workspace_utils
 
 # pylint: disable=wrong-import-position,import-error
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
@@ -41,12 +43,17 @@
 
   def __init__(self, config):
     self.config = config
+    self.workspace = workspace_utils.Workspace(config)
     self.clusterfuzz_deployment = (
-        clusterfuzz_deployment.get_clusterfuzz_deployment(self.config))
+        clusterfuzz_deployment.get_clusterfuzz_deployment(
+            self.config, self.workspace))
+
     # Set by the initialize method.
-    self.out_dir = None
     self.fuzz_target_paths = None
-    self.artifacts_dir = None
+
+  def get_fuzz_targets(self):
+    """Returns fuzz targets in out directory."""
+    return utils.get_fuzz_targets(self.workspace.out)
 
   def initialize(self):
     """Initialization method. Must be called before calling run_fuzz_targets.
@@ -64,55 +71,51 @@
           self.config.fuzz_seconds)
       return False
 
-    self.out_dir = os.path.join(self.config.workspace, 'out')
-    if not os.path.exists(self.out_dir):
-      logging.error('Out directory: %s does not exist.', self.out_dir)
+    if not os.path.exists(self.workspace.out):
+      logging.error('Out directory: %s does not exist.', self.workspace.out)
       return False
 
-    self.artifacts_dir = os.path.join(self.out_dir, 'artifacts')
-    if not os.path.exists(self.artifacts_dir):
-      os.mkdir(self.artifacts_dir)
-    elif (not os.path.isdir(self.artifacts_dir) or
-          os.listdir(self.artifacts_dir)):
+    if not os.path.exists(self.workspace.artifacts):
+      os.makedirs(self.workspace.artifacts)
+    elif (not os.path.isdir(self.workspace.artifacts) or
+          os.listdir(self.workspace.artifacts)):
       logging.error('Artifacts path: %s exists and is not an empty directory.',
-                    self.artifacts_dir)
+                    self.workspace.artifacts)
       return False
 
-    self.fuzz_target_paths = utils.get_fuzz_targets(self.out_dir)
+    self.fuzz_target_paths = self.get_fuzz_targets()
     logging.info('Fuzz targets: %s', self.fuzz_target_paths)
     if not self.fuzz_target_paths:
       logging.error('No fuzz targets were found in out directory: %s.',
-                    self.out_dir)
+                    self.workspace.out)
       return False
 
     return True
 
+  def cleanup_after_fuzz_target_run(self, fuzz_target_obj):  # pylint: disable=no-self-use
+    """Cleans up after running |fuzz_target_obj|."""
+    raise NotImplementedError('Child class must implement method.')
+
   def run_fuzz_target(self, fuzz_target_obj):  # pylint: disable=no-self-use
     """Fuzzes with |fuzz_target_obj| and returns the result."""
-    # TODO(metzman): Make children implement this so that the batch runner can
-    # do things differently.
-    result = fuzz_target_obj.fuzz()
-    fuzz_target_obj.free_disk_if_needed()
-    return result
+    raise NotImplementedError('Child class must implement method.')
 
   @property
   def quit_on_bug_found(self):
     """Property that is checked to determine if fuzzing should quit after first
     bug is found."""
-    raise NotImplementedError('Child class must implement method')
+    raise NotImplementedError('Child class must implement method.')
 
   def get_fuzz_target_artifact(self, target, artifact_name):
     """Returns the path of a fuzzing artifact named |artifact_name| for
     |fuzz_target|."""
-    artifact_name = '{target_name}-{sanitizer}-{artifact_name}'.format(
-        target_name=target.target_name,
-        sanitizer=self.config.sanitizer,
-        artifact_name=artifact_name)
-    return os.path.join(self.artifacts_dir, artifact_name)
+    artifact_name = (f'{target.target_name}-{self.config.sanitizer}-'
+                     f'{artifact_name}')
+    return os.path.join(self.workspace.artifacts, artifact_name)
 
   def create_fuzz_target_obj(self, target_path, run_seconds):
     """Returns a fuzz target object."""
-    return fuzz_target.FuzzTarget(target_path, run_seconds, self.out_dir,
+    return fuzz_target.FuzzTarget(target_path, run_seconds, self.workspace,
                                   self.clusterfuzz_deployment, self.config)
 
   def run_fuzz_targets(self):
@@ -134,6 +137,7 @@
       target = self.create_fuzz_target_obj(target_path, run_seconds)
       start_time = time.time()
       result = self.run_fuzz_target(target)
+      self.cleanup_after_fuzz_target_run(target)
 
       # It's OK if this goes negative since we take max when determining
       # run_seconds.
@@ -162,6 +166,60 @@
     return bug_found
 
 
+class PruneTargetRunner(BaseFuzzTargetRunner):
+  """Runner that prunes corpora."""
+
+  @property
+  def quit_on_bug_found(self):
+    return False
+
+  def run_fuzz_target(self, fuzz_target_obj):
+    """Prunes with |fuzz_target_obj| and returns the result."""
+    result = fuzz_target_obj.prune()
+    logging.debug('Corpus path contents: %s.', os.listdir(result.corpus_path))
+    self.clusterfuzz_deployment.upload_corpus(fuzz_target_obj.target_name,
+                                              result.corpus_path,
+                                              replace=True)
+    return result
+
+  def cleanup_after_fuzz_target_run(self, fuzz_target_obj):  # pylint: disable=no-self-use
+    """Cleans up after pruning with |fuzz_target_obj|."""
+    fuzz_target_obj.free_disk_if_needed()
+
+
+class CoverageTargetRunner(BaseFuzzTargetRunner):
+  """Runner that runs the 'coverage' command."""
+
+  @property
+  def quit_on_bug_found(self):
+    raise NotImplementedError('Not implemented for CoverageTargetRunner.')
+
+  def get_fuzz_targets(self):
+    """Returns fuzz targets in out directory."""
+    # We only want fuzz targets from the root because during the coverage build,
+    # a lot of the image's filesystem is copied into /out for the purpose of
+    # generating coverage reports.
+    # TOOD(metzman): Figure out if top_level_only should be the only behavior
+    # for this function.
+    return utils.get_fuzz_targets(self.workspace.out, top_level_only=True)
+
+  def run_fuzz_targets(self):
+    """Generates a coverage report. Always returns False since it never finds
+    any bugs."""
+    generate_coverage_report.generate_coverage_report(
+        self.fuzz_target_paths, self.workspace, self.clusterfuzz_deployment,
+        self.config)
+    return False
+
+  def run_fuzz_target(self, fuzz_target_obj):  # pylint: disable=no-self-use
+    """Fuzzes with |fuzz_target_obj| and returns the result."""
+    raise NotImplementedError('Not implemented for CoverageTargetRunner.')
+
+  def cleanup_after_fuzz_target_run(self, fuzz_target_obj):  # pylint: disable=no-self-use
+    """Cleans up after running |fuzz_target_obj|."""
+    raise NotImplementedError('Not implemented for CoverageTargetRunner.')
+
+
 class CiFuzzTargetRunner(BaseFuzzTargetRunner):
   """Runner for fuzz targets used in CI (patch-fuzzing) context."""
 
@@ -169,6 +227,13 @@
   def quit_on_bug_found(self):
     return True
 
+  def cleanup_after_fuzz_target_run(self, fuzz_target_obj):  # pylint: disable=no-self-use
+    """Cleans up after running |fuzz_target_obj|."""
+    fuzz_target_obj.free_disk_if_needed()
+
+  def run_fuzz_target(self, fuzz_target_obj):  # pylint: disable=no-self-use
+    return fuzz_target_obj.fuzz()
+
 
 class BatchFuzzTargetRunner(BaseFuzzTargetRunner):
   """Runner for fuzz targets used in batch fuzzing context."""
@@ -177,14 +242,42 @@
   def quit_on_bug_found(self):
     return False
 
+  def run_fuzz_target(self, fuzz_target_obj):
+    """Fuzzes with |fuzz_target_obj| and returns the result."""
+    result = fuzz_target_obj.fuzz()
+    logging.debug('Corpus path contents: %s.', os.listdir(result.corpus_path))
+    self.clusterfuzz_deployment.upload_corpus(fuzz_target_obj.target_name,
+                                              result.corpus_path)
+    return result
+
+  def cleanup_after_fuzz_target_run(self, fuzz_target_obj):
+    """Cleans up after running |fuzz_target_obj|."""
+    # This must be done after we upload the corpus, otherwise it will be deleted
+    # before we get a chance to upload it. We can't delete the fuzz target
+    # because it is needed when we upload the build.
+    fuzz_target_obj.free_disk_if_needed(delete_fuzz_target=False)
+
+  def run_fuzz_targets(self):
+    result = super().run_fuzz_targets()
+    self.clusterfuzz_deployment.upload_crashes()
+    return result
+
+
+_RUN_FUZZERS_MODE_RUNNER_MAPPING = {
+    'batch': BatchFuzzTargetRunner,
+    'coverage': CoverageTargetRunner,
+    'prune': PruneTargetRunner,
+    'ci': CiFuzzTargetRunner,
+}
+
 
 def get_fuzz_target_runner(config):
   """Returns a fuzz target runner object based on the run_fuzzers_mode of
   |config|."""
-  logging.info('RUN_FUZZERS_MODE is: %s', config.run_fuzzers_mode)
-  if config.run_fuzzers_mode == 'batch':
-    return BatchFuzzTargetRunner(config)
-  return CiFuzzTargetRunner(config)
+  runner = _RUN_FUZZERS_MODE_RUNNER_MAPPING[config.run_fuzzers_mode](config)
+  logging.info('RUN_FUZZERS_MODE is: %s. Runner: %s.', config.run_fuzzers_mode,
+               runner)
+  return runner
 
 
 def run_fuzzers(config):  # pylint: disable=too-many-locals
diff --git a/infra/cifuzz/run_fuzzers_entrypoint.py b/infra/cifuzz/run_fuzzers_entrypoint.py
index 46e208d..adfd1a9 100644
--- a/infra/cifuzz/run_fuzzers_entrypoint.py
+++ b/infra/cifuzz/run_fuzzers_entrypoint.py
@@ -33,19 +33,49 @@
   if not config.low_disk_space:
     return
   logging.info('Deleting builder docker images to save disk space.')
-  project_image = docker.get_project_image_name(config.project_name)
+  project_image = docker.get_project_image_name(config.oss_fuzz_project_name)
   images = [
       project_image,
-      docker.BASE_RUNNER_TAG,
-      docker.MSAN_LIBS_BUILDER_TAG,
+      docker.BASE_BUILDER_TAG,
+      docker.BASE_BUILDER_TAG + ':xenial',
+      docker.BASE_BUILDER_TAG + '-go',
+      docker.BASE_BUILDER_TAG + '-jvm',
+      docker.BASE_BUILDER_TAG + '-python',
+      docker.BASE_BUILDER_TAG + '-rust',
+      docker.BASE_BUILDER_TAG + '-swift',
   ]
   docker.delete_images(images)
 
 
+def run_fuzzers_entrypoint():
+  """This is the entrypoint for the run_fuzzers github action.
+  This action can be added to any OSS-Fuzz project's workflow that uses
+  Github."""
+  config = config_utils.RunFuzzersConfig()
+  # The default return code when an error occurs.
+  returncode = 1
+  if config.dry_run:
+    # Sets the default return code on error to success.
+    returncode = 0
+
+  delete_unneeded_docker_images(config)
+  # Run the specified project's fuzzers from the build.
+  result = run_fuzzers.run_fuzzers(config)
+  if result == run_fuzzers.RunFuzzersResult.ERROR:
+    logging.error('Error occurred while running in workspace %s.',
+                  config.workspace)
+    return returncode
+  if result == run_fuzzers.RunFuzzersResult.BUG_FOUND:
+    logging.info('Bug found.')
+    if not config.dry_run:
+      # Return 2 when a bug was found by a fuzzer causing the CI to fail.
+      return 2
+  return 0
+
+
 def main():
-  """Runs OSS-Fuzz project's fuzzers for CI tools.
+  """Runs project's fuzzers for CI tools.
   This is the entrypoint for the run_fuzzers github action.
-  This action can be added to any OSS-Fuzz project's workflow that uses Github.
 
   NOTE: libFuzzer binaries must be located in the ${GITHUB_WORKSPACE}/out
   directory in order for this action to be used. This action will only fuzz the
@@ -65,32 +95,9 @@
     SANITIZER: The sanitizer to use when running fuzzers.
 
   Returns:
-    0 on success or 1 on failure.
+    0 on success or nonzero on failure.
   """
-  config = config_utils.RunFuzzersConfig()
-  # The default return code when an error occurs.
-  returncode = 1
-  if config.dry_run:
-    # Sets the default return code on error to success.
-    returncode = 0
-
-  if not config.workspace:
-    logging.error('This script needs to be run within Github actions.')
-    return returncode
-
-  delete_unneeded_docker_images(config)
-  # Run the specified project's fuzzers from the build.
-  result = run_fuzzers.run_fuzzers(config)
-  if result == run_fuzzers.RunFuzzersResult.ERROR:
-    logging.error('Error occurred while running in workspace %s.',
-                  config.workspace)
-    return returncode
-  if result == run_fuzzers.RunFuzzersResult.BUG_FOUND:
-    logging.info('Bug found.')
-    if not config.dry_run:
-      # Return 2 when a bug was found by a fuzzer causing the CI to fail.
-      return 2
-  return 0
+  return run_fuzzers_entrypoint()
 
 
 if __name__ == '__main__':
diff --git a/infra/cifuzz/run_fuzzers_test.py b/infra/cifuzz/run_fuzzers_test.py
index b265990..db442b1 100644
--- a/infra/cifuzz/run_fuzzers_test.py
+++ b/infra/cifuzz/run_fuzzers_test.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """Tests for running fuzzers."""
+import json
 import os
 import sys
 import shutil
@@ -22,7 +23,7 @@
 import parameterized
 from pyfakefs import fake_filesystem_unittest
 
-import config_utils
+import build_fuzzers
 import fuzz_target
 import run_fuzzers
 
@@ -30,6 +31,7 @@
 INFRA_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 sys.path.append(INFRA_DIR)
 
+import helper
 import test_helpers
 
 # NOTE: This integration test relies on
@@ -49,22 +51,6 @@
 FUZZ_SECONDS = 10
 
 
-def _create_config(**kwargs):
-  """Creates a config object and then sets every attribute that is a key in
-  |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an
-  attribute of Config."""
-  with mock.patch('os.path.basename', return_value=None), mock.patch(
-      'config_utils.get_project_src_path',
-      return_value=None), mock.patch('config_utils._is_dry_run',
-                                     return_value=True):
-    config = config_utils.RunFuzzersConfig()
-
-  for key, value in kwargs.items():
-    assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
-    setattr(config, key, value)
-  return config
-
-
 class RunFuzzerIntegrationTestMixin:  # pylint: disable=too-few-public-methods,invalid-name
   """Mixin for integration test classes that runbuild_fuzzers on builds of a
   specific sanitizer."""
@@ -72,39 +58,43 @@
   FUZZER_DIR = None
   FUZZER = None
 
+  def setUp(self):
+    """Patch the environ so that we can execute runner scripts."""
+    test_helpers.patch_environ(self, runner=True)
+
   def _test_run_with_sanitizer(self, fuzzer_dir, sanitizer):
     """Calls run_fuzzers on fuzzer_dir and |sanitizer| and asserts
     the run succeeded and that no bug was found."""
     with test_helpers.temp_dir_copy(fuzzer_dir) as fuzzer_dir_copy:
-      config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                              workspace=fuzzer_dir_copy,
-                              project_name='curl',
-                              sanitizer=sanitizer)
+      config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS,
+                                              workspace=fuzzer_dir_copy,
+                                              oss_fuzz_project_name='curl',
+                                              sanitizer=sanitizer)
       result = run_fuzzers.run_fuzzers(config)
     self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND)
 
 
+@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
+                 'INTEGRATION_TESTS=1 not set')
 class RunMemoryFuzzerIntegrationTest(RunFuzzerIntegrationTestMixin,
                                      unittest.TestCase):
   """Integration test for build_fuzzers with an MSAN build."""
   FUZZER_DIR = MEMORY_FUZZER_DIR
   FUZZER = MEMORY_FUZZER
 
-  @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
-                   'INTEGRATION_TESTS=1 not set')
   def test_run_with_memory_sanitizer(self):
     """Tests run_fuzzers with a valid MSAN build."""
     self._test_run_with_sanitizer(self.FUZZER_DIR, 'memory')
 
 
+@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
+                 'INTEGRATION_TESTS=1 not set')
 class RunUndefinedFuzzerIntegrationTest(RunFuzzerIntegrationTestMixin,
                                         unittest.TestCase):
   """Integration test for build_fuzzers with an UBSAN build."""
   FUZZER_DIR = UNDEFINED_FUZZER_DIR
   FUZZER = UNDEFINED_FUZZER
 
-  @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
-                   'INTEGRATION_TESTS=1 not set')
   def test_run_with_undefined_sanitizer(self):
     """Tests run_fuzzers with a valid UBSAN build."""
     self._test_run_with_sanitizer(self.FUZZER_DIR, 'undefined')
@@ -114,19 +104,22 @@
   """Tests BaseFuzzTargetRunner."""
 
   def _create_runner(self, **kwargs):  # pylint: disable=no-self-use
-    defaults = {'fuzz_seconds': FUZZ_SECONDS, 'project_name': EXAMPLE_PROJECT}
+    defaults = {
+        'fuzz_seconds': FUZZ_SECONDS,
+        'oss_fuzz_project_name': EXAMPLE_PROJECT
+    }
     for default_key, default_value in defaults.items():
       if default_key not in kwargs:
         kwargs[default_key] = default_value
 
-    config = _create_config(**kwargs)
+    config = test_helpers.create_run_config(**kwargs)
     return run_fuzzers.BaseFuzzTargetRunner(config)
 
   def _test_initialize_fail(self, expected_error_args, **create_runner_kwargs):
-    with mock.patch('logging.error') as mocked_error:
+    with mock.patch('logging.error') as mock_error:
       runner = self._create_runner(**create_runner_kwargs)
       self.assertFalse(runner.initialize())
-      mocked_error.assert_called_with(*expected_error_args)
+      mock_error.assert_called_with(*expected_error_args)
 
   @parameterized.parameterized.expand([(0,), (None,), (-1,)])
   def test_initialize_invalid_fuzz_seconds(self, fuzz_seconds):
@@ -134,10 +127,10 @@
     expected_error_args = ('Fuzz_seconds argument must be greater than 1, '
                            'but was: %s.', fuzz_seconds)
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
+      out_path = os.path.join(tmp_dir, 'build-out')
       os.mkdir(out_path)
-      with mock.patch('utils.get_fuzz_targets') as mocked_get_fuzz_targets:
-        mocked_get_fuzz_targets.return_value = [
+      with mock.patch('utils.get_fuzz_targets') as mock_get_fuzz_targets:
+        mock_get_fuzz_targets.return_value = [
             os.path.join(out_path, 'fuzz_target')
         ]
         self._test_initialize_fail(expected_error_args,
@@ -147,16 +140,17 @@
   def test_initialize_no_out_dir(self):
     """Tests initialize fails with no out dir."""
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
+      out_path = os.path.join(tmp_dir, 'build-out')
       expected_error_args = ('Out directory: %s does not exist.', out_path)
       self._test_initialize_fail(expected_error_args, workspace=tmp_dir)
 
   def test_initialize_nonempty_artifacts(self):
     """Tests initialize with a file artifacts path."""
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
+      out_path = os.path.join(tmp_dir, 'build-out')
       os.mkdir(out_path)
-      artifacts_path = os.path.join(out_path, 'artifacts')
+      os.makedirs(os.path.join(tmp_dir, 'out'))
+      artifacts_path = os.path.join(tmp_dir, 'out', 'artifacts')
       with open(artifacts_path, 'w') as artifacts_handle:
         artifacts_handle.write('fake')
       expected_error_args = (
@@ -167,8 +161,9 @@
   def test_initialize_bad_artifacts(self):
     """Tests initialize with a non-empty artifacts path."""
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
-      artifacts_path = os.path.join(out_path, 'artifacts')
+      out_path = os.path.join(tmp_dir, 'build-out')
+      os.mkdir(out_path)
+      artifacts_path = os.path.join(tmp_dir, 'out', 'artifacts')
       os.makedirs(artifacts_path)
       artifact_path = os.path.join(artifacts_path, 'artifact')
       with open(artifact_path, 'w') as artifact_handle:
@@ -180,37 +175,37 @@
 
   @mock.patch('utils.get_fuzz_targets')
   @mock.patch('logging.error')
-  def test_initialize_empty_artifacts(self, mocked_log_error,
-                                      mocked_get_fuzz_targets):
+  def test_initialize_empty_artifacts(self, mock_log_error,
+                                      mock_get_fuzz_targets):
     """Tests initialize with an empty artifacts dir."""
-    mocked_get_fuzz_targets.return_value = ['fuzz-target']
+    mock_get_fuzz_targets.return_value = ['fuzz-target']
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
-      artifacts_path = os.path.join(out_path, 'artifacts')
+      out_path = os.path.join(tmp_dir, 'build-out')
+      os.mkdir(out_path)
+      artifacts_path = os.path.join(tmp_dir, 'out', 'artifacts')
       os.makedirs(artifacts_path)
       runner = self._create_runner(workspace=tmp_dir)
       self.assertTrue(runner.initialize())
-      mocked_log_error.assert_not_called()
+      mock_log_error.assert_not_called()
       self.assertTrue(os.path.isdir(artifacts_path))
 
   @mock.patch('utils.get_fuzz_targets')
   @mock.patch('logging.error')
-  def test_initialize_no_artifacts(self, mocked_log_error,
-                                   mocked_get_fuzz_targets):
+  def test_initialize_no_artifacts(self, mock_log_error, mock_get_fuzz_targets):
     """Tests initialize with no artifacts dir (the expected setting)."""
-    mocked_get_fuzz_targets.return_value = ['fuzz-target']
+    mock_get_fuzz_targets.return_value = ['fuzz-target']
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
-      os.makedirs(out_path)
+      out_path = os.path.join(tmp_dir, 'build-out')
+      os.mkdir(out_path)
       runner = self._create_runner(workspace=tmp_dir)
       self.assertTrue(runner.initialize())
-      mocked_log_error.assert_not_called()
-      self.assertTrue(os.path.isdir(os.path.join(out_path, 'artifacts')))
+      mock_log_error.assert_not_called()
+      self.assertTrue(os.path.isdir(os.path.join(tmp_dir, 'out', 'artifacts')))
 
   def test_initialize_no_fuzz_targets(self):
     """Tests initialize with no fuzz targets."""
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
+      out_path = os.path.join(tmp_dir, 'build-out')
       os.makedirs(out_path)
       expected_error_args = ('No fuzz targets were found in out directory: %s.',
                              out_path)
@@ -218,18 +213,21 @@
 
   def test_get_fuzz_target_artifact(self):
     """Tests that get_fuzz_target_artifact works as intended."""
-    runner = self._create_runner()
-    artifacts_dir = 'artifacts-dir'
-    runner.artifacts_dir = artifacts_dir
-    artifact_name = 'artifact-name'
-    target = mock.MagicMock()
-    target_name = 'target_name'
-    target.target_name = target_name
-    fuzz_target_artifact = runner.get_fuzz_target_artifact(
-        target, artifact_name)
-    expected_fuzz_target_artifact = (
-        'artifacts-dir/target_name-address-artifact-name')
-    self.assertEqual(fuzz_target_artifact, expected_fuzz_target_artifact)
+    with tempfile.TemporaryDirectory() as tmp_dir:
+      runner = self._create_runner(workspace=tmp_dir)
+      crashes_dir = 'crashes-dir'
+      runner.crashes_dir = crashes_dir
+      artifact_name = 'artifact-name'
+      target = mock.MagicMock()
+      target_name = 'target_name'
+      target.target_name = target_name
+
+      fuzz_target_artifact = runner.get_fuzz_target_artifact(
+          target, artifact_name)
+      expected_fuzz_target_artifact = os.path.join(
+          tmp_dir, 'out', 'artifacts', 'target_name-address-artifact-name')
+
+      self.assertEqual(fuzz_target_artifact, expected_fuzz_target_artifact)
 
 
 class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
@@ -241,91 +239,176 @@
   @mock.patch('utils.get_fuzz_targets')
   @mock.patch('run_fuzzers.CiFuzzTargetRunner.run_fuzz_target')
   @mock.patch('run_fuzzers.CiFuzzTargetRunner.create_fuzz_target_obj')
-  def test_run_fuzz_targets_quits(self, mocked_create_fuzz_target_obj,
-                                  mocked_run_fuzz_target,
-                                  mocked_get_fuzz_targets):
+  def test_run_fuzz_targets_quits(self, mock_create_fuzz_target_obj,
+                                  mock_run_fuzz_target, mock_get_fuzz_targets):
     """Tests that run_fuzz_targets quits on the first crash it finds."""
     workspace = 'workspace'
-    out_path = os.path.join(workspace, 'out')
+    out_path = os.path.join(workspace, 'build-out')
     self.fs.create_dir(out_path)
-    config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                            workspace=workspace,
-                            project_name=EXAMPLE_PROJECT)
+    config = test_helpers.create_run_config(
+        fuzz_seconds=FUZZ_SECONDS,
+        workspace=workspace,
+        oss_fuzz_project_name=EXAMPLE_PROJECT)
     runner = run_fuzzers.CiFuzzTargetRunner(config)
 
-    mocked_get_fuzz_targets.return_value = ['target1', 'target2']
+    mock_get_fuzz_targets.return_value = ['target1', 'target2']
     runner.initialize()
     testcase = os.path.join(workspace, 'testcase')
     self.fs.create_file(testcase)
-    stacktrace = b'stacktrace'
-    mocked_run_fuzz_target.return_value = fuzz_target.FuzzResult(
-        testcase, stacktrace)
+    stacktrace = 'stacktrace'
+    corpus_dir = 'corpus'
+    self.fs.create_dir(corpus_dir)
+    mock_run_fuzz_target.return_value = fuzz_target.FuzzResult(
+        testcase, stacktrace, corpus_dir)
     magic_mock = mock.MagicMock()
     magic_mock.target_name = 'target1'
-    mocked_create_fuzz_target_obj.return_value = magic_mock
+    mock_create_fuzz_target_obj.return_value = magic_mock
     self.assertTrue(runner.run_fuzz_targets())
-    self.assertIn('target1-address-testcase', os.listdir(runner.artifacts_dir))
-    self.assertEqual(mocked_run_fuzz_target.call_count, 1)
+    self.assertIn('target1-address-testcase',
+                  os.listdir(runner.workspace.artifacts))
+    self.assertEqual(mock_run_fuzz_target.call_count, 1)
 
 
 class BatchFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
-  """Tests that CiFuzzTargetRunner works as intended."""
+  """Tests that BatchFuzzTargetRunnerTest works as intended."""
+  WORKSPACE = 'workspace'
+  STACKTRACE = 'stacktrace'
+  CORPUS_DIR = 'corpus'
 
   def setUp(self):
     self.setUpPyfakefs()
+    out_dir = os.path.join(self.WORKSPACE, 'build-out')
+    self.fs.create_dir(out_dir)
+    self.testcase1 = os.path.join(out_dir, 'testcase-aaa')
+    self.fs.create_file(self.testcase1)
+    self.testcase2 = os.path.join(out_dir, 'testcase-bbb')
+    self.fs.create_file(self.testcase2)
+    self.config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS,
+                                                 workspace=self.WORKSPACE,
+                                                 is_github=True)
 
-  @mock.patch('utils.get_fuzz_targets')
+  @mock.patch('utils.get_fuzz_targets', return_value=['target1', 'target2'])
+  @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_build',
+              return_value=True)
   @mock.patch('run_fuzzers.BatchFuzzTargetRunner.run_fuzz_target')
   @mock.patch('run_fuzzers.BatchFuzzTargetRunner.create_fuzz_target_obj')
-  def test_run_fuzz_targets_quits(self, mocked_create_fuzz_target_obj,
-                                  mocked_run_fuzz_target,
-                                  mocked_get_fuzz_targets):
+  def test_run_fuzz_targets_quits(self, mock_create_fuzz_target_obj,
+                                  mock_run_fuzz_target, _, __):
     """Tests that run_fuzz_targets doesn't quit on the first crash it finds."""
-    workspace = 'workspace'
-    out_path = os.path.join(workspace, 'out')
-    self.fs.create_dir(out_path)
-    config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                            workspace=workspace,
-                            project_name=EXAMPLE_PROJECT)
-    runner = run_fuzzers.BatchFuzzTargetRunner(config)
-
-    mocked_get_fuzz_targets.return_value = ['target1', 'target2']
+    runner = run_fuzzers.BatchFuzzTargetRunner(self.config)
     runner.initialize()
-    testcase1 = os.path.join(workspace, 'testcase-aaa')
-    testcase2 = os.path.join(workspace, 'testcase-bbb')
-    self.fs.create_file(testcase1)
-    self.fs.create_file(testcase2)
-    stacktrace = b'stacktrace'
+
     call_count = 0
 
-    def mock_run_fuzz_target(_):
+    def mock_run_fuzz_target_impl(_):
       nonlocal call_count
       if call_count == 0:
-        testcase = testcase1
+        testcase = self.testcase1
       elif call_count == 1:
-        testcase = testcase2
+        testcase = self.testcase2
       assert call_count != 2
       call_count += 1
-      return fuzz_target.FuzzResult(testcase, stacktrace)
+      if not os.path.exists(self.CORPUS_DIR):
+        self.fs.create_dir(self.CORPUS_DIR)
+      return fuzz_target.FuzzResult(testcase, self.STACKTRACE, self.CORPUS_DIR)
 
-    mocked_run_fuzz_target.side_effect = mock_run_fuzz_target
+    mock_run_fuzz_target.side_effect = mock_run_fuzz_target_impl
     magic_mock = mock.MagicMock()
     magic_mock.target_name = 'target1'
-    mocked_create_fuzz_target_obj.return_value = magic_mock
+    mock_create_fuzz_target_obj.return_value = magic_mock
     self.assertTrue(runner.run_fuzz_targets())
-    self.assertIn('target1-address-testcase-aaa',
-                  os.listdir(runner.artifacts_dir))
-    self.assertEqual(mocked_run_fuzz_target.call_count, 2)
+    self.assertEqual(mock_run_fuzz_target.call_count, 2)
+
+  @mock.patch('run_fuzzers.BaseFuzzTargetRunner.run_fuzz_targets',
+              return_value=False)
+  @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_crashes')
+  def test_run_fuzz_targets_upload_crashes_and_builds(self, mock_upload_crashes,
+                                                      _):
+    """Tests that run_fuzz_targets uploads crashes and builds correctly."""
+    runner = run_fuzzers.BatchFuzzTargetRunner(self.config)
+    # TODO(metzman): Don't rely on this failing gracefully.
+    runner.initialize()
+
+    self.assertFalse(runner.run_fuzz_targets())
+    self.assertEqual(mock_upload_crashes.call_count, 1)
 
 
+@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
+                 'INTEGRATION_TESTS=1 not set')
+class CoverageReportIntegrationTest(unittest.TestCase):
+  """Integration tests for coverage reports."""
+  SANITIZER = 'coverage'
+
+  def setUp(self):
+    test_helpers.patch_environ(self, runner=True)
+
+  @mock.patch('filestore.github_actions._upload_artifact_with_upload_js')
+  def test_coverage_report(self, _):
+    """Tests generation of coverage reports end-to-end, from building to
+    generation."""
+
+    with test_helpers.docker_temp_dir() as temp_dir:
+      shared = os.path.join(temp_dir, 'shared')
+      os.mkdir(shared)
+      copy_command = ('cp -r /opt/code_coverage /shared && '
+                      'cp $(which llvm-profdata) /shared && '
+                      'cp $(which llvm-cov) /shared')
+      assert helper.docker_run([
+          '-v', f'{shared}:/shared', 'gcr.io/oss-fuzz-base/base-runner', 'bash',
+          '-c', copy_command
+      ])
+
+      os.environ['CODE_COVERAGE_SRC'] = os.path.join(shared, 'code_coverage')
+      os.environ['PATH'] += os.pathsep + shared
+      # Do coverage build.
+      build_config = test_helpers.create_build_config(
+          oss_fuzz_project_name=EXAMPLE_PROJECT,
+          project_repo_name='oss-fuzz',
+          workspace=temp_dir,
+          commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523',
+          base_commit='da0746452433dc18bae699e355a9821285d863c8',
+          sanitizer=self.SANITIZER,
+          is_github=True,
+          # Needed for test not to fail because of permissions issues.
+          bad_build_check=False)
+      self.assertTrue(build_fuzzers.build_fuzzers(build_config))
+
+      # TODO(metzman): Get rid of this here and make 'compile' do this.
+      chmod_command = ('chmod -R +r /out && '
+                       'find /out -type d -exec chmod +x {} +')
+
+      assert helper.docker_run([
+          '-v', f'{os.path.join(temp_dir, "build-out")}:/out',
+          'gcr.io/oss-fuzz-base/base-builder', 'bash', '-c', chmod_command
+      ])
+
+      # Generate report.
+      run_config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS,
+                                                  workspace=temp_dir,
+                                                  sanitizer=self.SANITIZER,
+                                                  run_fuzzers_mode='coverage',
+                                                  is_github=True)
+      result = run_fuzzers.run_fuzzers(run_config)
+      self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND)
+      expected_summary_path = os.path.join(
+          TEST_DATA_PATH, 'example_coverage_report_summary.json')
+      with open(expected_summary_path) as file_handle:
+        expected_summary = json.loads(file_handle.read())
+        actual_summary_path = os.path.join(temp_dir, 'cifuzz-coverage',
+                                           'report', 'linux', 'summary.json')
+      with open(actual_summary_path) as file_handle:
+        actual_summary = json.loads(file_handle.read())
+      self.assertEqual(expected_summary, actual_summary)
+
+
+@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
+                 'INTEGRATION_TESTS=1 not set')
 class RunAddressFuzzersIntegrationTest(RunFuzzerIntegrationTestMixin,
                                        unittest.TestCase):
   """Integration tests for build_fuzzers with an ASAN build."""
 
   BUILD_DIR_NAME = 'cifuzz-latest-build'
 
-  @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
-                   'INTEGRATION_TESTS=1 not set')
   def test_new_bug_found(self):
     """Tests run_fuzzers with a valid ASAN build."""
     # Set the first return value to True, then the second to False to
@@ -336,46 +419,61 @@
       with tempfile.TemporaryDirectory() as tmp_dir:
         workspace = os.path.join(tmp_dir, 'workspace')
         shutil.copytree(TEST_DATA_PATH, workspace)
-        config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                                workspace=workspace,
-                                project_name=EXAMPLE_PROJECT)
+        config = test_helpers.create_run_config(
+            fuzz_seconds=FUZZ_SECONDS,
+            workspace=workspace,
+            oss_fuzz_project_name=EXAMPLE_PROJECT)
         result = run_fuzzers.run_fuzzers(config)
         self.assertEqual(result, run_fuzzers.RunFuzzersResult.BUG_FOUND)
-        build_dir = os.path.join(workspace, 'out', self.BUILD_DIR_NAME)
-        self.assertNotEqual(0, len(os.listdir(build_dir)))
 
-  @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
-                   'INTEGRATION_TESTS=1 not set')
   @mock.patch('fuzz_target.FuzzTarget.is_reproducible',
               side_effect=[True, True])
   def test_old_bug_found(self, _):
     """Tests run_fuzzers with a bug found in OSS-Fuzz before."""
-    config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                            workspace=TEST_DATA_PATH,
-                            project_name=EXAMPLE_PROJECT)
     with tempfile.TemporaryDirectory() as tmp_dir:
       workspace = os.path.join(tmp_dir, 'workspace')
       shutil.copytree(TEST_DATA_PATH, workspace)
-      config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                              workspace=TEST_DATA_PATH,
-                              project_name=EXAMPLE_PROJECT)
+      config = test_helpers.create_run_config(
+          fuzz_seconds=FUZZ_SECONDS,
+          workspace=workspace,
+          oss_fuzz_project_name=EXAMPLE_PROJECT)
       result = run_fuzzers.run_fuzzers(config)
       self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND)
-      build_dir = os.path.join(TEST_DATA_PATH, 'out', self.BUILD_DIR_NAME)
-      self.assertTrue(os.path.exists(build_dir))
-      self.assertNotEqual(0, len(os.listdir(build_dir)))
 
   def test_invalid_build(self):
     """Tests run_fuzzers with an invalid ASAN build."""
     with tempfile.TemporaryDirectory() as tmp_dir:
-      out_path = os.path.join(tmp_dir, 'out')
+      out_path = os.path.join(tmp_dir, 'build-out')
       os.mkdir(out_path)
-      config = _create_config(fuzz_seconds=FUZZ_SECONDS,
-                              workspace=tmp_dir,
-                              project_name=EXAMPLE_PROJECT)
+      config = test_helpers.create_run_config(
+          fuzz_seconds=FUZZ_SECONDS,
+          workspace=tmp_dir,
+          oss_fuzz_project_name=EXAMPLE_PROJECT)
       result = run_fuzzers.run_fuzzers(config)
     self.assertEqual(result, run_fuzzers.RunFuzzersResult.ERROR)
 
 
+class GetFuzzTargetRunnerTest(unittest.TestCase):
+  """Tests for get_fuzz_fuzz_target_runner."""
+
+  @parameterized.parameterized.expand([
+      ('batch', run_fuzzers.BatchFuzzTargetRunner),
+      ('ci', run_fuzzers.CiFuzzTargetRunner),
+      ('coverage', run_fuzzers.CoverageTargetRunner)
+  ])
+  def test_get_fuzz_target_runner(self, run_fuzzers_mode,
+                                  fuzz_target_runner_cls):
+    """Tests that get_fuzz_target_runner returns the correct runner based on the
+    specified run_fuzzers_mode."""
+    with tempfile.TemporaryDirectory() as tmp_dir:
+      run_config = test_helpers.create_run_config(
+          fuzz_seconds=FUZZ_SECONDS,
+          workspace=tmp_dir,
+          oss_fuzz_project_name='example',
+          run_fuzzers_mode=run_fuzzers_mode)
+      runner = run_fuzzers.get_fuzz_target_runner(run_config)
+      self.assertTrue(isinstance(runner, fuzz_target_runner_cls))
+
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/infra/cifuzz/stack_parser.py b/infra/cifuzz/stack_parser.py
index 69c44bc..b53f875 100644
--- a/infra/cifuzz/stack_parser.py
+++ b/infra/cifuzz/stack_parser.py
@@ -18,30 +18,30 @@
 # From clusterfuzz: src/python/crash_analysis/crash_analyzer.py
 # Used to get the beginning of the stacktrace.
 STACKTRACE_TOOL_MARKERS = [
-    b'AddressSanitizer',
-    b'ASAN:',
-    b'CFI: Most likely a control flow integrity violation;',
-    b'ERROR: libFuzzer',
-    b'KASAN:',
-    b'LeakSanitizer',
-    b'MemorySanitizer',
-    b'ThreadSanitizer',
-    b'UndefinedBehaviorSanitizer',
-    b'UndefinedSanitizer',
+    'AddressSanitizer',
+    'ASAN:',
+    'CFI: Most likely a control flow integrity violation;',
+    'ERROR: libFuzzer',
+    'KASAN:',
+    'LeakSanitizer',
+    'MemorySanitizer',
+    'ThreadSanitizer',
+    'UndefinedBehaviorSanitizer',
+    'UndefinedSanitizer',
 ]
 
 # From clusterfuzz: src/python/crash_analysis/crash_analyzer.py
 # Used to get the end of the stacktrace.
 STACKTRACE_END_MARKERS = [
-    b'ABORTING',
-    b'END MEMORY TOOL REPORT',
-    b'End of process memory map.',
-    b'END_KASAN_OUTPUT',
-    b'SUMMARY:',
-    b'Shadow byte and word',
-    b'[end of stack trace]',
-    b'\nExiting',
-    b'minidump has been written',
+    'ABORTING',
+    'END MEMORY TOOL REPORT',
+    'End of process memory map.',
+    'END_KASAN_OUTPUT',
+    'SUMMARY:',
+    'Shadow byte and word',
+    '[end of stack trace]',
+    '\nExiting',
+    'minidump has been written',
 ]
 
 
@@ -82,5 +82,5 @@
   summary_str = fuzzer_output[begin_stack:end_stack]
 
   # Write sections of fuzzer output to specific files.
-  with open(parsed_output_file_path, 'ab') as summary_handle:
+  with open(parsed_output_file_path, 'a') as summary_handle:
     summary_handle.write(summary_str)
diff --git a/infra/cifuzz/stack_parser_test.py b/infra/cifuzz/stack_parser_test.py
index faf601f..5a631b4 100644
--- a/infra/cifuzz/stack_parser_test.py
+++ b/infra/cifuzz/stack_parser_test.py
@@ -46,12 +46,12 @@
     # Read the fuzzer output from disk.
     fuzzer_output_path = os.path.join(TEST_DATA_PATH, fuzzer_output_file)
     self.fs.add_real_file(fuzzer_output_path)
-    with open(fuzzer_output_path, 'rb') as fuzzer_output_handle:
+    with open(fuzzer_output_path, 'r') as fuzzer_output_handle:
       fuzzer_output = fuzzer_output_handle.read()
     bug_summary_path = '/bug-summary.txt'
-    with mock.patch('logging.info') as mocked_info:
+    with mock.patch('logging.info') as mock_info:
       stack_parser.parse_fuzzer_output(fuzzer_output, bug_summary_path)
-      mocked_info.assert_not_called()
+      mock_info.assert_not_called()
 
     with open(bug_summary_path) as bug_summary_handle:
       bug_summary = bug_summary_handle.read()
@@ -67,10 +67,10 @@
   def test_parse_invalid_output(self):
     """Checks that no files are created when an invalid input was given."""
     artifact_path = '/bug-summary.txt'
-    with mock.patch('logging.error') as mocked_error:
-      stack_parser.parse_fuzzer_output(b'not a valid output_string',
+    with mock.patch('logging.error') as mock_error:
+      stack_parser.parse_fuzzer_output('not a valid output_string',
                                        artifact_path)
-      assert mocked_error.call_count
+      assert mock_error.call_count
     self.assertFalse(os.path.exists(artifact_path))
 
 
diff --git a/infra/cifuzz/test_data/out/example_crash_fuzzer b/infra/cifuzz/test_data/build-out/example_crash_fuzzer
similarity index 100%
rename from infra/cifuzz/test_data/out/example_crash_fuzzer
rename to infra/cifuzz/test_data/build-out/example_crash_fuzzer
Binary files differ
diff --git a/infra/cifuzz/test_data/out/example_nocrash_fuzzer b/infra/cifuzz/test_data/build-out/example_nocrash_fuzzer
similarity index 100%
rename from infra/cifuzz/test_data/out/example_nocrash_fuzzer
rename to infra/cifuzz/test_data/build-out/example_nocrash_fuzzer
Binary files differ
diff --git a/infra/cifuzz/test_data/example_coverage_report_summary.json b/infra/cifuzz/test_data/example_coverage_report_summary.json
new file mode 100644
index 0000000..0004a1b
--- /dev/null
+++ b/infra/cifuzz/test_data/example_coverage_report_summary.json
@@ -0,0 +1 @@
+{"data": [{"files": [{"filename": "/src/my-git-repo/projects/example/my-api-repo/do_stuff_fuzzer.cpp", "summary": {"branches": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}, "functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 5, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/my-git-repo/projects/example/my-api-repo/my_api.cpp", "summary": {"branches": {"count": 10, "covered": 0, "notcovered": 10, "percent": 0}, "functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 15, "covered": 0, "percent": 0}, "regions": {"count": 11, "covered": 0, "notcovered": 11, "percent": 0}}}], "totals": {"branches": {"count": 10, "covered": 0, "notcovered": 10, "percent": 0}, "functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 20, "covered": 0, "percent": 0}, "regions": {"count": 12, "covered": 0, "notcovered": 12, "percent": 0}}}], "type": "llvm.coverage.json.export", "version": "2.0.1"}
\ No newline at end of file
diff --git a/infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile
new file mode 100644
index 0000000..e245538
--- /dev/null
+++ b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make
+
+COPY . $SRC/external-project
+WORKDIR $SRC/external-project
+COPY .clusterfuzzlite/build.sh $SRC/
diff --git a/infra/cifuzz/test_data/external-project/oss-fuzz/build.sh b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/build.sh
similarity index 100%
rename from infra/cifuzz/test_data/external-project/oss-fuzz/build.sh
rename to infra/cifuzz/test_data/external-project/.clusterfuzzlite/build.sh
diff --git a/infra/cifuzz/test_data/external-project/oss-fuzz/Dockerfile b/infra/cifuzz/test_data/external-project/oss-fuzz/Dockerfile
deleted file mode 100644
index e9dc330..0000000
--- a/infra/cifuzz/test_data/external-project/oss-fuzz/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make
-
-COPY . $SRC/external-project
-WORKDIR external-project
-COPY oss-fuzz/build.sh $SRC/
diff --git a/infra/cifuzz/test_data/memory/out/curl_fuzzer_memory b/infra/cifuzz/test_data/memory/build-out/curl_fuzzer_memory
similarity index 100%
rename from infra/cifuzz/test_data/memory/out/curl_fuzzer_memory
rename to infra/cifuzz/test_data/memory/build-out/curl_fuzzer_memory
Binary files differ
diff --git a/infra/cifuzz/test_data/undefined/out/curl_fuzzer_undefined b/infra/cifuzz/test_data/undefined/build-out/curl_fuzzer_undefined
similarity index 100%
rename from infra/cifuzz/test_data/undefined/out/curl_fuzzer_undefined
rename to infra/cifuzz/test_data/undefined/build-out/curl_fuzzer_undefined
Binary files differ
diff --git a/infra/cifuzz/test_helpers.py b/infra/cifuzz/test_helpers.py
new file mode 100644
index 0000000..85b5a8a
--- /dev/null
+++ b/infra/cifuzz/test_helpers.py
@@ -0,0 +1,116 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Contains convenient helpers for writing tests."""
+
+import contextlib
+import os
+import sys
+import shutil
+import tempfile
+from unittest import mock
+
+import config_utils
+import docker
+import workspace_utils
+
+INFRA_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(INFRA_DIR)
+
+import helper
+
+
+@mock.patch('config_utils._is_dry_run', return_value=True)
+@mock.patch('config_utils.GenericCiEnvironment.project_src_path',
+            return_value=None)
+@mock.patch('os.path.basename', return_value=None)
+def _create_config(config_cls, _, __, ___, **kwargs):
+  """Creates a config object from |config_cls| and then sets every attribute
+  that is a key in |kwargs| to the corresponding value. Asserts that each key in
+  |kwargs| is an attribute of config."""
+  with mock.patch('config_utils.BaseConfig.validate', return_value=True):
+    config = config_cls()
+  for key, value in kwargs.items():
+    assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
+    setattr(config, key, value)
+
+  return config
+
+
+def create_build_config(**kwargs):
+  """Wrapper around _create_config for build configs."""
+  return _create_config(config_utils.BuildFuzzersConfig, **kwargs)
+
+
+def create_run_config(**kwargs):
+  """Wrapper around _create_config for run configs."""
+  return _create_config(config_utils.RunFuzzersConfig, **kwargs)
+
+
+def create_workspace(workspace_path='/workspace'):
+  """Returns a workspace located at |workspace_path| ('/workspace' by
+  default)."""
+  config = create_run_config(workspace=workspace_path)
+  return workspace_utils.Workspace(config)
+
+
+def patch_environ(testcase_obj, env=None, empty=False, runner=False):
+  """Patch environment. |testcase_obj| is the unittest.TestCase that contains
+  tests. |env|, if specified, is a dictionary of environment variables to start
+  from. If |empty| is True then the new patched environment will be empty. If
+  |runner| is True then the necessary environment variables will be set to run
+  the scripts from base-runner."""
+  if env is None:
+    env = {}
+
+  patcher = mock.patch.dict(os.environ, env)
+  testcase_obj.addCleanup(patcher.stop)
+  patcher.start()
+  if empty:
+    for key in os.environ.copy():
+      del os.environ[key]
+
+  if runner:
+    # Add the scripts for base-runner to the path since the wont be in
+    # /usr/local/bin on host machines during testing.
+    base_runner_dir = os.path.join(INFRA_DIR, 'base-images', 'base-runner')
+    os.environ['PATH'] = (os.environ.get('PATH', '') + os.pathsep +
+                          base_runner_dir)
+    if 'GOPATH' not in os.environ:
+      # A GOPATH must be set or else the coverage script fails, even for getting
+      # the coverage of non-Go programs.
+      os.environ['GOPATH'] = '/root/go'
+
+
+@contextlib.contextmanager
+def temp_dir_copy(directory):
+  """Context manager that yields a temporary copy of |directory|."""
+  with tempfile.TemporaryDirectory() as temp_dir:
+    temp_copy_path = os.path.join(temp_dir, os.path.basename(directory))
+    shutil.copytree(directory, temp_copy_path)
+    yield temp_copy_path
+
+
+@contextlib.contextmanager
+def docker_temp_dir():
+  """Returns a temporary a directory that is useful for use with docker. On
+  cleanup this contextmanager uses docker to delete the directory's contents so
+  that if anything is owned by root it can be deleted (which
+  tempfile.TemporaryDirectory() cannot do) by non-root users."""
+  with tempfile.TemporaryDirectory() as temp_dir:
+    yield temp_dir
+    helper.docker_run([
+        '-v', f'{temp_dir}:/temp_dir', '-t', docker.BASE_BUILDER_TAG,
+        '/bin/bash', '-c', 'rm -rf /temp_dir/*'
+    ])
diff --git a/infra/cifuzz/workspace_utils.py b/infra/cifuzz/workspace_utils.py
new file mode 100644
index 0000000..ed296bc
--- /dev/null
+++ b/infra/cifuzz/workspace_utils.py
@@ -0,0 +1,75 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Module for representing the workspace directory which CIFuzz uses."""
+
+import os
+
+
+class Workspace:
+  """Class representing the workspace directory."""
+
+  def __init__(self, config):
+    self.workspace = config.workspace
+
+  def initialize_dir(self, directory):  # pylint: disable=no-self-use
+    """Creates directory if it doesn't already exist, otherwise does nothing."""
+    os.makedirs(directory, exist_ok=True)
+
+  @property
+  def repo_storage(self):
+    """The parent directory for repo storage."""
+    return os.path.join(self.workspace, 'storage')
+
+  @property
+  def out(self):
+    """The out directory used for storing the fuzzer build built by
+    build_fuzzers."""
+    # Don't use 'out' because it needs to be used by artifacts.
+    return os.path.join(self.workspace, 'build-out')
+
+  @property
+  def work(self):
+    """The directory used as the work directory for the fuzzer build/run."""
+    return os.path.join(self.workspace, 'work')
+
+  @property
+  def artifacts(self):
+    """The directory used to store artifacts for download by CI-system users."""
+    # This is hardcoded by a lot of clients, so we need to use this.
+    return os.path.join(self.workspace, 'out', 'artifacts')
+
+  @property
+  def clusterfuzz_build(self):
+    """The directory where builds from ClusterFuzz are stored."""
+    return os.path.join(self.workspace, 'cifuzz-prev-build')
+
+  @property
+  def clusterfuzz_coverage(self):
+    """The directory where builds from ClusterFuzz are stored."""
+    return os.path.join(self.workspace, 'cifuzz-prev-coverage')
+
+  @property
+  def coverage_report(self):
+    """The directory where coverage reports generated by cifuzz are put."""
+    return os.path.join(self.workspace, 'cifuzz-coverage')
+
+  @property
+  def corpora(self):
+    """The directory where corpora from ClusterFuzz are stored."""
+    return os.path.join(self.workspace, 'cifuzz-corpus')
+
+  @property
+  def pruned_corpora(self):
+    """The directory where pruned corpora are stored."""
+    return os.path.join(self.workspace, 'cifuzz-pruned-corpus')
diff --git a/infra/constants.py b/infra/constants.py
new file mode 100644
index 0000000..a323a43
--- /dev/null
+++ b/infra/constants.py
@@ -0,0 +1,38 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+"""Constants for OSS-Fuzz."""
+
+DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH = '.clusterfuzzlite'
+
+DEFAULT_LANGUAGE = 'c++'
+DEFAULT_SANITIZER = 'address'
+DEFAULT_ARCHITECTURE = 'x86_64'
+DEFAULT_ENGINE = 'libfuzzer'
+LANGUAGES = [
+    'c',
+    'c++',
+    'go',
+    'jvm',
+    'python',
+    'rust',
+    'swift',
+]
+LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'jvm', 'rust', 'swift']
+SANITIZERS = [
+    'address', 'none', 'memory', 'undefined', 'dataflow', 'thread', 'coverage'
+]
+ARCHITECTURES = ['i386', 'x86_64']
+ENGINES = ['libfuzzer', 'afl', 'honggfuzz', 'dataflow', 'none']
diff --git a/infra/helper.py b/infra/helper.py
index e24df4d..805f39a 100755
--- a/infra/helper.py
+++ b/infra/helper.py
@@ -22,6 +22,7 @@
 import argparse
 import datetime
 import errno
+import logging
 import os
 import pipes
 import re
@@ -29,25 +30,31 @@
 import sys
 import templates
 
+import constants
+
 OSS_FUZZ_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
 BUILD_DIR = os.path.join(OSS_FUZZ_DIR, 'build')
 
-BASE_IMAGES = [
-    'gcr.io/oss-fuzz-base/base-image',
-    'gcr.io/oss-fuzz-base/base-clang',
-    'gcr.io/oss-fuzz-base/base-builder',
-    'gcr.io/oss-fuzz-base/base-runner',
-    'gcr.io/oss-fuzz-base/base-runner-debug',
-    'gcr.io/oss-fuzz-base/base-sanitizer-libs-builder',
-    'gcr.io/oss-fuzz-base/msan-libs-builder',
-]
+BASE_RUNNER_IMAGE = 'gcr.io/oss-fuzz-base/base-runner'
+
+BASE_IMAGES = {
+    'generic': [
+        'gcr.io/oss-fuzz-base/base-image',
+        'gcr.io/oss-fuzz-base/base-clang',
+        'gcr.io/oss-fuzz-base/base-builder',
+        BASE_RUNNER_IMAGE,
+        'gcr.io/oss-fuzz-base/base-runner-debug',
+    ],
+    'go': ['gcr.io/oss-fuzz-base/base-builder-go'],
+    'jvm': ['gcr.io/oss-fuzz-base/base-builder-jvm'],
+    'python': ['gcr.io/oss-fuzz-base/base-builder-python'],
+    'rust': ['gcr.io/oss-fuzz-base/base-builder-rust'],
+    'swift': ['gcr.io/oss-fuzz-base/base-builder-swift'],
+}
 
 VALID_PROJECT_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_-]+$')
 MAX_PROJECT_NAME_LENGTH = 26
 
-if sys.version_info[0] >= 3:
-  raw_input = input  # pylint: disable=invalid-name
-
 CORPUS_URL_FORMAT = (
     'gs://{project_name}-corpus.clusterfuzz-external.appspot.com/libFuzzer/'
     '{fuzz_target}/')
@@ -55,60 +62,158 @@
     'gs://{project_name}-backup.clusterfuzz-external.appspot.com/corpus/'
     'libFuzzer/{fuzz_target}/')
 
+LANGUAGE_REGEX = re.compile(r'[^\s]+')
 PROJECT_LANGUAGE_REGEX = re.compile(r'\s*language\s*:\s*([^\s]+)')
 
-# Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
+WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)')
+
+LANGUAGES_WITH_BUILDER_IMAGES = {'go', 'jvm', 'python', 'rust', 'swift'}
+
+if sys.version_info[0] >= 3:
+  raw_input = input  # pylint: disable=invalid-name
 
 # pylint: disable=too-many-lines
 
 
+class Project:
+  """Class representing a project that is in OSS-Fuzz or an external project
+  (ClusterFuzzLite user)."""
+
+  def __init__(
+      self,
+      project_name_or_path,
+      is_external=False,
+      build_integration_path=constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH):
+    self.is_external = is_external
+    if self.is_external:
+      self.path = os.path.abspath(project_name_or_path)
+      self.name = os.path.basename(self.path)
+      self.build_integration_path = os.path.join(self.path,
+                                                 build_integration_path)
+    else:
+      self.name = project_name_or_path
+      self.path = os.path.join(OSS_FUZZ_DIR, 'projects', self.name)
+      self.build_integration_path = self.path
+
+  @property
+  def dockerfile_path(self):
+    """Returns path to the project Dockerfile."""
+    return os.path.join(self.build_integration_path, 'Dockerfile')
+
+  @property
+  def language(self):
+    """Returns project language."""
+    if self.is_external:
+      # TODO(metzman): Handle this properly.
+      return constants.DEFAULT_LANGUAGE
+
+    project_yaml_path = os.path.join(self.path, 'project.yaml')
+    with open(project_yaml_path) as file_handle:
+      content = file_handle.read()
+      for line in content.splitlines():
+        match = PROJECT_LANGUAGE_REGEX.match(line)
+        if match:
+          return match.group(1)
+
+    logging.warning('Language not specified in project.yaml.')
+    return None
+
+  @property
+  def out(self):
+    """Returns the out dir for the project. Creates it if needed."""
+    return _get_out_dir(self.name)
+
+  @property
+  def work(self):
+    """Returns the out dir for the project. Creates it if needed."""
+    return _get_project_build_subdir(self.name, 'work')
+
+  @property
+  def corpus(self):
+    """Returns the out dir for the project. Creates it if needed."""
+    return _get_project_build_subdir(self.name, 'corpus')
+
+
 def main():  # pylint: disable=too-many-branches,too-many-return-statements
-  """Get subcommand from program arguments and do it."""
+  """Gets subcommand from program arguments and does it. Returns 0 on success 1
+  on error."""
+  logging.basicConfig(level=logging.INFO)
+
+  parser = get_parser()
+  args = parse_args(parser)
+
+  # Note: this has to happen after parse_args above as parse_args needs to know
+  # the original CWD for external projects.
   os.chdir(OSS_FUZZ_DIR)
   if not os.path.exists(BUILD_DIR):
     os.mkdir(BUILD_DIR)
 
-  args = parse_args()
-
   # We have different default values for `sanitizer` depending on the `engine`.
   # Some commands do not have `sanitizer` argument, so `hasattr` is necessary.
   if hasattr(args, 'sanitizer') and not args.sanitizer:
     if args.engine == 'dataflow':
       args.sanitizer = 'dataflow'
     else:
-      args.sanitizer = 'address'
+      args.sanitizer = constants.DEFAULT_SANITIZER
 
   if args.command == 'generate':
-    return generate(args)
-  if args.command == 'build_image':
-    return build_image(args)
-  if args.command == 'build_fuzzers':
-    return build_fuzzers(args)
-  if args.command == 'check_build':
-    return check_build(args)
-  if args.command == 'download_corpora':
-    return download_corpora(args)
-  if args.command == 'run_fuzzer':
-    return run_fuzzer(args)
-  if args.command == 'coverage':
-    return coverage(args)
-  if args.command == 'reproduce':
-    return reproduce(args)
-  if args.command == 'shell':
-    return shell(args)
-  if args.command == 'pull_images':
-    return pull_images(args)
-
-  return 0
+    result = generate(args)
+  elif args.command == 'build_image':
+    result = build_image(args)
+  elif args.command == 'build_fuzzers':
+    result = build_fuzzers(args)
+  elif args.command == 'check_build':
+    result = check_build(args)
+  elif args.command == 'download_corpora':
+    result = download_corpora(args)
+  elif args.command == 'run_fuzzer':
+    result = run_fuzzer(args)
+  elif args.command == 'coverage':
+    result = coverage(args)
+  elif args.command == 'reproduce':
+    result = reproduce(args)
+  elif args.command == 'shell':
+    result = shell(args)
+  elif args.command == 'pull_images':
+    result = pull_images()
+  else:
+    # Print help string if no arguments provided.
+    parser.print_help()
+    result = False
+  return bool_to_retcode(result)
 
 
-def parse_args(args=None):
-  """Parses args using argparser and returns parsed args."""
+def bool_to_retcode(boolean):
+  """Returns 0 if |boolean| is Truthy, 0 is the standard return code for a
+  successful process execution. Returns 1 otherwise, indicating the process
+  failed."""
+  return 0 if boolean else 1
+
+
+def parse_args(parser, args=None):
+  """Parses |args| using |parser| and returns parsed args. Also changes
+  |args.build_integration_path| to have correct default behavior."""
   # Use default argument None for args so that in production, argparse does its
   # normal behavior, but unittesting is easier.
-  parser = get_parser()
-  return parser.parse_args(args)
+  parsed_args = parser.parse_args(args)
+  project = getattr(parsed_args, 'project', None)
+  if not project:
+    return parsed_args
+
+  # Use hacky method for extracting attributes so that ShellTest works.
+  # TODO(metzman): Fix this.
+  is_external = getattr(parsed_args, 'external', False)
+  parsed_args.project = Project(parsed_args.project, is_external)
+  return parsed_args
+
+
+def _add_external_project_args(parser):
+  parser.add_argument(
+      '--external',
+      help='Is project external?',
+      default=False,
+      action='store_true',
+  )
 
 
 def get_parser():  # pylint: disable=too-many-statements
@@ -118,17 +223,28 @@
 
   generate_parser = subparsers.add_parser(
       'generate', help='Generate files for new project.')
-  generate_parser.add_argument('project_name')
+  generate_parser.add_argument('project')
+  generate_parser.add_argument(
+      '--language',
+      default=constants.DEFAULT_LANGUAGE,
+      choices=['c', 'c++', 'rust', 'go', 'jvm', 'swift', 'python'],
+      help='Project language.')
+  _add_external_project_args(generate_parser)
 
   build_image_parser = subparsers.add_parser('build_image',
                                              help='Build an image.')
-  build_image_parser.add_argument('project_name')
+  build_image_parser.add_argument('project')
   build_image_parser.add_argument('--pull',
                                   action='store_true',
                                   help='Pull latest base image.')
+  build_image_parser.add_argument('--cache',
+                                  action='store_true',
+                                  default=False,
+                                  help='Use docker cache when building image.')
   build_image_parser.add_argument('--no-pull',
                                   action='store_true',
                                   help='Do not pull latest base image.')
+  _add_external_project_args(build_image_parser)
 
   build_fuzzers_parser = subparsers.add_parser(
       'build_fuzzers', help='Build fuzzers for a project.')
@@ -136,10 +252,15 @@
   _add_engine_args(build_fuzzers_parser)
   _add_sanitizer_args(build_fuzzers_parser)
   _add_environment_args(build_fuzzers_parser)
-  build_fuzzers_parser.add_argument('project_name')
+  _add_external_project_args(build_fuzzers_parser)
+  build_fuzzers_parser.add_argument('project')
   build_fuzzers_parser.add_argument('source_path',
                                     help='path of local source',
                                     nargs='?')
+  build_fuzzers_parser.add_argument('--mount_path',
+                                    dest='mount_path',
+                                    help='path to mount local source in '
+                                    '(defaults to WORKDIR)')
   build_fuzzers_parser.add_argument('--clean',
                                     dest='clean',
                                     action='store_true',
@@ -154,26 +275,26 @@
   check_build_parser = subparsers.add_parser(
       'check_build', help='Checks that fuzzers execute without errors.')
   _add_architecture_args(check_build_parser)
-  _add_engine_args(
-      check_build_parser,
-      choices=['libfuzzer', 'afl', 'honggfuzz', 'dataflow', 'none'])
-  _add_sanitizer_args(
-      check_build_parser,
-      choices=['address', 'memory', 'undefined', 'dataflow', 'thread'])
+  _add_engine_args(check_build_parser, choices=constants.ENGINES)
+  _add_sanitizer_args(check_build_parser, choices=constants.SANITIZERS)
   _add_environment_args(check_build_parser)
-  check_build_parser.add_argument('project_name', help='name of the project')
+  check_build_parser.add_argument('project',
+                                  help='name of the project or path (external)')
   check_build_parser.add_argument('fuzzer_name',
                                   help='name of the fuzzer',
                                   nargs='?')
+  _add_external_project_args(check_build_parser)
 
   run_fuzzer_parser = subparsers.add_parser(
       'run_fuzzer', help='Run a fuzzer in the emulated fuzzing environment.')
   _add_engine_args(run_fuzzer_parser)
   _add_sanitizer_args(run_fuzzer_parser)
   _add_environment_args(run_fuzzer_parser)
+  _add_external_project_args(run_fuzzer_parser)
   run_fuzzer_parser.add_argument(
       '--corpus-dir', help='directory to store corpus for the fuzz target')
-  run_fuzzer_parser.add_argument('project_name', help='name of the project')
+  run_fuzzer_parser.add_argument('project',
+                                 help='name of the project or path (external)')
   run_fuzzer_parser.add_argument('fuzzer_name', help='name of the fuzzer')
   run_fuzzer_parser.add_argument('fuzzer_args',
                                  help='arguments to pass to the fuzzer',
@@ -197,35 +318,40 @@
   coverage_parser.add_argument('--corpus-dir',
                                help='specify location of corpus'
                                ' to be used (requires --fuzz-target argument)')
-  coverage_parser.add_argument('project_name', help='name of the project')
+  coverage_parser.add_argument('project',
+                               help='name of the project or path (external)')
   coverage_parser.add_argument('extra_args',
                                help='additional arguments to '
                                'pass to llvm-cov utility.',
                                nargs='*')
+  _add_external_project_args(coverage_parser)
 
   download_corpora_parser = subparsers.add_parser(
       'download_corpora', help='Download all corpora for a project.')
   download_corpora_parser.add_argument('--fuzz-target',
                                        help='specify name of a fuzz target')
-  download_corpora_parser.add_argument('project_name',
-                                       help='name of the project')
+  download_corpora_parser.add_argument(
+      'project', help='name of the project or path (external)')
 
   reproduce_parser = subparsers.add_parser('reproduce',
                                            help='Reproduce a crash.')
   reproduce_parser.add_argument('--valgrind',
                                 action='store_true',
                                 help='run with valgrind')
-  reproduce_parser.add_argument('project_name', help='name of the project')
+  reproduce_parser.add_argument('project',
+                                help='name of the project or path (external)')
   reproduce_parser.add_argument('fuzzer_name', help='name of the fuzzer')
   reproduce_parser.add_argument('testcase_path', help='path of local testcase')
   reproduce_parser.add_argument('fuzzer_args',
                                 help='arguments to pass to the fuzzer',
                                 nargs=argparse.REMAINDER)
   _add_environment_args(reproduce_parser)
+  _add_external_project_args(reproduce_parser)
 
   shell_parser = subparsers.add_parser(
       'shell', help='Run /bin/bash within the builder container.')
-  shell_parser.add_argument('project_name', help='name of the project')
+  shell_parser.add_argument('project',
+                            help='name of the project or path (external)')
   shell_parser.add_argument('source_path',
                             help='path of local source',
                             nargs='?')
@@ -233,6 +359,7 @@
   _add_engine_args(shell_parser)
   _add_sanitizer_args(shell_parser)
   _add_environment_args(shell_parser)
+  _add_external_project_args(shell_parser)
 
   subparsers.add_parser('pull_images', help='Pull base images.')
   return parser
@@ -243,29 +370,33 @@
   return os.path.exists(os.path.join('infra', 'base-images', image_name))
 
 
-def check_project_exists(project_name):
+def check_project_exists(project):
   """Checks if a project exists."""
-  if not os.path.exists(_get_project_dir(project_name)):
-    print(project_name, 'does not exist', file=sys.stderr)
-    return False
+  if os.path.exists(project.path):
+    return True
 
-  return True
+  if project.is_external:
+    descriptive_project_name = project.path
+  else:
+    descriptive_project_name = project.name
+
+  logging.error('"%s" does not exist.', descriptive_project_name)
+  return False
 
 
-def _check_fuzzer_exists(project_name, fuzzer_name):
+def _check_fuzzer_exists(project, fuzzer_name):
   """Checks if a fuzzer exists."""
   command = ['docker', 'run', '--rm']
-  command.extend(['-v', '%s:/out' % _get_output_dir(project_name)])
-  command.append('ubuntu:16.04')
+  command.extend(['-v', '%s:/out' % project.out])
+  command.append(BASE_RUNNER_IMAGE)
 
   command.extend(['/bin/bash', '-c', 'test -f /out/%s' % fuzzer_name])
 
   try:
     subprocess.check_call(command)
   except subprocess.CalledProcessError:
-    print(fuzzer_name,
-          'does not seem to exist. Please run build_fuzzers first.',
-          file=sys.stderr)
+    logging.error('%s does not seem to exist. Please run build_fuzzers first.',
+                  fuzzer_name)
     return False
 
   return True
@@ -281,76 +412,44 @@
   return ' '.join(pipes.quote(part) for part in command)
 
 
-def _get_project_dir(project_name):
-  """Returns path to the project."""
-  return os.path.join(OSS_FUZZ_DIR, 'projects', project_name)
-
-
-def get_dockerfile_path(project_name):
-  """Returns path to the project Dockerfile."""
-  return os.path.join(_get_project_dir(project_name), 'Dockerfile')
-
-
-def _get_corpus_dir(project_name=''):
-  """Creates and returns path to /corpus directory for the given project (if
-  specified)."""
-  directory = os.path.join(BUILD_DIR, 'corpus', project_name)
+def _get_project_build_subdir(project, subdir_name):
+  """Creates the |subdir_name| subdirectory of the |project| subdirectory in
+  |BUILD_DIR| and returns its path."""
+  directory = os.path.join(BUILD_DIR, subdir_name, project)
   if not os.path.exists(directory):
     os.makedirs(directory)
 
   return directory
 
 
-def _get_output_dir(project_name=''):
+def _get_out_dir(project=''):
   """Creates and returns path to /out directory for the given project (if
   specified)."""
-  directory = os.path.join(BUILD_DIR, 'out', project_name)
-  if not os.path.exists(directory):
-    os.makedirs(directory)
-
-  return directory
+  return _get_project_build_subdir(project, 'out')
 
 
-def _get_work_dir(project_name=''):
-  """Creates and returns path to /work directory for the given project (if
-  specified)."""
-  directory = os.path.join(BUILD_DIR, 'work', project_name)
-  if not os.path.exists(directory):
-    os.makedirs(directory)
-
-  return directory
+def _add_architecture_args(parser, choices=None):
+  """Adds common architecture args."""
+  if choices is None:
+    choices = constants.ARCHITECTURES
+  parser.add_argument('--architecture',
+                      default=constants.DEFAULT_ARCHITECTURE,
+                      choices=choices)
 
 
-def _get_project_language(project_name):
-  """Returns project language."""
-  project_yaml_path = os.path.join(OSS_FUZZ_DIR, 'projects', project_name,
-                                   'project.yaml')
-  with open(project_yaml_path) as file_handle:
-    content = file_handle.read()
-    for line in content.splitlines():
-      match = PROJECT_LANGUAGE_REGEX.match(line)
-      if match:
-        return match.group(1)
-
-  return None
+def _add_engine_args(parser, choices=None):
+  """Adds common engine args."""
+  if choices is None:
+    choices = constants.ENGINES
+  parser.add_argument('--engine',
+                      default=constants.DEFAULT_ENGINE,
+                      choices=choices)
 
 
-def _add_architecture_args(parser, choices=('x86_64', 'i386')):
-  """Add common architecture args."""
-  parser.add_argument('--architecture', default='x86_64', choices=choices)
-
-
-def _add_engine_args(parser,
-                     choices=('libfuzzer', 'afl', 'honggfuzz', 'dataflow',
-                              'none')):
-  """Add common engine args."""
-  parser.add_argument('--engine', default='libfuzzer', choices=choices)
-
-
-def _add_sanitizer_args(parser,
-                        choices=('address', 'memory', 'undefined', 'coverage',
-                                 'dataflow', 'thread')):
-  """Add common sanitizer args."""
+def _add_sanitizer_args(parser, choices=None):
+  """Adds common sanitizer args."""
+  if choices is None:
+    choices = constants.SANITIZERS
   parser.add_argument(
       '--sanitizer',
       default=None,
@@ -359,47 +458,50 @@
 
 
 def _add_environment_args(parser):
-  """Add common environment args."""
+  """Adds common environment args."""
   parser.add_argument('-e',
                       action='append',
                       help="set environment variable e.g. VAR=value")
 
 
-def build_image_impl(image_name, no_cache=False, pull=False):
-  """Build image."""
+def build_image_impl(project, cache=True, pull=False):
+  """Builds image."""
+  image_name = project.name
 
-  proj_is_base_image = is_base_image(image_name)
-  if proj_is_base_image:
+  if is_base_image(image_name):
     image_project = 'oss-fuzz-base'
-    dockerfile_dir = os.path.join('infra', 'base-images', image_name)
+    docker_build_dir = os.path.join(OSS_FUZZ_DIR, 'infra', 'base-images',
+                                    image_name)
+    dockerfile_path = os.path.join(docker_build_dir, 'Dockerfile')
   else:
-    image_project = 'oss-fuzz'
-    if not check_project_exists(image_name):
+    if not check_project_exists(project):
       return False
+    dockerfile_path = project.dockerfile_path
+    docker_build_dir = project.path
+    image_project = 'oss-fuzz'
 
-    dockerfile_dir = os.path.join('projects', image_name)
+  if pull and not pull_images(project.language):
+    return False
 
   build_args = []
-  if no_cache:
+  if not cache:
     build_args.append('--no-cache')
 
   build_args += [
-      '-t', 'gcr.io/%s/%s' % (image_project, image_name), dockerfile_dir
+      '-t',
+      'gcr.io/%s/%s' % (image_project, image_name), '--file', dockerfile_path
   ]
-
-  return docker_build(build_args, pull=pull)
+  build_args.append(docker_build_dir)
+  return docker_build(build_args)
 
 
 def _env_to_docker_args(env_list):
-  """Turn envirnoment variable list into docker arguments."""
+  """Turns envirnoment variable list into docker arguments."""
   return sum([['-e', v] for v in env_list], [])
 
 
-WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)')
-
-
 def workdir_from_lines(lines, default='/src'):
-  """Get the WORKDIR from the given lines."""
+  """Gets the WORKDIR from the given lines."""
   for line in reversed(lines):  # reversed to get last WORKDIR.
     match = re.match(WORKDIR_REGEX, line)
     if match:
@@ -414,18 +516,16 @@
   return default
 
 
-def _workdir_from_dockerfile(project_name):
-  """Parse WORKDIR from the Dockerfile for the given project."""
-  dockerfile_path = get_dockerfile_path(project_name)
-
-  with open(dockerfile_path) as file_handle:
+def _workdir_from_dockerfile(project):
+  """Parses WORKDIR from the Dockerfile for the given project."""
+  with open(project.dockerfile_path) as file_handle:
     lines = file_handle.readlines()
 
-  return workdir_from_lines(lines, default=os.path.join('/src', project_name))
+  return workdir_from_lines(lines, default=os.path.join('/src', project.name))
 
 
 def docker_run(run_args, print_output=True):
-  """Call `docker run`."""
+  """Calls `docker run`."""
   command = ['docker', 'run', '--rm', '--privileged']
 
   # Support environments with a TTY.
@@ -434,32 +534,29 @@
 
   command.extend(run_args)
 
-  print('Running:', _get_command_string(command))
+  logging.info('Running: %s.', _get_command_string(command))
   stdout = None
   if not print_output:
     stdout = open(os.devnull, 'w')
 
   try:
     subprocess.check_call(command, stdout=stdout, stderr=subprocess.STDOUT)
-  except subprocess.CalledProcessError as error:
-    return error.returncode
+  except subprocess.CalledProcessError:
+    return False
 
-  return 0
+  return True
 
 
-def docker_build(build_args, pull=False):
-  """Call `docker build`."""
+def docker_build(build_args):
+  """Calls `docker build`."""
   command = ['docker', 'build']
-  if pull:
-    command.append('--pull')
-
   command.extend(build_args)
-  print('Running:', _get_command_string(command))
+  logging.info('Running: %s.', _get_command_string(command))
 
   try:
     subprocess.check_call(command)
   except subprocess.CalledProcessError:
-    print('docker build failed.', file=sys.stderr)
+    logging.error('Docker build failed.')
     return False
 
   return True
@@ -468,22 +565,22 @@
 def docker_pull(image):
   """Call `docker pull`."""
   command = ['docker', 'pull', image]
-  print('Running:', _get_command_string(command))
+  logging.info('Running: %s', _get_command_string(command))
 
   try:
     subprocess.check_call(command)
   except subprocess.CalledProcessError:
-    print('docker pull failed.', file=sys.stderr)
+    logging.error('Docker pull failed.')
     return False
 
   return True
 
 
 def build_image(args):
-  """Build docker image."""
+  """Builds docker image."""
   if args.pull and args.no_pull:
-    print('Incompatible arguments --pull and --no-pull.')
-    return 1
+    logging.error('Incompatible arguments --pull and --no-pull.')
+    return False
 
   if args.pull:
     pull = True
@@ -494,89 +591,74 @@
     pull = y_or_n.lower() == 'y'
 
   if pull:
-    print('Pulling latest base images...')
+    logging.info('Pulling latest base images...')
   else:
-    print('Using cached base images...')
+    logging.info('Using cached base images...')
 
   # If build_image is called explicitly, don't use cache.
-  if build_image_impl(args.project_name, no_cache=True, pull=pull):
-    return 0
+  if build_image_impl(args.project, cache=args.cache, pull=pull):
+    return True
 
-  return 1
+  return False
 
 
 def build_fuzzers_impl(  # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
-    project_name,
+    project,
     clean,
     engine,
     sanitizer,
     architecture,
     env_to_add,
     source_path,
-    no_cache=False,
-    mount_location=None):
-  """Build fuzzers."""
-  if not build_image_impl(project_name, no_cache=no_cache):
-    return 1
-
-  project_out_dir = _get_output_dir(project_name)
-  project_work_dir = _get_work_dir(project_name)
-  project_language = _get_project_language(project_name)
-  if not project_language:
-    print('WARNING: language not specified in project.yaml. Build may fail.')
+    mount_path=None):
+  """Builds fuzzers."""
+  if not build_image_impl(project):
+    return False
 
   if clean:
-    print('Cleaning existing build artifacts.')
+    logging.info('Cleaning existing build artifacts.')
 
     # Clean old and possibly conflicting artifacts in project's out directory.
     docker_run([
         '-v',
-        '%s:/out' % project_out_dir, '-t',
-        'gcr.io/oss-fuzz/%s' % project_name, '/bin/bash', '-c', 'rm -rf /out/*'
+        '%s:/out' % project.out, '-t',
+        'gcr.io/oss-fuzz/%s' % project.name, '/bin/bash', '-c', 'rm -rf /out/*'
     ])
 
     docker_run([
         '-v',
-        '%s:/work' % project_work_dir, '-t',
-        'gcr.io/oss-fuzz/%s' % project_name, '/bin/bash', '-c', 'rm -rf /work/*'
+        '%s:/work' % project.work, '-t',
+        'gcr.io/oss-fuzz/%s' % project.name, '/bin/bash', '-c', 'rm -rf /work/*'
     ])
 
   else:
-    print('Keeping existing build artifacts as-is (if any).')
+    logging.info('Keeping existing build artifacts as-is (if any).')
   env = [
       'FUZZING_ENGINE=' + engine,
       'SANITIZER=' + sanitizer,
       'ARCHITECTURE=' + architecture,
   ]
 
-  if project_language:
-    env.append('FUZZING_LANGUAGE=' + project_language)
+  _add_oss_fuzz_ci_if_needed(env)
+
+  if project.language:
+    env.append('FUZZING_LANGUAGE=' + project.language)
 
   if env_to_add:
     env += env_to_add
 
-  # Copy instrumented libraries.
-  if sanitizer == 'memory':
-    docker_run([
-        '-v',
-        '%s:/work' % project_work_dir, 'gcr.io/oss-fuzz-base/msan-libs-builder',
-        'bash', '-c', 'cp -r /msan /work'
-    ])
-    env.append('MSAN_LIBS_PATH=' + '/work/msan')
-
   command = ['--cap-add', 'SYS_PTRACE'] + _env_to_docker_args(env)
   if source_path:
-    workdir = _workdir_from_dockerfile(project_name)
-    if mount_location:
+    workdir = _workdir_from_dockerfile(project)
+    if mount_path:
       command += [
           '-v',
-          '%s:%s' % (_get_absolute_path(source_path), mount_location),
+          '%s:%s' % (_get_absolute_path(source_path), mount_path),
       ]
     else:
       if workdir == '/src':
-        print('Cannot use local checkout with "WORKDIR: /src".',
-              file=sys.stderr)
-        return 1
+        logging.error('Cannot use local checkout with "WORKDIR: /src".')
+        return False
 
       command += [
           '-v',
@@ -585,50 +667,52 @@
 
   command += [
       '-v',
-      '%s:/out' % project_out_dir, '-v',
-      '%s:/work' % project_work_dir, '-t',
-      'gcr.io/oss-fuzz/%s' % project_name
+      '%s:/out' % project.out, '-v',
+      '%s:/work' % project.work, '-t',
+      'gcr.io/oss-fuzz/%s' % project.name
   ]
 
-  result_code = docker_run(command)
-  if result_code:
-    print('Building fuzzers failed.', file=sys.stderr)
-    return result_code
+  result = docker_run(command)
+  if not result:
+    logging.error('Building fuzzers failed.')
+    return False
 
-  # Patch MSan builds to use instrumented shared libraries.
-  if sanitizer == 'memory':
-    docker_run([
-        '-v',
-        '%s:/out' % project_out_dir, '-v',
-        '%s:/work' % project_work_dir
-    ] + _env_to_docker_args(env) + [
-        'gcr.io/oss-fuzz-base/base-sanitizer-libs-builder', 'patch_build.py',
-        '/out'
-    ])
-
-  return 0
+  return True
 
 
 def build_fuzzers(args):
-  """Build fuzzers."""
-  return build_fuzzers_impl(args.project_name, args.clean, args.engine,
-                            args.sanitizer, args.architecture, args.e,
-                            args.source_path)
+  """Builds fuzzers."""
+  return build_fuzzers_impl(args.project,
+                            args.clean,
+                            args.engine,
+                            args.sanitizer,
+                            args.architecture,
+                            args.e,
+                            args.source_path,
+                            mount_path=args.mount_path)
+
+
+def _add_oss_fuzz_ci_if_needed(env):
+  """Adds value of |OSS_FUZZ_CI| environment variable to |env| if it is set."""
+  oss_fuzz_ci = os.getenv('OSS_FUZZ_CI')
+  if oss_fuzz_ci:
+    env.append('OSS_FUZZ_CI=' + oss_fuzz_ci)
 
 
 def check_build(args):
   """Checks that fuzzers in the container execute without errors."""
-  if not check_project_exists(args.project_name):
-    return 1
+  if not check_project_exists(args.project):
+    return False
 
   if (args.fuzzer_name and
-      not _check_fuzzer_exists(args.project_name, args.fuzzer_name)):
-    return 1
+      not _check_fuzzer_exists(args.project, args.fuzzer_name)):
+    return False
 
-  fuzzing_language = _get_project_language(args.project_name)
-  if fuzzing_language is None:
-    print('WARNING: language not specified in project.yaml. Defaulting to C++.')
-    fuzzing_language = 'c++'
+  fuzzing_language = args.project.language
+  if not fuzzing_language:
+    fuzzing_language = constants.DEFAULT_LANGUAGE
+    logging.warning('Language not specified in project.yaml. Defaulting to %s.',
+                    fuzzing_language)
 
   env = [
       'FUZZING_ENGINE=' + args.engine,
@@ -636,13 +720,12 @@
       'ARCHITECTURE=' + args.architecture,
       'FUZZING_LANGUAGE=' + fuzzing_language,
   ]
+  _add_oss_fuzz_ci_if_needed(env)
   if args.e:
     env += args.e
 
   run_args = _env_to_docker_args(env) + [
-      '-v',
-      '%s:/out' % _get_output_dir(args.project_name), '-t',
-      'gcr.io/oss-fuzz-base/base-runner'
+      '-v', '%s:/out' % args.project.out, '-t', BASE_RUNNER_IMAGE
   ]
 
   if args.fuzzer_name:
@@ -650,39 +733,45 @@
   else:
     run_args.append('test_all.py')
 
-  exit_code = docker_run(run_args)
-  if exit_code == 0:
-    print('Check build passed.')
+  result = docker_run(run_args)
+  if result:
+    logging.info('Check build passed.')
   else:
-    print('Check build failed.')
+    logging.error('Check build failed.')
 
-  return exit_code
+  return result
 
 
-def _get_fuzz_targets(project_name):
-  """Return names of fuzz targest build in the project's /out directory."""
+def _get_fuzz_targets(project):
+  """Returns names of fuzz targest build in the project's /out directory."""
   fuzz_targets = []
-  for name in os.listdir(_get_output_dir(project_name)):
+  for name in os.listdir(project.out):
     if name.startswith('afl-'):
       continue
+    if name.startswith('jazzer_'):
+      continue
+    if name == 'llvm-symbolizer':
+      continue
 
-    path = os.path.join(_get_output_dir(project_name), name)
-    if os.path.isfile(path) and os.access(path, os.X_OK):
+    path = os.path.join(project.out, name)
+    # Python and JVM fuzz targets are only executable for the root user, so
+    # we can't use os.access.
+    if os.path.isfile(path) and (os.stat(path).st_mode & 0o111):
       fuzz_targets.append(name)
 
   return fuzz_targets
 
 
-def _get_latest_corpus(project_name, fuzz_target, base_corpus_dir):
-  """Download the latest corpus for the given fuzz target."""
+def _get_latest_corpus(project, fuzz_target, base_corpus_dir):
+  """Downloads the latest corpus for the given fuzz target."""
   corpus_dir = os.path.join(base_corpus_dir, fuzz_target)
   if not os.path.exists(corpus_dir):
     os.makedirs(corpus_dir)
 
-  if not fuzz_target.startswith(project_name + '_'):
-    fuzz_target = '%s_%s' % (project_name, fuzz_target)
+  if not fuzz_target.startswith(project.name + '_'):
+    fuzz_target = '%s_%s' % (project.name, fuzz_target)
 
-  corpus_backup_url = CORPUS_BACKUP_URL_FORMAT.format(project_name=project_name,
+  corpus_backup_url = CORPUS_BACKUP_URL_FORMAT.format(project_name=project.name,
                                                       fuzz_target=fuzz_target)
   command = ['gsutil', 'ls', corpus_backup_url]
 
@@ -693,8 +782,7 @@
 
   # Some fuzz targets (e.g. new ones) may not have corpus yet, just skip those.
   if corpus_listing.returncode:
-    print('WARNING: corpus for {0} not found:\n'.format(fuzz_target),
-          file=sys.stderr)
+    logging.warning('Corpus for %s not found:\n', fuzz_target)
     return
 
   if output:
@@ -708,80 +796,73 @@
     os.remove(archive_path)
   else:
     # Sync the working corpus copy if a minimized backup is not available.
-    corpus_url = CORPUS_URL_FORMAT.format(project_name=project_name,
+    corpus_url = CORPUS_URL_FORMAT.format(project_name=project.name,
                                           fuzz_target=fuzz_target)
     command = ['gsutil', '-m', '-q', 'rsync', '-R', corpus_url, corpus_dir]
     subprocess.check_call(command)
 
 
 def download_corpora(args):
-  """Download most recent corpora from GCS for the given project."""
-  if not check_project_exists(args.project_name):
-    return 1
+  """Downloads most recent corpora from GCS for the given project."""
+  if not check_project_exists(args.project):
+    return False
 
   try:
     with open(os.devnull, 'w') as stdout:
       subprocess.check_call(['gsutil', '--version'], stdout=stdout)
   except OSError:
-    print(
-        'ERROR: gsutil not found. Please install it from '
-        'https://cloud.google.com/storage/docs/gsutil_install',
-        file=sys.stderr)
+    logging.error('gsutil not found. Please install it from '
+                  'https://cloud.google.com/storage/docs/gsutil_install')
     return False
 
   if args.fuzz_target:
     fuzz_targets = [args.fuzz_target]
   else:
-    fuzz_targets = _get_fuzz_targets(args.project_name)
+    fuzz_targets = _get_fuzz_targets(args.project)
 
-  corpus_dir = _get_corpus_dir(args.project_name)
-  if not os.path.exists(corpus_dir):
-    os.makedirs(corpus_dir)
+  corpus_dir = args.project.corpus
 
   def _download_for_single_target(fuzz_target):
     try:
-      _get_latest_corpus(args.project_name, fuzz_target, corpus_dir)
+      _get_latest_corpus(args.project, fuzz_target, corpus_dir)
       return True
     except Exception as error:  # pylint:disable=broad-except
-      print('ERROR: corpus download for %s failed: %s' %
-            (fuzz_target, str(error)),
-            file=sys.stderr)
+      logging.error('Corpus download for %s failed: %s.', fuzz_target,
+                    str(error))
       return False
 
-  print('Downloading corpora for %s project to %s' %
-        (args.project_name, corpus_dir))
+  logging.info('Downloading corpora for %s project to %s.', args.project.name,
+               corpus_dir)
   thread_pool = ThreadPool()
   return all(thread_pool.map(_download_for_single_target, fuzz_targets))
 
 
 def coverage(args):
-  """Generate code coverage using clang source based code coverage."""
+  """Generates code coverage using clang source based code coverage."""
   if args.corpus_dir and not args.fuzz_target:
-    print(
-        'ERROR: --corpus-dir requires specifying a particular fuzz target '
-        'using --fuzz-target',
-        file=sys.stderr)
-    return 1
+    logging.error(
+        '--corpus-dir requires specifying a particular fuzz target using '
+        '--fuzz-target')
+    return False
 
-  if not check_project_exists(args.project_name):
-    return 1
+  if not check_project_exists(args.project):
+    return False
 
-  project_language = _get_project_language(args.project_name)
-  if project_language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
-    print(
-        'ERROR: Project is written in %s, coverage for it is not supported yet.'
-        % project_language,
-        file=sys.stderr)
-    return 1
+  if args.project.language not in constants.LANGUAGES_WITH_COVERAGE_SUPPORT:
+    logging.error(
+        'Project is written in %s, coverage for it is not supported yet.',
+        args.project.language)
+    return False
 
-  if not args.no_corpus_download and not args.corpus_dir:
+  if (not args.no_corpus_download and not args.corpus_dir and
+      not args.project.is_external):
     if not download_corpora(args):
-      return 1
+      return False
 
   env = [
       'FUZZING_ENGINE=libfuzzer',
-      'FUZZING_LANGUAGE=%s' % project_language,
-      'PROJECT=%s' % args.project_name,
+      'FUZZING_LANGUAGE=%s' % args.project.language,
+      'PROJECT=%s' % args.project.name,
       'SANITIZER=coverage',
       'HTTP_PORT=%s' % args.port,
       'COVERAGE_EXTRA_ARGS=%s' % ' '.join(args.extra_args),
@@ -797,41 +878,41 @@
 
   if args.corpus_dir:
     if not os.path.exists(args.corpus_dir):
-      print('ERROR: the path provided in --corpus-dir argument does not exist',
-            file=sys.stderr)
-      return 1
+      logging.error('The path provided in --corpus-dir argument does not '
+                    'exist.')
+      return False
     corpus_dir = os.path.realpath(args.corpus_dir)
     run_args.extend(['-v', '%s:/corpus/%s' % (corpus_dir, args.fuzz_target)])
   else:
-    run_args.extend(['-v', '%s:/corpus' % _get_corpus_dir(args.project_name)])
+    run_args.extend(['-v', '%s:/corpus' % args.project.corpus])
 
   run_args.extend([
       '-v',
-      '%s:/out' % _get_output_dir(args.project_name),
+      '%s:/out' % args.project.out,
       '-t',
-      'gcr.io/oss-fuzz-base/base-runner',
+      BASE_RUNNER_IMAGE,
   ])
 
   run_args.append('coverage')
   if args.fuzz_target:
     run_args.append(args.fuzz_target)
 
-  exit_code = docker_run(run_args)
-  if exit_code == 0:
-    print('Successfully generated clang code coverage report.')
+  result = docker_run(run_args)
+  if result:
+    logging.info('Successfully generated clang code coverage report.')
   else:
-    print('Failed to generate clang code coverage report.')
+    logging.error('Failed to generate clang code coverage report.')
 
-  return exit_code
+  return result
 
 
 def run_fuzzer(args):
   """Runs a fuzzer in the container."""
-  if not check_project_exists(args.project_name):
-    return 1
+  if not check_project_exists(args.project):
+    return False
 
-  if not _check_fuzzer_exists(args.project_name, args.fuzzer_name):
-    return 1
+  if not _check_fuzzer_exists(args.project, args.fuzzer_name):
+    return False
 
   env = [
       'FUZZING_ENGINE=' + args.engine,
@@ -846,9 +927,8 @@
 
   if args.corpus_dir:
     if not os.path.exists(args.corpus_dir):
-      print('ERROR: the path provided in --corpus-dir argument does not exist',
-            file=sys.stderr)
-      return 1
+      logging.error('The path provided in --corpus-dir argument does not exist')
+      return False
     corpus_dir = os.path.realpath(args.corpus_dir)
     run_args.extend([
         '-v',
@@ -858,9 +938,9 @@
 
   run_args.extend([
       '-v',
-      '%s:/out' % _get_output_dir(args.project_name),
+      '%s:/out' % args.project.out,
       '-t',
-      'gcr.io/oss-fuzz-base/base-runner',
+      BASE_RUNNER_IMAGE,
       'run_fuzzer',
       args.fuzzer_name,
   ] + args.fuzzer_args)
@@ -869,25 +949,25 @@
 
 
 def reproduce(args):
-  """Reproduce a specific test case from a specific project."""
-  return reproduce_impl(args.project_name, args.fuzzer_name, args.valgrind,
-                        args.e, args.fuzzer_args, args.testcase_path)
+  """Reproduces a specific test case from a specific project."""
+  return reproduce_impl(args.project, args.fuzzer_name, args.valgrind, args.e,
+                        args.fuzzer_args, args.testcase_path)
 
 
 def reproduce_impl(  # pylint: disable=too-many-arguments
-    project_name,
+    project,
     fuzzer_name,
     valgrind,
     env_to_add,
     fuzzer_args,
     testcase_path,
-    runner=docker_run,
-    err_result=1):
+    run_function=docker_run,
+    err_result=False):
   """Reproduces a testcase in the container."""
-  if not check_project_exists(project_name):
+  if not check_project_exists(project):
     return err_result
 
-  if not _check_fuzzer_exists(project_name, fuzzer_name):
+  if not _check_fuzzer_exists(project, fuzzer_name):
     return err_result
 
   debugger = ''
@@ -906,7 +986,7 @@
 
   run_args = _env_to_docker_args(env) + [
       '-v',
-      '%s:/out' % _get_output_dir(project_name),
+      '%s:/out' % project.out,
       '-v',
       '%s:/testcase' % _get_absolute_path(testcase_path),
       '-t',
@@ -916,55 +996,109 @@
       '-runs=100',
   ] + fuzzer_args
 
-  return runner(run_args)
+  return run_function(run_args)
 
 
-def generate(args):
-  """Generate empty project files."""
-  if len(args.project_name) > MAX_PROJECT_NAME_LENGTH:
-    print('Project name needs to be less than or equal to %d characters.' %
-          MAX_PROJECT_NAME_LENGTH,
-          file=sys.stderr)
-    return 1
+def _validate_project_name(project_name):
+  """Validates |project_name| is a valid OSS-Fuzz project name."""
+  if len(project_name) > MAX_PROJECT_NAME_LENGTH:
+    logging.error(
+        'Project name needs to be less than or equal to %d characters.',
+        MAX_PROJECT_NAME_LENGTH)
+    return False
 
-  if not VALID_PROJECT_NAME_REGEX.match(args.project_name):
-    print('Invalid project name.', file=sys.stderr)
-    return 1
+  if not VALID_PROJECT_NAME_REGEX.match(project_name):
+    logging.info('Invalid project name: %s.', project_name)
+    return False
 
-  directory = os.path.join('projects', args.project_name)
+  return True
 
+
+def _validate_language(language):
+  if not LANGUAGE_REGEX.match(language):
+    logging.error('Invalid project language %s.', language)
+    return False
+
+  return True
+
+
+def _create_build_integration_directory(directory):
+  """Returns True on successful creation of a build integration directory.
+  Suitable for OSS-Fuzz and external projects."""
   try:
-    os.mkdir(directory)
+    os.makedirs(directory)
   except OSError as error:
     if error.errno != errno.EEXIST:
       raise
-    print(directory, 'already exists.', file=sys.stderr)
-    return 1
+    logging.error('%s already exists.', directory)
+    return False
+  return True
 
-  print('Writing new files to', directory)
+
+def _template_project_file(filename, template, template_args, directory):
+  """Templates |template| using |template_args| and writes the result to
+  |directory|/|filename|. Sets the file to executable if |filename| is
+  build.sh."""
+  file_path = os.path.join(directory, filename)
+  with open(file_path, 'w') as file_handle:
+    file_handle.write(template % template_args)
+
+  if filename == 'build.sh':
+    os.chmod(file_path, 0o755)
+
+
+def generate(args):
+  """Generates empty project files."""
+  return _generate_impl(args.project, args.language)
+
+
+def _get_current_datetime():
+  """Returns this year. Needed for mocking."""
+  return datetime.datetime.now()
+
+
+def _base_builder_from_language(language):
+  """Returns the base builder for the specified language."""
+  if language not in LANGUAGES_WITH_BUILDER_IMAGES:
+    return 'base-builder'
+  return 'base-builder-{language}'.format(language=language)
+
+
+def _generate_impl(project, language):
+  """Implementation of generate(). Useful for testing."""
+  if project.is_external:
+    # External project.
+    project_templates = templates.EXTERNAL_TEMPLATES
+  else:
+    # Internal project.
+    if not _validate_project_name(project.name):
+      return False
+    project_templates = templates.TEMPLATES
+
+  if not _validate_language(language):
+    return False
+
+  directory = project.build_integration_path
+  if not _create_build_integration_directory(directory):
+    return False
+
+  logging.info('Writing new files to: %s.', directory)
 
   template_args = {
-      'project_name': args.project_name,
-      'year': datetime.datetime.now().year
+      'project_name': project.name,
+      'base_builder': _base_builder_from_language(language),
+      'language': language,
+      'year': _get_current_datetime().year
   }
-  with open(os.path.join(directory, 'project.yaml'), 'w') as file_handle:
-    file_handle.write(templates.PROJECT_YAML_TEMPLATE % template_args)
-
-  with open(os.path.join(directory, 'Dockerfile'), 'w') as file_handle:
-    file_handle.write(templates.DOCKER_TEMPLATE % template_args)
-
-  build_sh_path = os.path.join(directory, 'build.sh')
-  with open(build_sh_path, 'w') as file_handle:
-    file_handle.write(templates.BUILD_TEMPLATE % template_args)
-
-  os.chmod(build_sh_path, 0o755)
-  return 0
+  for filename, template in project_templates.items():
+    _template_project_file(filename, template, template_args, directory)
+  return True
 
 
 def shell(args):
   """Runs a shell within a docker image."""
-  if not build_image_impl(args.project_name):
-    return 1
+  if not build_image_impl(args.project):
+    return False
 
   env = [
       'FUZZING_ENGINE=' + args.engine,
@@ -972,18 +1106,18 @@
       'ARCHITECTURE=' + args.architecture,
   ]
 
-  if args.project_name != 'base-runner-debug':
-    env.append('FUZZING_LANGUAGE=' + _get_project_language(args.project_name))
+  if args.project.name != 'base-runner-debug':
+    env.append('FUZZING_LANGUAGE=' + args.project.language)
 
   if args.e:
     env += args.e
 
-  if is_base_image(args.project_name):
+  if is_base_image(args.project.name):
     image_project = 'oss-fuzz-base'
-    out_dir = _get_output_dir()
+    out_dir = _get_out_dir()
   else:
     image_project = 'oss-fuzz'
-    out_dir = _get_output_dir(args.project_name)
+    out_dir = args.project.out
 
   run_args = _env_to_docker_args(env)
   if args.source_path:
@@ -995,21 +1129,25 @@
   run_args.extend([
       '-v',
       '%s:/out' % out_dir, '-v',
-      '%s:/work' % _get_work_dir(args.project_name), '-t',
-      'gcr.io/%s/%s' % (image_project, args.project_name), '/bin/bash'
+      '%s:/work' % args.project.work, '-t',
+      'gcr.io/%s/%s' % (image_project, args.project.name), '/bin/bash'
   ])
 
   docker_run(run_args)
-  return 0
+  return True
 
 
-def pull_images(_):
-  """Pull base images."""
-  for base_image in BASE_IMAGES:
-    if not docker_pull(base_image):
-      return 1
+def pull_images(language=None):
+  """Pulls base images used to build projects in language lang (or all if lang
+  is None)."""
+  for base_image_lang, base_images in BASE_IMAGES.items():
+    if (language is None or base_image_lang == 'generic' or
+        base_image_lang == language):
+      for base_image in base_images:
+        if not docker_pull(base_image):
+          return False
 
-  return 0
+  return True
 
 
 if __name__ == '__main__':
diff --git a/infra/helper_test.py b/infra/helper_test.py
index d899a83..951eba4 100644
--- a/infra/helper_test.py
+++ b/infra/helper_test.py
@@ -13,23 +13,224 @@
 # limitations under the License.
 """Tests for helper.py"""
 
+import datetime
+import os
+import tempfile
 import unittest
 from unittest import mock
 
+from pyfakefs import fake_filesystem_unittest
+
+import constants
 import helper
+import templates
+
+# pylint: disable=no-self-use,protected-access
 
 
-class TestShell(unittest.TestCase):
+class ShellTest(unittest.TestCase):
   """Tests 'shell' command."""
 
   @mock.patch('helper.docker_run')
   @mock.patch('helper.build_image_impl')
-  def test_base_runner_debug(self, mocked_build_image_impl, _):
+  def test_base_runner_debug(self, _, __):
     """Tests that shell base-runner-debug works as intended."""
     image_name = 'base-runner-debug'
     unparsed_args = ['shell', image_name]
-    args = helper.parse_args(unparsed_args)
+    parser = helper.get_parser()
+    args = helper.parse_args(parser, unparsed_args)
     args.sanitizer = 'address'
     result = helper.shell(args)
-    mocked_build_image_impl.assert_called_with(image_name)
-    self.assertEqual(result, 0)
+    self.assertTrue(result)
+
+
+class BuildImageImplTest(unittest.TestCase):
+  """Tests for build_image_impl."""
+
+  @mock.patch('helper.docker_build')
+  def test_no_cache(self, mock_docker_build):
+    """Tests that cache=False is handled properly."""
+    image_name = 'base-image'
+    helper.build_image_impl(helper.Project(image_name), cache=False)
+    self.assertIn('--no-cache', mock_docker_build.call_args_list[0][0][0])
+
+  @mock.patch('helper.docker_build')
+  @mock.patch('helper.pull_images')
+  def test_pull(self, mock_pull_images, _):
+    """Tests that pull=True is handled properly."""
+    image_name = 'base-image'
+    project = helper.Project(image_name, is_external=True)
+    self.assertTrue(helper.build_image_impl(project, pull=True))
+    mock_pull_images.assert_called_with('c++')
+
+  @mock.patch('helper.docker_build')
+  def test_base_image(self, mock_docker_build):
+    """Tests that build_image_impl works as intended with a base-image."""
+    image_name = 'base-image'
+    self.assertTrue(helper.build_image_impl(helper.Project(image_name)))
+    build_dir = os.path.join(helper.OSS_FUZZ_DIR,
+                             'infra/base-images/base-image')
+    mock_docker_build.assert_called_with([
+        '-t', 'gcr.io/oss-fuzz-base/base-image', '--file',
+        os.path.join(build_dir, 'Dockerfile'), build_dir
+    ])
+
+  @mock.patch('helper.docker_build')
+  def test_oss_fuzz_project(self, mock_docker_build):
+    """Tests that build_image_impl works as intended with an OSS-Fuzz
+    project."""
+    project_name = 'example'
+    self.assertTrue(helper.build_image_impl(helper.Project(project_name)))
+    build_dir = os.path.join(helper.OSS_FUZZ_DIR, 'projects', project_name)
+    mock_docker_build.assert_called_with([
+        '-t', 'gcr.io/oss-fuzz/example', '--file',
+        os.path.join(build_dir, 'Dockerfile'), build_dir
+    ])
+
+  @mock.patch('helper.docker_build')
+  def test_external_project(self, mock_docker_build):
+    """Tests that build_image_impl works as intended with a non-OSS-Fuzz
+    project."""
+    with tempfile.TemporaryDirectory() as temp_dir:
+      project_src_path = os.path.join(temp_dir, 'example')
+      os.mkdir(project_src_path)
+      build_integration_path = 'build-integration'
+      project = helper.Project(project_src_path,
+                               is_external=True,
+                               build_integration_path=build_integration_path)
+      self.assertTrue(helper.build_image_impl(project))
+      mock_docker_build.assert_called_with([
+          '-t', 'gcr.io/oss-fuzz/example', '--file',
+          os.path.join(project_src_path, build_integration_path, 'Dockerfile'),
+          project_src_path
+      ])
+
+
+class GenerateImplTest(fake_filesystem_unittest.TestCase):
+  """Tests for _generate_impl."""
+  PROJECT_NAME = 'newfakeproject'
+  PROJECT_LANGUAGE = 'python'
+
+  def setUp(self):
+    self.setUpPyfakefs()
+    self.fs.add_real_directory(helper.OSS_FUZZ_DIR)
+
+  def _verify_templated_files(self, template_dict, directory, language):
+    template_args = {
+        'project_name': self.PROJECT_NAME,
+        'year': 2021,
+        'base_builder': helper._base_builder_from_language(language),
+        'language': language,
+    }
+    for filename, template in template_dict.items():
+      file_path = os.path.join(directory, filename)
+      with open(file_path, 'r') as file_handle:
+        contents = file_handle.read()
+      self.assertEqual(contents, template % template_args)
+
+  @mock.patch('helper._get_current_datetime',
+              return_value=datetime.datetime(year=2021, month=1, day=1))
+  def test_generate_oss_fuzz_project(self, _):
+    """Tests that the correct files are generated for an OSS-Fuzz project."""
+    helper._generate_impl(helper.Project(self.PROJECT_NAME),
+                          self.PROJECT_LANGUAGE)
+    self._verify_templated_files(
+        templates.TEMPLATES,
+        os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.PROJECT_NAME),
+        self.PROJECT_LANGUAGE)
+
+  def test_generate_external_project(self):
+    """Tests that the correct files are generated for a non-OSS-Fuzz project."""
+    build_integration_path = '/newfakeproject/build-integration'
+    helper._generate_impl(
+        helper.Project('/newfakeproject/',
+                       is_external=True,
+                       build_integration_path=build_integration_path),
+        self.PROJECT_LANGUAGE)
+    self._verify_templated_files(templates.EXTERNAL_TEMPLATES,
+                                 build_integration_path, self.PROJECT_LANGUAGE)
+
+  def test_generate_swift_project(self):
+    """Tests that the swift project uses the correct base image."""
+    helper._generate_impl(helper.Project(self.PROJECT_NAME), 'swift')
+    self._verify_templated_files(
+        templates.TEMPLATES,
+        os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.PROJECT_NAME),
+        'swift')
+
+
+class ProjectTest(fake_filesystem_unittest.TestCase):
+  """Tests for Project class."""
+
+  def setUp(self):
+    self.project_name = 'project'
+    self.internal_project = helper.Project(self.project_name)
+    self.external_project_path = os.path.join('/path', 'to', self.project_name)
+    self.external_project = helper.Project(self.external_project_path,
+                                           is_external=True)
+    self.setUpPyfakefs()
+
+  def test_init_external_project(self):
+    """Tests __init__ method for external projects."""
+    self.assertEqual(self.external_project.name, self.project_name)
+    self.assertEqual(self.external_project.path, self.external_project_path)
+    self.assertEqual(
+        self.external_project.build_integration_path,
+        os.path.join(self.external_project_path,
+                     constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH))
+
+  def test_init_internal_project(self):
+    """Tests __init__ method for internal projects."""
+    self.assertEqual(self.internal_project.name, self.project_name)
+    path = os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.project_name)
+    self.assertEqual(self.internal_project.path, path)
+    self.assertEqual(self.internal_project.build_integration_path, path)
+
+  def test_dockerfile_path_internal_project(self):
+    """Tests that dockerfile_path works as intended."""
+    self.assertEqual(
+        self.internal_project.dockerfile_path,
+        os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.project_name,
+                     'Dockerfile'))
+
+  def test_dockerfile_path_external_project(self):
+    """Tests that dockerfile_path works as intended."""
+    self.assertEqual(
+        self.external_project.dockerfile_path,
+        os.path.join(self.external_project_path,
+                     constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH,
+                     'Dockerfile'))
+
+  def test_out(self):
+    """Tests that out works as intended."""
+    out_dir = self.internal_project.out
+    self.assertEqual(
+        out_dir,
+        os.path.join(helper.OSS_FUZZ_DIR, 'build', 'out', self.project_name))
+    self.assertTrue(os.path.exists(out_dir))
+
+  def test_work(self):
+    """Tests that work works as intended."""
+    work_dir = self.internal_project.work
+    self.assertEqual(
+        work_dir,
+        os.path.join(helper.OSS_FUZZ_DIR, 'build', 'work', self.project_name))
+    self.assertTrue(os.path.exists(work_dir))
+
+  def test_corpus(self):
+    """Tests that corpus works as intended."""
+    corpus_dir = self.internal_project.corpus
+    self.assertEqual(
+        corpus_dir,
+        os.path.join(helper.OSS_FUZZ_DIR, 'build', 'corpus', self.project_name))
+    self.assertTrue(os.path.exists(corpus_dir))
+
+  def test_language_internal_project(self):
+    """Tests that language works as intended for an internal project."""
+    project_yaml_path = os.path.join(self.internal_project.path, 'project.yaml')
+    self.fs.create_file(project_yaml_path, contents='language: python')
+    self.assertEqual(self.internal_project.language, 'python')
+
+  def test_language_external_project(self):
+    """Tests that language works as intended for an external project."""
+    self.assertEqual(self.external_project.language, 'c++')
diff --git a/infra/presubmit.py b/infra/presubmit.py
index 90b4f90..6db1862 100755
--- a/infra/presubmit.py
+++ b/infra/presubmit.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python3
-# Copyright 2020 Google LLC.
+# Copyright 2020 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 ################################################################################
-"""Check code for common issues before submitting."""
+"""Checks code for common issues before submitting."""
 
 import argparse
 import os
@@ -23,6 +23,8 @@
 import unittest
 import yaml
 
+import constants
+
 _SRC_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 
@@ -62,8 +64,8 @@
 
 
 def check_lib_fuzzing_engine(paths):
-  """Call _check_one_lib_fuzzing_engine on each path in |paths|. Return True if
-  the result of every call is True."""
+  """Calls _check_one_lib_fuzzing_engine on each path in |paths|. Returns True
+  if the result of every call is True."""
   return all([_check_one_lib_fuzzing_engine(path) for path in paths])
 
 
@@ -73,9 +75,9 @@
   # Sections in a project.yaml and the constant values that they are allowed
   # to have.
   SECTIONS_AND_CONSTANTS = {
-      'sanitizers': {'address', 'none', 'memory', 'undefined', 'dataflow'},
-      'architectures': {'i386', 'x86_64'},
-      'fuzzing_engines': {'afl', 'libfuzzer', 'honggfuzz', 'dataflow', 'none'},
+      'sanitizers': constants.SANITIZERS,
+      'architectures': constants.ARCHITECTURES,
+      'fuzzing_engines': constants.ENGINES,
   }
 
   # Note: this list must be updated when we allow new sections.
@@ -100,15 +102,6 @@
       'view_restrictions',
   ]
 
-  LANGUAGES_SUPPORTED = [
-      'c',
-      'c++',
-      'go',
-      'jvm',
-      'python',
-      'rust',
-  ]
-
   # Note that some projects like boost only have auto-ccs. However, forgetting
   # primary contact is probably a mistake.
   REQUIRED_SECTIONS = ['primary_contact', 'main_repo']
@@ -121,7 +114,7 @@
     self.success = True
 
   def do_checks(self):
-    """Do all project.yaml checks. Return True if they pass."""
+    """Does all project.yaml checks. Returns True if they pass."""
     if self.is_disabled():
       return True
 
@@ -131,23 +124,43 @@
         self.check_valid_section_names,
         self.check_valid_emails,
         self.check_valid_language,
+        self.check_dataflow,
     ]
     for check_function in checks:
       check_function()
     return self.success
 
   def is_disabled(self):
-    """Is this project disabled."""
+    """Returns True if this project is disabled."""
     return self.data.get('disabled', False)
 
   def error(self, message):
-    """Print an error message and set self.success to False."""
+    """Prints an error message and sets self.success to False."""
     self.success = False
     print('Error in {filename}: {message}'.format(filename=self.filename,
                                                   message=message))
 
+  def check_dataflow(self):
+    """Checks that if "dataflow" is specified in "fuzzing_engines", it is also
+    specified in "sanitizers", and that if specified in "sanitizers", it is also
+    specified in "fuzzing_engines". Returns True if this condition is met."""
+    engines = self.data.get('fuzzing_engines', [])
+    dfsan_engines = 'dataflow' in engines
+    sanitizers = self.data.get('sanitizers', [])
+    dfsan_sanitizers = 'dataflow' in sanitizers
+
+    if dfsan_engines and not dfsan_sanitizers:
+      self.error('"dataflow" only specified in "fuzzing_engines" must also be '
+                 'specified in "sanitizers" or in neither.')
+      return
+
+    if dfsan_sanitizers and not dfsan_engines:
+      self.error('"dataflow" only specified in "sanitizers" must also be '
+                 'specified in "fuzzing_engines" or in neither.')
+      return
+
   def check_project_yaml_constants(self):
-    """Check that certain sections only have certain constant values."""
+    """Returns True if certain sections only have certain constant values."""
     for section, allowed_constants in self.SECTIONS_AND_CONSTANTS.items():
       if section not in self.data:
         continue
@@ -172,20 +185,20 @@
           self.error('Not allowed value in the project.yaml: ' + str(constant))
 
   def check_valid_section_names(self):
-    """Check that only valid sections are included."""
+    """Returns True if all section names are valid."""
     for name in self.data:
       if name not in self.VALID_SECTION_NAMES:
         self.error('{name} is not a valid section name ({valid_names})'.format(
             name=name, valid_names=self.VALID_SECTION_NAMES))
 
   def check_required_sections(self):
-    """Check that all required sections are present."""
+    """Returns True if all required sections are in |self.data|."""
     for section in self.REQUIRED_SECTIONS:
       if section not in self.data:
         self.error(section + ' section is missing.')
 
   def check_valid_emails(self):
-    """Check that emails are valid looking."""
+    """Returns True if emails are valid looking.."""
     # Get email addresses.
     email_addresses = []
     primary_contact = self.data.get('primary_contact')
@@ -201,18 +214,18 @@
         self.error(email_address + ' is an invalid email address.')
 
   def check_valid_language(self):
-    """Check that the language is specified and valid."""
+    """Returns True if the language is specified and valid."""
     language = self.data.get('language')
     if not language:
       self.error('Missing "language" attribute in project.yaml.')
-    elif language not in self.LANGUAGES_SUPPORTED:
+    elif language not in constants.LANGUAGES:
       self.error(
           '"language: {language}" is not supported ({supported}).'.format(
-              language=language, supported=self.LANGUAGES_SUPPORTED))
+              language=language, supported=constants.LANGUAGES))
 
 
 def _check_one_project_yaml(project_yaml_filename):
-  """Do checks on the project.yaml file."""
+  """Does checks on the project.yaml file. Returns True on success."""
   if not _is_project_file(project_yaml_filename, 'project.yaml'):
     return True
 
@@ -221,13 +234,13 @@
 
 
 def check_project_yaml(paths):
-  """Call _check_one_project_yaml on each path in |paths|. Return True if
-  the result of every call is True."""
+  """Calls _check_one_project_yaml on each path in |paths|. Returns True if the
+  result of every call is True."""
   return all([_check_one_project_yaml(path) for path in paths])
 
 
 def do_checks(changed_files):
-  """Run all presubmit checks return False if any fails."""
+  """Runs all presubmit checks. Returns False if any fails."""
   checks = [
       check_license, yapf, lint, check_project_yaml, check_lib_fuzzing_engine
   ]
@@ -245,6 +258,7 @@
     '.cc',
     '.cpp',
     '.css',
+    '.Dockerfile',
     '.h',
     '.htm',
     '.html',
@@ -253,17 +267,21 @@
     '.py',
     '.sh',
 ]
+THIRD_PARTY_DIR_NAME = 'third_party'
 
 _LICENSE_STRING = 'http://www.apache.org/licenses/LICENSE-2.0'
 
 
 def check_license(paths):
-  """Validate license header."""
+  """Validates license header."""
   if not paths:
     return True
 
   success = True
   for path in paths:
+    path_parts = str(path).split(os.sep)
+    if any(path_part == THIRD_PARTY_DIR_NAME for path_part in path_parts):
+      continue
     filename = os.path.basename(path)
     extension = os.path.splitext(path)[1]
     if (filename not in _CHECK_LICENSE_FILENAMES and
@@ -279,7 +297,7 @@
 
 
 def bool_to_returncode(success):
-  """Return 0 if |success|. Otherwise return 1."""
+  """Returns 0 if |success|. Otherwise returns 1."""
   if success:
     print('Success.')
     return 0
@@ -294,7 +312,7 @@
 
 
 def lint(_=None):
-  """Run python's linter on infra. Return False if it fails linting."""
+  """Runs python's linter on infra. Returns False if it fails linting."""
 
   command = ['python3', '-m', 'pylint', '-j', '0', 'infra']
   returncode = subprocess.run(command, check=False).returncode
@@ -302,9 +320,9 @@
 
 
 def yapf(paths, validate=True):
-  """Do yapf on |path| if it is Python file. Only validates format if
-  |validate| otherwise, formats the file. Returns False if validation
-  or formatting fails."""
+  """Does yapf on |path| if it is Python file. Only validates format if
+  |validate|. Otherwise, formats the file. Returns False if validation or
+  formatting fails."""
   paths = [path for path in paths if is_nonfuzzer_python(path)]
   if not paths:
     return True
@@ -318,9 +336,9 @@
 
 
 def get_changed_files():
-  """Return a list of absolute paths of files changed in this git branch."""
+  """Returns a list of absolute paths of files changed in this git branch."""
   branch_commit_hash = subprocess.check_output(
-      ['git', 'merge-base', 'FETCH_HEAD', 'origin/HEAD']).strip().decode()
+      ['git', 'merge-base', 'HEAD', 'origin/HEAD']).strip().decode()
 
   diff_commands = [
       # Return list of modified files in the commits on this branch.
@@ -354,9 +372,9 @@
 
 
 def run_nonbuild_tests(parallel):
-  """Run all tests but build tests. Do it in parallel if |parallel|. The reason
-  why we exclude build tests is because they use an emulator that prevents them
-  from being used in parallel."""
+  """Runs all tests but build tests. Does them in parallel if |parallel|. The
+  reason why we exclude build tests is because they use an emulator that
+  prevents them from being used in parallel."""
   # We look for all project directories because otherwise pytest won't run tests
   # that are not in valid modules (e.g. "base-images").
   relevant_dirs = set()
@@ -369,21 +387,34 @@
   # pass directories to pytest.
   command = [
       'pytest',
-      # Test errors with error: "ModuleNotFoundError: No module named 'apt'.
-      '--ignore-glob=infra/base-images/base-sanitizer-libs-builder/*',
       '--ignore-glob=infra/build/*',
   ]
   if parallel:
     command.extend(['-n', 'auto'])
   command += list(relevant_dirs)
   print('Running non-build tests.')
-  return subprocess.run(command, check=False).returncode == 0
+
+  # TODO(metzman): Get rid of this once config_utils stops using it.
+  env = os.environ.copy()
+  env['CIFUZZ_TEST'] = '1'
+
+  return subprocess.run(command, check=False, env=env).returncode == 0
 
 
-def run_tests(_=None, parallel=False):
+def run_tests(_=None, parallel=False, build_tests=True, nonbuild_tests=True):
   """Runs all unit tests."""
-  nonbuild_success = run_nonbuild_tests(parallel)
-  build_success = run_build_tests()
+  build_success = True
+  nonbuild_success = True
+  if nonbuild_tests:
+    nonbuild_success = run_nonbuild_tests(parallel)
+  else:
+    print('Skipping nonbuild tests as specified.')
+
+  if build_tests:
+    build_success = run_build_tests()
+  else:
+    print('Skipping build tests as specified.')
+
   return nonbuild_success and build_success
 
 
@@ -411,6 +442,17 @@
                       action='store_true',
                       help='Run tests in parallel.',
                       default=False)
+  parser.add_argument('-s',
+                      '--skip-build-tests',
+                      action='store_true',
+                      help='Skip build tests which are slow and must run '
+                      'sequentially.',
+                      default=False)
+  parser.add_argument('-n',
+                      '--skip-nonbuild-tests',
+                      action='store_true',
+                      help='Only do build tests.',
+                      default=False)
   args = parser.parse_args()
 
   if args.all_files:
@@ -434,7 +476,10 @@
     return bool_to_returncode(success)
 
   if args.command == 'infra-tests':
-    success = run_tests(relevant_files, parallel=args.parallel)
+    success = run_tests(relevant_files,
+                        parallel=args.parallel,
+                        build_tests=(not args.skip_build_tests),
+                        nonbuild_tests=(not args.skip_nonbuild_tests))
     return bool_to_returncode(success)
 
   # Do all the checks (but no tests).
diff --git a/infra/pytest.ini b/infra/pytest.ini
index d9bb373..2a10272 100644
--- a/infra/pytest.ini
+++ b/infra/pytest.ini
@@ -1,2 +1,3 @@
 [pytest]
-python_files = *_test.py
\ No newline at end of file
+python_files = *_test.py
+log_cli = true
\ No newline at end of file
diff --git a/infra/repo_manager.py b/infra/repo_manager.py
index a0b97b3..07880d8 100644
--- a/infra/repo_manager.py
+++ b/infra/repo_manager.py
@@ -135,7 +135,7 @@
              check_result=True)
     self.git(['remote', 'update'], check_result=True)
 
-  def get_commit_list(self, newest_commit, oldest_commit=None):
+  def get_commit_list(self, newest_commit, oldest_commit=None, limit=None):
     """Gets the list of commits(inclusive) between the old and new commits.
 
     Args:
@@ -162,7 +162,11 @@
     else:
       commit_range = newest_commit
 
-    out, _, err_code = self.git(['rev-list', commit_range])
+    limit_args = []
+    if limit:
+      limit_args.append(f'--max-count={limit}')
+
+    out, _, err_code = self.git(['rev-list', commit_range] + limit_args)
     commits = out.split('\n')
     commits = [commit for commit in commits if commit]
     if err_code or not commits:
diff --git a/infra/retry.py b/infra/retry.py
index 1a94180..1f6d54b 100644
--- a/infra/retry.py
+++ b/infra/retry.py
@@ -56,9 +56,9 @@
       """Handle retry."""
       if (exception is None or
           isinstance(exception, exception_type)) and num_try < tries:
-        logging.log('Retrying on %s failed with %s. Retrying again.',
-                    function_with_type,
-                    sys.exc_info()[1])
+        logging.info('Retrying on %s failed with %s. Retrying again.',
+                     function_with_type,
+                     sys.exc_info()[1])
         sleep(get_delay(num_try, delay, backoff))
         return True
 
diff --git a/infra/run_fuzzers.Dockerfile b/infra/run_fuzzers.Dockerfile
index b00bb12..8c8d7bb 100644
--- a/infra/run_fuzzers.Dockerfile
+++ b/infra/run_fuzzers.Dockerfile
@@ -13,7 +13,8 @@
 # limitations under the License.
 #
 ################################################################################
-# Docker image to run the CIFuzz action run_fuzzers in.
+# Docker image for running fuzzers on CIFuzz (the run_fuzzers action on GitHub
+# actions).
 
 FROM gcr.io/oss-fuzz-base/cifuzz-base
 
@@ -22,5 +23,9 @@
 # just expand to '/opt/oss-fuzz'.
 ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/run_fuzzers_entrypoint.py"]
 
+WORKDIR ${OSS_FUZZ_ROOT}/infra
+
 # Copy infra source code.
-ADD . ${OSS_FUZZ_ROOT}/infra
\ No newline at end of file
+ADD . ${OSS_FUZZ_ROOT}/infra
+
+RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt
diff --git a/infra/templates.py b/infra/templates.py
index f16da92..3db2914 100755
--- a/infra/templates.py
+++ b/infra/templates.py
@@ -17,7 +17,7 @@
 
 PROJECT_YAML_TEMPLATE = """\
 homepage: "<your_project_homepage>"
-language: <programming_language>  # Example values: c, c++, go, rust.
+language: %(language)s"
 primary_contact: "<primary_contact_email>"
 main_repo: "https://path/to/main/repo.git"
 """
@@ -39,13 +39,21 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/%(base_builder)s
 RUN apt-get update && apt-get install -y make autoconf automake libtool
 RUN git clone --depth 1 <git_url> %(project_name)s     # or use other version control
 WORKDIR %(project_name)s
 COPY build.sh $SRC/
 """
 
+EXTERNAL_DOCKER_TEMPLATE = """\
+FROM gcr.io/oss-fuzz-base/%(base_builder)s:v1
+RUN apt-get update && apt-get install -y make autoconf automake libtool
+RUN COPY . $SRC/%(project_name)s
+WORKDIR %(project_name)s
+COPY .clusterfuzzlite/build.sh $SRC/
+"""
+
 BUILD_TEMPLATE = """\
 #!/bin/bash -eu
 # Copyright %(year)d Google LLC
@@ -76,3 +84,30 @@
 #     /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \\
 #     $LIB_FUZZING_ENGINE /path/to/library.a
 """
+
+EXTERNAL_BUILD_TEMPLATE = """\
+#!/bin/bash -eu
+
+# build project
+# e.g.
+# ./autogen.sh
+# ./configure
+# make -j$(nproc) all
+
+# build fuzzers
+# e.g.
+# $CXX $CXXFLAGS -std=c++11 -Iinclude \\
+#     /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \\
+#     $LIB_FUZZING_ENGINE /path/to/library.a
+"""
+
+TEMPLATES = {
+    'build.sh': BUILD_TEMPLATE,
+    'Dockerfile': DOCKER_TEMPLATE,
+    'project.yaml': PROJECT_YAML_TEMPLATE
+}
+
+EXTERNAL_TEMPLATES = {
+    'build.sh': EXTERNAL_BUILD_TEMPLATE,
+    'Dockerfile': EXTERNAL_DOCKER_TEMPLATE
+}
diff --git a/infra/test_helpers.py b/infra/test_helpers.py
deleted file mode 100644
index be0b1b8..0000000
--- a/infra/test_helpers.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Contains convenient helpers for writing tests."""
-
-import contextlib
-import os
-import shutil
-import tempfile
-from unittest import mock
-
-
-def patch_environ(testcase_obj, env=None):
-  """Patch environment."""
-  if env is None:
-    env = {}
-
-  patcher = mock.patch.dict(os.environ, env)
-  testcase_obj.addCleanup(patcher.stop)
-  patcher.start()
-
-
-@contextlib.contextmanager
-def temp_dir_copy(directory):
-  """Context manager that yields a temporary copy of |directory|."""
-  with tempfile.TemporaryDirectory() as temp_dir:
-    temp_copy_path = os.path.join(temp_dir, os.path.basename(directory))
-    shutil.copytree(directory, temp_copy_path)
-    yield temp_copy_path
diff --git a/infra/test_repos.py b/infra/test_repos.py
index fb12fbe..3898768 100644
--- a/infra/test_repos.py
+++ b/infra/test_repos.py
@@ -27,7 +27,7 @@
 ExampleRepo = collections.namedtuple('ExampleRepo', [
     'project_name', 'oss_repo_name', 'git_repo_name', 'image_location',
     'git_url', 'new_commit', 'old_commit', 'intro_commit', 'fuzz_target',
-    'test_case_path'
+    'testcase_path'
 ])
 
 TEST_DIR_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)),
@@ -36,6 +36,8 @@
 # WARNING: Tests are dependent upon the following repos existing and the
 # specified commits existing.
 # TODO(metzman): Fix this problem.
+# TODO(metzman): The testcases got deleted here because the test that used them
+# was skipped. Probably worth deleting the test.
 TEST_REPOS = [
     ExampleRepo(project_name='curl',
                 oss_repo_name='curl',
@@ -46,7 +48,7 @@
                 new_commit='dda418266c99ceab368d723facb52069cbb9c8d5',
                 intro_commit='df26f5f9c36e19cd503c0e462e9f72ad37b84c82',
                 fuzz_target='curl_fuzzer_ftp',
-                test_case_path=os.path.join(TEST_DIR_PATH, 'curl_test_data')),
+                testcase_path=os.path.join(TEST_DIR_PATH, 'curl_test_data')),
     ExampleRepo(project_name='libarchive',
                 oss_repo_name='libarchive',
                 git_repo_name='libarchive',
@@ -56,8 +58,8 @@
                 new_commit='458e49358f17ec58d65ab1c45cf299baaf3c98d1',
                 intro_commit='840266712006de5e737f8052db920dfea2be4260',
                 fuzz_target='libarchive_fuzzer',
-                test_case_path=os.path.join(TEST_DIR_PATH,
-                                            'libarchive_test_data')),
+                testcase_path=os.path.join(TEST_DIR_PATH,
+                                           'libarchive_test_data')),
     ExampleRepo(project_name='gonids',
                 oss_repo_name='gonids',
                 git_repo_name='gonids',
@@ -67,7 +69,7 @@
                 new_commit='',
                 intro_commit='',
                 fuzz_target='',
-                test_case_path='')
+                testcase_path='')
 ]
 
 INVALID_REPO = ExampleRepo(project_name='notaproj',
@@ -79,4 +81,4 @@
                            new_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
                            intro_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
                            fuzz_target='NONEFUZZER',
-                           test_case_path='not/a/path')
+                           testcase_path='not/a/path')
diff --git a/infra/triage-party/README.md b/infra/triage-party/README.md
new file mode 100644
index 0000000..2ab4241
--- /dev/null
+++ b/infra/triage-party/README.md
@@ -0,0 +1,13 @@
+# triage-party
+
+This folder contains the triage party config and deploy script for the oss-fuzz instance of [triage-party](https://github.com/google/triage-party).
+
+To make changes to triage party, you'll need to:
+1. Make changes to the [config](oss-fuzz.yaml)
+1. Deploy a new revision to Cloud Run via [deploy.sh](deploy.sh):
+
+```
+GITHUB_TOKEN_PATH=[path to file containing github token] DB_PASS=[CloudSQL database password]  ./deploy.sh 
+```
+
+Visit https://triage-party-pahypmb2lq-uc.a.run.app to join the party!
diff --git a/infra/triage-party/deploy.sh b/infra/triage-party/deploy.sh
new file mode 100755
index 0000000..cabdf43
--- /dev/null
+++ b/infra/triage-party/deploy.sh
@@ -0,0 +1,42 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -eux
+
+
+export PROJECT=oss-fuzz
+export IMAGE=gcr.io/oss-fuzz-base/triage-party
+export SERVICE_NAME=triage-party
+export CONFIG_FILE=config/examples/oss-fuzz.yaml
+
+
+# Copy triage-party into tmp dir, and copy config into correct spot
+readonly clean_repo=$(mktemp -d)
+git clone --depth 1 https://github.com/google/triage-party.git "${clean_repo}"
+cp ./oss-fuzz.yaml "${clean_repo}"/${CONFIG_FILE}
+cd "${clean_repo}"
+
+
+docker build -t "${IMAGE}" --build-arg "CFG=./${CONFIG_FILE}" .
+docker push "${IMAGE}" || exit 2
+
+readonly token="$(cat "${GITHUB_TOKEN_PATH}")"
+gcloud beta run deploy "${SERVICE_NAME}" \
+    --project "${PROJECT}" \
+    --image "${IMAGE}" \
+    --set-env-vars="GITHUB_TOKEN=${token},PERSIST_BACKEND=cloudsql,PERSIST_PATH=tp:${DB_PASS}@tcp(oss-fuzz/us-central1/triage-party)/tp" \
+    --allow-unauthenticated \
+    --region us-central1 \
+    --memory 384Mi \
+    --platform managed
diff --git a/infra/triage-party/oss-fuzz.yaml b/infra/triage-party/oss-fuzz.yaml
new file mode 100644
index 0000000..107e53e
--- /dev/null
+++ b/infra/triage-party/oss-fuzz.yaml
@@ -0,0 +1,172 @@
+settings:
+  name: oss-fuzz
+  repos:
+    - https://github.com/google/oss-fuzz
+
+collections:
+  - id: Fuzzing Issues
+    name: Fuzzing Issues
+    dedup: true
+    description: >
+      Status of issues across oss-fuzz repos
+    rules:
+      # People who need a response
+      - fuzz-issue-updated-support
+      # fuzzing issues
+      - fuzz-bugs
+      - fuzz-priority
+      # Issues needing reprioritization
+      - fuzz-many-reactions
+      - fuzz-many-commenters
+      - fuzz-issue-zombies
+        # People with questions
+      - fuzz-issue-has-question
+  - id: PRs - fuzzing
+    name: OSS Fuzz PRs
+    description: >
+      Status of PRs in OSS-Fuzz
+    rules:
+      - prs-fuzz
+      - fuzz-pr-approved-stale
+      - fuzz-pr-unapproved-stale
+
+
+rules:
+  ### Pull requests
+
+  prs-fuzz:
+    name: "OSS Fuzz PRs"
+    type: pull_request
+    resolution: "Review requests or mark them as do-not-merge/work-in-progress"
+    filters:
+      - title: "!.*(WIP|wip).*"
+      - tag: "!(changes-requested|draft|approved)"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  # PR's needing closure
+  fuzz-pr-approved-stale:
+    name: "Pull requests: Approved and getting old"
+    resolution: "Merge PR"
+    type: pull_request
+    filters:
+      - label: "approved"
+      - updated: +2d
+      - responded: +1d
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  fuzz-pr-unapproved-stale:
+    name: "Pull Requests: Stale"
+    resolution: "Add comment and/or close PR"
+    type: pull_request
+    filters:
+      - created: +3d
+      - updated: +2d
+      - responded: +1d
+      - tag: "!draft"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  pr-approved-stale:
+    name: "Pull requests: Approved and getting old"
+    resolution: "Merge PR"
+    type: pull_request
+    filters:
+      - label: "approved"
+      - updated: +5d
+      - responded: +2d
+
+  pr-unapproved-stale:
+    name: "Pull Requests: Stale"
+    type: pull_request
+    resolution: "Add comment and/or close PR"
+    filters:
+      - created: +20d
+      - updated: +5d
+      - responded: +2d
+
+  
+  ### Fuzzing Issues
+
+  fuzz-bugs:
+    name: "Fuzzing bugs that have not been commented on for 6 months"
+    resolution: "comment a status update"
+    type: issue
+    filters:
+      - label: "bug"
+      - responded: +180d
+      - tag: "!member-last"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+
+  fuzz-priority:
+    name: "Fuzzing priority issues that have not been commented on for 6 months"
+    resolution: "comment a status update"
+    type: issue
+    filters:
+      - label: "priority"
+      - responded: +180d
+      - tag: "!member-last"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+
+  fuzz-many-reactions:
+    name: "many reactions, low priority"
+    resolution: "Upgrade to priority"
+    filters:
+      - reactions: ">3"
+      - reactions-per-month: ">0.75"
+      - label: "!priority"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  fuzz-many-commenters:
+    name: "many commenters, low priority"
+    resolution: "Upgrade to priority"
+    filters:
+      - commenters: ">2"
+      - commenters-per-month: ">1.9"
+      - created: "+30d"
+      - label: "!priority"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  fuzz-issue-zombies:
+    name: "Screaming into the void"
+    resolution: "Reopen, or ask folks to open a new issue"
+    type: issue
+    filters:
+      - state: closed
+      - updated: -7d
+      - tag: recv
+      - comments-while-closed: ">1"
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  # People with questions
+  fuzz-issue-has-question:
+    name: "Overdue answers for a question"
+    resolution: "Add a comment"
+    type: issue
+    filters:
+      - tag: recv-q
+      - tag: "!member-last"
+      - tag: "!contributor-last"
+      - responded: +6d
+    repos:
+      - https://github.com/google/oss-fuzz
+
+  fuzz-issue-updated-support:
+    name: "Open support requests"
+    resolution: "Add a comment"
+    type: issue
+    filters:
+      - tag: recv
+      - tag: "!member-last"
+      - tag: "!contributor-last"
+      - responded: +6d
+    repos:
+      - https://github.com/google/oss-fuzz
diff --git a/infra/utils.py b/infra/utils.py
index fe5dd87..f0b58a4 100644
--- a/infra/utils.py
+++ b/infra/utils.py
@@ -17,6 +17,7 @@
 import os
 import posixpath
 import re
+import shlex
 import stat
 import subprocess
 import sys
@@ -25,7 +26,8 @@
 
 ALLOWED_FUZZ_TARGET_EXTENSIONS = ['', '.exe']
 FUZZ_TARGET_SEARCH_STRING = 'LLVMFuzzerTestOneInput'
-VALID_TARGET_NAME = re.compile(r'^[a-zA-Z0-9_-]+$')
+VALID_TARGET_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_-]+$')
+BLOCKLISTED_TARGET_NAME_REGEX = re.compile(r'^(jazzer_driver.*)$')
 
 # Location of google cloud storage for latest OSS-Fuzz builds.
 GCS_BASE_URL = 'https://storage.googleapis.com/'
@@ -38,16 +40,25 @@
     os.chdir(helper.OSS_FUZZ_DIR)
 
 
-def execute(command, location=None, check_result=False):
-  """ Runs a shell command in the specified directory location.
+def command_to_string(command):
+  """Returns the stringfied version of |command| a list representing a binary to
+  run and arguments to pass to it or a string representing a binary to run."""
+  if isinstance(command, str):
+    return command
+  return shlex.join(command)
+
+
+def execute(command, env=None, location=None, check_result=False):
+  """Runs a shell command in the specified directory location.
 
   Args:
     command: The command as a list to be run.
-    location: The directory the command is run in.
-    check_result: Should an exception be thrown on failed command.
+    env: (optional) an environment to pass to Popen to run the command in.
+    location (optional): The directory to run command in.
+    check_result (optional): Should an exception be thrown on failure.
 
   Returns:
-    stdout, stderr, error code.
+    stdout, stderr, returncode.
 
   Raises:
     RuntimeError: running a command resulted in an error.
@@ -58,24 +69,27 @@
   process = subprocess.Popen(command,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
-                             cwd=location)
+                             cwd=location,
+                             env=env)
   out, err = process.communicate()
   out = out.decode('utf-8', errors='ignore')
   err = err.decode('utf-8', errors='ignore')
+
+  command_str = command_to_string(command)
   if err:
-    logging.debug('Stderr of command \'%s\' is %s.', ' '.join(command), err)
+    logging.debug('Stderr of command "%s" is: %s.', command_str, err)
   if check_result and process.returncode:
-    raise RuntimeError(
-        'Executing command \'{0}\' failed with error: {1}.'.format(
-            ' '.join(command), err))
+    raise RuntimeError('Executing command "{0}" failed with error: {1}.'.format(
+        command_str, err))
   return out, err, process.returncode
 
 
-def get_fuzz_targets(path):
-  """Get list of fuzz targets in a directory.
+def get_fuzz_targets(path, top_level_only=False):
+  """Gets fuzz targets in a directory.
 
   Args:
     path: A path to search for fuzz targets in.
+    top_level_only: If True, only search |path|, do not recurse into subdirs.
 
   Returns:
     A list of paths to fuzzers or an empty list if None.
@@ -84,6 +98,9 @@
     return []
   fuzz_target_paths = []
   for root, _, fuzzers in os.walk(path):
+    if top_level_only and path != root:
+      continue
+
     for fuzzer in fuzzers:
       file_path = os.path.join(root, fuzzer)
       if is_fuzz_target_local(file_path):
@@ -112,11 +129,17 @@
   Copied from clusterfuzz src/python/bot/fuzzers/utils.py
   with slight modifications.
   """
+  # pylint: disable=too-many-return-statements
   filename, file_extension = os.path.splitext(os.path.basename(file_path))
-  if not VALID_TARGET_NAME.match(filename):
+  if not VALID_TARGET_NAME_REGEX.match(filename):
     # Check fuzz target has a valid name (without any special chars).
     return False
 
+  if BLOCKLISTED_TARGET_NAME_REGEX.match(filename):
+    # Check fuzz target an explicitly disallowed name (e.g. binaries used for
+    # jazzer-based targets).
+    return False
+
   if file_extension not in ALLOWED_FUZZ_TARGET_EXTENSIONS:
     # Ignore files with disallowed extensions (to prevent opening e.g. .zips).
     return False
@@ -135,7 +158,7 @@
 
 
 def binary_print(string):
-  """Print that can print a binary string."""
+  """Prints string. Can print a binary string."""
   if isinstance(string, bytes):
     string += b'\n'
   else:
diff --git a/infra/utils_test.py b/infra/utils_test.py
index aa6ec7b..9b7fbc9 100644
--- a/infra/utils_test.py
+++ b/infra/utils_test.py
@@ -24,7 +24,7 @@
 EXAMPLE_PROJECT = 'example'
 
 TEST_OUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
-                            'cifuzz', 'test_data', 'out')
+                            'cifuzz', 'test_data', 'build-out')
 
 
 class IsFuzzTargetLocalTest(unittest.TestCase):
@@ -118,17 +118,33 @@
   def test_string(self):  # pylint: disable=no-self-use
     """Tests that utils.binary_print can print a regular string."""
     # Should execute without raising any exceptions.
-    with mock.patch('sys.stdout.buffer.write') as mocked_write:
+    with mock.patch('sys.stdout.buffer.write') as mock_write:
       utils.binary_print('hello')
-      mocked_write.assert_called_with('hello\n')
+      mock_write.assert_called_with('hello\n')
 
   @unittest.skip('Causes spurious failures because of side-effects.')
   def test_binary_string(self):  # pylint: disable=no-self-use
     """Tests that utils.binary_print can print a bianry string."""
     # Should execute without raising any exceptions.
-    with mock.patch('sys.stdout.buffer.write') as mocked_write:
+    with mock.patch('sys.stdout.buffer.write') as mock_write:
       utils.binary_print(b'hello')
-      mocked_write.assert_called_with(b'hello\n')
+      mock_write.assert_called_with(b'hello\n')
+
+
+class CommandToStringTest(unittest.TestCase):
+  """Tests for command_to_string."""
+
+  def test_string(self):
+    """Tests that command_to_string returns the argument passed to it when it is
+    passed a string."""
+    command = 'command'
+    self.assertEqual(utils.command_to_string(command), command)
+
+  def test_list(self):
+    """Tests that command_to_string returns the correct stringwhen it is passed
+    a list."""
+    command = ['command', 'arg1', 'arg2']
+    self.assertEqual(utils.command_to_string(command), 'command arg1 arg2')
 
 
 if __name__ == '__main__':
diff --git a/projects/apache-commons/CompressSevenZFuzzer.java b/projects/apache-commons/CompressSevenZFuzzer.java
new file mode 100644
index 0000000..8bc1932
--- /dev/null
+++ b/projects/apache-commons/CompressSevenZFuzzer.java
@@ -0,0 +1,39 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import org.apache.commons.compress.archivers.sevenz.SevenZFile;
+import org.apache.commons.compress.archivers.sevenz.SevenZFileOptions;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+
+import java.io.IOException;
+import java.util.logging.LogManager;
+
+public class CompressSevenZFuzzer {
+    private static final SevenZFileOptions options = new SevenZFileOptions.Builder()
+        .withMaxMemoryLimitInKb(1_000_000)
+        .build();
+
+    public static void fuzzerInitialize() {
+        LogManager.getLogManager().reset();
+    }
+
+    public static void fuzzerTestOneInput(byte[] data) {
+        try {
+            new SevenZFile(new SeekableInMemoryByteChannel(data), options).close();
+        } catch (IOException ignored) {
+        }
+    }
+}
diff --git a/projects/apache-commons/CompressTarFuzzer.java b/projects/apache-commons/CompressTarFuzzer.java
new file mode 100644
index 0000000..2df863d
--- /dev/null
+++ b/projects/apache-commons/CompressTarFuzzer.java
@@ -0,0 +1,33 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import org.apache.commons.compress.archivers.tar.TarFile;
+
+import java.io.IOException;
+import java.util.logging.LogManager;
+
+public class CompressTarFuzzer {
+    public static void fuzzerInitialize() {
+        LogManager.getLogManager().reset();
+    }
+
+    public static void fuzzerTestOneInput(byte[] data) {
+        try {
+            new TarFile(data).close();
+        } catch (IOException ignored) {
+        }
+    }
+}
diff --git a/projects/apache-commons/CompressZipFuzzer.java b/projects/apache-commons/CompressZipFuzzer.java
new file mode 100644
index 0000000..bc9a8a0
--- /dev/null
+++ b/projects/apache-commons/CompressZipFuzzer.java
@@ -0,0 +1,34 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+
+import java.io.IOException;
+import java.util.logging.LogManager;
+
+public class CompressZipFuzzer {
+    public static void fuzzerInitialize() {
+        LogManager.getLogManager().reset();
+    }
+
+    public static void fuzzerTestOneInput(byte[] data) {
+        try {
+            new ZipFile(new SeekableInMemoryByteChannel(data)).close();
+        } catch (IOException ignored) {
+        }
+    }
+}
diff --git a/projects/apache-commons/Dockerfile b/projects/apache-commons/Dockerfile
new file mode 100644
index 0000000..55b460c
--- /dev/null
+++ b/projects/apache-commons/Dockerfile
@@ -0,0 +1,61 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+    unzip maven.zip -d $SRC/maven && \
+    rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+# Dictionaries
+RUN git clone --depth 1 https://github.com/google/fuzzing && \
+    mv fuzzing/dictionaries/zip.dict $SRC/CompressZipFuzzer.dict && \
+    mv fuzzing/dictionaries/gif.dict $SRC/ImagingGifFuzzer.dict && \
+    mv fuzzing/dictionaries/jpeg.dict $SRC/ImagingJpegFuzzer.dict && \
+    mv fuzzing/dictionaries/png.dict $SRC/ImagingPngFuzzer.dict && \
+    mv fuzzing/dictionaries/tiff.dict $SRC/ImagingTiffFuzzer.dict && \
+    rm -rf fuzzing
+
+# Seed corpus (go-fuzz-corpus)
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \
+    zip -j $SRC/CompressTarFuzzer_seed_corpus.zip go-fuzz-corpus/tar/corpus/* && \
+    zip -j $SRC/CompressZipFuzzer_seed_corpus.zip go-fuzz-corpus/zip/corpus/* && \
+    zip -j $SRC/ImagingBmpFuzzer_seed_corpus.zip go-fuzz-corpus/bmp/corpus/* && \
+    zip -j $SRC/ImagingGifFuzzer_seed_corpus.zip go-fuzz-corpus/gif/corpus/* && \
+    zip -j $SRC/ImagingJpegFuzzer_seed_corpus.zip go-fuzz-corpus/jpeg/corpus/* && \
+    zip -j $SRC/ImagingPngFuzzer_seed_corpus.zip go-fuzz-corpus/png/corpus/* && \
+    zip -j $SRC/ImagingTiffFuzzer_seed_corpus.zip go-fuzz-corpus/tiff/corpus/* && \
+    rm -rf go-fuzz-corpus
+
+# Compress
+RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-compress.git
+
+RUN zip -uj $SRC/CompressTarFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.tar && \
+    zip -uj $SRC/CompressZipFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.zip && \
+    zip -j $SRC/CompressSevenZFuzzer_seed_corpus.zip commons-compress/src/test/resources/bla.7z
+
+# Imaging
+RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-imaging.git
+
+# Geometry
+RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-geometry.git
+
+# Copy build script and all fuzzers
+COPY build.sh $SRC/
+COPY *Fuzzer.java $SRC/
+WORKDIR $SRC/
diff --git a/projects/apache-commons/GeometryObjFuzzer.java b/projects/apache-commons/GeometryObjFuzzer.java
new file mode 100644
index 0000000..6b8900f
--- /dev/null
+++ b/projects/apache-commons/GeometryObjFuzzer.java
@@ -0,0 +1,40 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.ByteArrayInputStream;
+import java.io.UncheckedIOException;
+
+import org.apache.commons.geometry.io.core.input.StreamGeometryInput;
+import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D;
+import org.apache.commons.geometry.io.euclidean.threed.obj.ObjBoundaryReadHandler3D;
+import org.apache.commons.numbers.core.Precision;
+
+public class GeometryObjFuzzer {
+    public static void fuzzerTestOneInput(final byte[] data) {
+        try {
+            final BoundaryReadHandler3D handler = new ObjBoundaryReadHandler3D();
+            final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20);
+
+            // check standard read
+            handler.read(new StreamGeometryInput(new ByteArrayInputStream(data)), precision);
+
+            // check mesh read
+            handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(data)), precision);
+        } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) {
+            // expected exception types; ignore
+        }
+    }
+}
diff --git a/projects/apache-commons/GeometryStlBinaryFuzzer.java b/projects/apache-commons/GeometryStlBinaryFuzzer.java
new file mode 100644
index 0000000..3df1547
--- /dev/null
+++ b/projects/apache-commons/GeometryStlBinaryFuzzer.java
@@ -0,0 +1,40 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.ByteArrayInputStream;
+import java.io.UncheckedIOException;
+
+import org.apache.commons.geometry.io.core.input.StreamGeometryInput;
+import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D;
+import org.apache.commons.geometry.io.euclidean.threed.stl.StlBoundaryReadHandler3D;
+import org.apache.commons.numbers.core.Precision;
+
+public class GeometryStlBinaryFuzzer {
+    public static void fuzzerTestOneInput(final byte[] data) {
+        try {
+            final BoundaryReadHandler3D handler = new StlBoundaryReadHandler3D();
+            final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20);
+
+            // check standard read
+            handler.read(new StreamGeometryInput(new ByteArrayInputStream(data)), precision);
+
+            // check mesh read
+            handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(data)), precision);
+        } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) {
+            // expected exception types; ignore
+        }
+    }
+}
diff --git a/projects/apache-commons/GeometryStlTextFuzzer.java b/projects/apache-commons/GeometryStlTextFuzzer.java
new file mode 100644
index 0000000..5bddb17
--- /dev/null
+++ b/projects/apache-commons/GeometryStlTextFuzzer.java
@@ -0,0 +1,55 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.nio.charset.StandardCharsets;
+
+import java.io.ByteArrayInputStream;
+import java.io.UncheckedIOException;
+
+import org.apache.commons.geometry.io.core.input.StreamGeometryInput;
+import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D;
+import org.apache.commons.geometry.io.euclidean.threed.stl.StlBoundaryReadHandler3D;
+import org.apache.commons.numbers.core.Precision;
+
+public class GeometryStlTextFuzzer {
+    public static void fuzzerTestOneInput(final byte[] data) {
+        // prepend the "solid" STL keyword to the input to ensure it is interpreted
+        // as text STL input
+        final byte[] dataWithPrefix = join("solid ".getBytes(StandardCharsets.US_ASCII), data);
+
+        try {
+            final BoundaryReadHandler3D handler = new StlBoundaryReadHandler3D();
+
+            final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20);
+
+            // check standard read
+            handler.read(new StreamGeometryInput(new ByteArrayInputStream(dataWithPrefix)), precision);
+
+            // check mesh read
+            handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(dataWithPrefix)), precision);
+        } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) {
+            // expected exception types; ignore
+        }
+    }
+
+    private static byte[] join(final byte[] a, final byte[] b) {
+        final byte[] result = new byte[a.length + b.length];
+        System.arraycopy(a, 0, result, 0, a.length);
+        System.arraycopy(b, 0, result, a.length, b.length);
+
+        return result;
+    }
+}
diff --git a/projects/apache-commons/GeometryTextFuzzer.java b/projects/apache-commons/GeometryTextFuzzer.java
new file mode 100644
index 0000000..ab318f2
--- /dev/null
+++ b/projects/apache-commons/GeometryTextFuzzer.java
@@ -0,0 +1,41 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.ByteArrayInputStream;
+import java.io.UncheckedIOException;
+
+import org.apache.commons.geometry.io.core.input.StreamGeometryInput;
+import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D;
+import org.apache.commons.geometry.io.euclidean.threed.txt.TextBoundaryReadHandler3D;
+import org.apache.commons.numbers.core.Precision;
+
+public class GeometryTextFuzzer {
+    public static void fuzzerTestOneInput(final byte[] data) {
+        try {
+            final BoundaryReadHandler3D handler = new TextBoundaryReadHandler3D();
+
+            final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20);
+
+            // check standard read
+            handler.read(new StreamGeometryInput(new ByteArrayInputStream(data)), precision);
+
+            // check mesh read
+            handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(data)), precision);
+        } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) {
+            // expected exception types; ignore
+        }
+    }
+}
diff --git a/projects/apache-commons/ImagingBmpFuzzer.java b/projects/apache-commons/ImagingBmpFuzzer.java
new file mode 100644
index 0000000..c907170
--- /dev/null
+++ b/projects/apache-commons/ImagingBmpFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.bmp.BmpImageParser;
+
+public class ImagingBmpFuzzer {
+  public static void fuzzerTestOneInput(byte[] input) {
+    try {
+      new BmpImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+    } catch (IOException | ImageReadException ignored) {
+    }
+  }
+}
diff --git a/projects/apache-commons/ImagingGifFuzzer.java b/projects/apache-commons/ImagingGifFuzzer.java
new file mode 100644
index 0000000..6c59cf4
--- /dev/null
+++ b/projects/apache-commons/ImagingGifFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.gif.GifImageParser;
+
+public class ImagingGifFuzzer {
+  public static void fuzzerTestOneInput(byte[] input) {
+    try {
+      new GifImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+    } catch (IOException | ImageReadException ignored) {
+    }
+  }
+}
diff --git a/projects/apache-commons/ImagingJpegFuzzer.java b/projects/apache-commons/ImagingJpegFuzzer.java
new file mode 100644
index 0000000..a40004e
--- /dev/null
+++ b/projects/apache-commons/ImagingJpegFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.jpeg.JpegImageParser;
+
+public class ImagingJpegFuzzer {
+  public static void fuzzerTestOneInput(byte[] input) {
+    try {
+      new JpegImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+    } catch (IOException | ImageReadException ignored) {
+    }
+  }
+}
diff --git a/projects/apache-commons/ImagingPngFuzzer.java b/projects/apache-commons/ImagingPngFuzzer.java
new file mode 100644
index 0000000..406480d
--- /dev/null
+++ b/projects/apache-commons/ImagingPngFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.png.PngImageParser;
+
+public class ImagingPngFuzzer {
+  public static void fuzzerTestOneInput(byte[] input) {
+    try {
+      new PngImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+    } catch (IOException | ImageReadException ignored) {
+    }
+  }
+}
diff --git a/projects/apache-commons/ImagingTiffFuzzer.java b/projects/apache-commons/ImagingTiffFuzzer.java
new file mode 100644
index 0000000..6833751
--- /dev/null
+++ b/projects/apache-commons/ImagingTiffFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.tiff.TiffImageParser;
+
+public class ImagingTiffFuzzer {
+  public static void fuzzerTestOneInput(byte[] input) {
+    try {
+      new TiffImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+    } catch (IOException | ImageReadException ignored) {
+    }
+  }
+}
diff --git a/projects/apache-commons/build.sh b/projects/apache-commons/build.sh
new file mode 100755
index 0000000..6716afd
--- /dev/null
+++ b/projects/apache-commons/build.sh
@@ -0,0 +1,66 @@
+#!/bin/bash -eu
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Move seed corpus and dictionary.
+mv $SRC/{*.zip,*.dict} $OUT
+
+PROJECTS="compress imaging geometry"
+GEOMETRY_MODULE="commons-geometry-io-euclidean"
+
+for project in $PROJECTS; do
+  cd $SRC/commons-$project
+  MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 -Djdk.version=15"
+  CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+  -Dexpression=project.version -q -DforceStdout)
+
+  if [ $project = 'geometry' ]; then
+    # commons-geometry is a multi-module project and requires special handling in order
+    # to build and extract the proper module (commons-geometry-io-euclidean)
+    $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -am -pl $GEOMETRY_MODULE $MAVEN_ARGS
+    cp "$GEOMETRY_MODULE/target/$GEOMETRY_MODULE-$CURRENT_VERSION.jar" $OUT/commons-$project.jar
+  else
+    $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS
+    cp "target/commons-$project-$CURRENT_VERSION.jar" $OUT/commons-$project.jar
+  fi
+
+  ALL_JARS="commons-$project.jar"
+
+  # The classpath at build-time includes the project jars in $OUT as well as the
+  # Jazzer API.
+  BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
+
+  # All .jar and .class files lie in the same directory as the fuzzer at runtime.
+  RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
+
+  for fuzzer in $(find $SRC -iname "$project"'*Fuzzer.java'); do
+    fuzzer_basename=$(basename -s .java $fuzzer)
+    javac -cp $BUILD_CLASSPATH $fuzzer
+    cp $SRC/$fuzzer_basename.class $OUT/
+
+    # Create an execution wrapper that executes Jazzer with the correct arguments.
+    echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m;-Djava.awt.headless=true\" \
+\$@" > $OUT/$fuzzer_basename
+    chmod +x $OUT/$fuzzer_basename
+  done
+done
diff --git a/projects/apache-commons/project.yaml b/projects/apache-commons/project.yaml
new file mode 100644
index 0000000..8d7aa5a
--- /dev/null
+++ b/projects/apache-commons/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://commons.apache.org"
+language: jvm
+primary_contact: "boards@gmail.com"
+auto_ccs:
+  - "fuzz-testing@commons.apache.org"
+  - "brunodepaulak@gmail.com"
+  - "meumertzheim@code-intelligence.com"
+  - "peteralfredlee@gmail.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://gitbox.apache.org/repos/asf/commons-compress.git"
+sanitizers:
+  - address
diff --git a/projects/apache-httpd/Dockerfile b/projects/apache-httpd/Dockerfile
new file mode 100644
index 0000000..39b419e
--- /dev/null
+++ b/projects/apache-httpd/Dockerfile
@@ -0,0 +1,34 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool wget libpcre3 \
+                                         libpcre3-dev uuid-dev pkg-config libtool-bin
+
+RUN git clone https://github.com/AdaLogics/fuzz-headers
+
+RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-2.4.1.tar.gz && \
+    tar -xf expat-2.4.1.tar.gz && \
+    cd expat-2.4.1 && \
+    ./configure && \
+    make && \
+    make install
+
+RUN git clone --depth=1 https://github.com/apache/httpd
+WORKDIR httpd
+COPY build.sh $SRC/
+COPY fuzz_*.c $SRC/
+COPY patches.diff $SRC/
diff --git a/projects/apache-httpd/build.sh b/projects/apache-httpd/build.sh
new file mode 100755
index 0000000..59cf786
--- /dev/null
+++ b/projects/apache-httpd/build.sh
@@ -0,0 +1,45 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+unset CPP
+unset CXX
+
+git apply  --ignore-space-change --ignore-whitespace $SRC/patches.diff
+
+# Download apr and place in httpd srclib folder. Apr-2.0 includes apr-utils
+svn checkout https://svn.apache.org/repos/asf/apr/apr/trunk/ srclib/apr
+
+# Build httpd
+./buildconf
+./configure --with-included-apr --enable-pool-debug
+make
+
+# Build the fuzzers
+for fuzzname in utils parse tokenize addr_parse uri request preq; do
+  $CC $CFLAGS $LIB_FUZZING_ENGINE \
+    -I$SRC/fuzz-headers/lang/c -I./include -I./os/unix \
+    -I./srclib/apr/include -I./srclib/apr-util/include/ \
+    $SRC/fuzz_${fuzzname}.c -o $OUT/fuzz_${fuzzname} \
+    ./modules.o buildmark.o \
+    -Wl,--start-group ./server/.libs/libmain.a \
+                      ./modules/core/.libs/libmod_so.a \
+                      ./modules/http/.libs/libmod_http.a \
+                      ./server/mpm/event/.libs/libevent.a \
+                      ./os/unix/.libs/libos.a \
+                      ./srclib/apr/.libs/libapr-2.a \
+    -Wl,--end-group -luuid -lpcre -lcrypt -lexpat
+done
diff --git a/projects/apache-httpd/fuzz_addr_parse.c b/projects/apache-httpd/fuzz_addr_parse.c
new file mode 100644
index 0000000..3fc00ab
--- /dev/null
+++ b/projects/apache-httpd/fuzz_addr_parse.c
@@ -0,0 +1,37 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "apr_network_io.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  apr_pool_t *pool;
+  apr_pool_initialize();
+  if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+    abort();
+  }
+
+  char *addr = NULL;
+  char *scope_id = NULL;
+  apr_port_t port = 0;
+  char *input_string = strndup((const char *)data, size);
+
+  apr_parse_addr_port(&addr, &scope_id, &port, input_string, pool);
+
+  free(input_string);
+  apr_pool_destroy(pool);
+  apr_terminate();
+
+  return 0;
+}
diff --git a/projects/apache-httpd/fuzz_parse.c b/projects/apache-httpd/fuzz_parse.c
new file mode 100644
index 0000000..fb87db5
--- /dev/null
+++ b/projects/apache-httpd/fuzz_parse.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_poll.h"
+#include "apr_portable.h"
+#include "apr_proc_mutex.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_proc.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_file_io.h"
+#include "apr_fnmatch.h"
+#include "apr_want.h"
+
+#include "apr_poll.h"
+#include "apr_want.h"
+
+#include "ap_config.h"
+#include "ap_expr.h"
+#include "ap_listen.h"
+#include "ap_provider.h"
+#include "ap_regex.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  char *new_str = (char *)malloc(size + 1);
+  if (new_str == NULL) {
+    return 0;
+  }
+  memcpy(new_str, data, size);
+  new_str[size] = '\0';
+
+  apr_pool_initialize();
+  apr_pool_t *v = NULL;
+  apr_pool_create(&v, NULL);
+
+  int only_ascii = 1;
+  for (int i = 0; i < size; i++) {
+    // Avoid unnessary exits because of non-ascii characters.
+    if (new_str[i] < 0x01 || new_str[i] > 0x7f) {
+      only_ascii = 0;
+    }
+    // Avoid forced exits beause of, e.g. unsupported characters or recursion
+    // depth
+    if (new_str[i] == 0x5c || new_str[i] == '{') {
+      only_ascii = 0;
+    }
+  }
+
+  // Now parse
+  if (only_ascii) {
+    ap_expr_info_t val;
+    ap_expr_parse(v, v, &val, new_str, NULL);
+  }
+
+  apr_pool_terminate();
+  free(new_str);
+  return 0;
+}
diff --git a/projects/apache-httpd/fuzz_preq.c b/projects/apache-httpd/fuzz_preq.c
new file mode 100644
index 0000000..2d8d921
--- /dev/null
+++ b/projects/apache-httpd/fuzz_preq.c
@@ -0,0 +1,84 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_poll.h"
+#include "apr_portable.h"
+#include "apr_proc_mutex.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_proc.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_file_io.h"
+#include "apr_fnmatch.h"
+#include "apr_want.h"
+
+#include "apr_poll.h"
+#include "apr_want.h"
+
+#include "ap_config.h"
+#include "ap_expr.h"
+#include "ap_listen.h"
+#include "ap_provider.h"
+#include "ap_regex.h"
+
+#include "ada_fuzz_header.h"
+#include "apreq_parser.h"
+
+apr_status_t hookfunc(apreq_hook_t *hook, apreq_param_t *param,
+                      apr_bucket_brigade *bb) {
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  af_gb_init();
+
+  const uint8_t *data2 = data;
+  size_t size2 = size;
+
+  /* get random data for the fuzzer */
+  char *new_str = af_gb_get_null_terminated(&data2, &size2);
+  char *new_str2 = af_gb_get_null_terminated(&data2, &size2);
+
+  if (new_str != NULL && new_str2 != NULL) {
+    apr_pool_initialize();
+    apr_pool_t *v = NULL;
+    apr_pool_create(&v, NULL);
+
+    apr_bucket_alloc_t *bucket = apr_bucket_alloc_create(v);
+    apr_bucket_brigade *brigade = apr_brigade_create(v, bucket);
+    apr_brigade_write(brigade, NULL, NULL, new_str, strlen(new_str));
+
+    apreq_parser_t parser;
+    parser.content_type = new_str2;
+    parser.temp_dir = "/tmp/";
+    parser.brigade_limit = 10;
+    parser.pool = v;
+    parser.ctx = NULL;
+    parser.bucket_alloc = bucket;
+
+    parser.hook = apreq_hook_make(parser.pool, hookfunc, NULL, parser.ctx);
+
+    apr_table_t *table = apr_table_make(parser.pool, 10);
+    if (af_get_short(&data2, &size2) % 2 == 0) {
+      apreq_parse_multipart(&parser, table, brigade);
+    } else {
+      apreq_parse_urlencoded(&parser, table, brigade);
+    }
+
+    apr_pool_terminate();
+  }
+  af_gb_cleanup();
+  return 0;
+}
diff --git a/projects/apache-httpd/fuzz_request.c b/projects/apache-httpd/fuzz_request.c
new file mode 100644
index 0000000..05a42c6
--- /dev/null
+++ b/projects/apache-httpd/fuzz_request.c
@@ -0,0 +1,138 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_poll.h"
+#include "apr_portable.h"
+#include "apr_proc_mutex.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_proc.h"
+#include "http_core.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_file_io.h"
+#include "apr_fnmatch.h"
+#include "apr_want.h"
+
+#include "apr_poll.h"
+#include "apr_want.h"
+
+#include "ap_config.h"
+#include "ap_expr.h"
+#include "ap_listen.h"
+#include "ap_provider.h"
+#include "ap_regex.h"
+
+#include "ada_fuzz_header.h"
+
+static const char *http_scheme2(const request_rec *r) {
+  /*
+   * The http module shouldn't return anything other than
+   * "http" (the default) or "https".
+   */
+  if (r->server->server_scheme &&
+      (strcmp(r->server->server_scheme, "https") == 0))
+    return "https";
+
+  return "http";
+}
+
+extern request_rec *ap_create_request(conn_rec *conn);
+extern int read_request_line(request_rec *r, apr_bucket_brigade *bb);
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  apr_pool_create(&apr_hook_global_pool, NULL);
+  ap_open_stderr_log(apr_hook_global_pool);
+  ap_hook_http_scheme(http_scheme2, NULL, NULL, APR_HOOK_REALLY_LAST);
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  af_gb_init();
+
+  const uint8_t *data2 = data;
+  size_t size2 = size;
+
+  /* get random data for the fuzzer */
+  char *new_str = af_gb_get_null_terminated(&data2, &size2);
+  char *new_str2 = af_gb_get_null_terminated(&data2, &size2);
+  char *new_str3 = af_gb_get_null_terminated(&data2, &size2);
+  char *new_str4 = af_gb_get_null_terminated(&data2, &size2);
+  char *new_str5 = af_gb_get_null_terminated(&data2, &size2);
+  if (new_str != NULL && 
+      new_str2 != NULL && 
+      new_str3 != NULL &&
+      new_str4 != NULL && 
+      new_str5 != NULL) {
+
+    /* this is the main fuzzing logic */
+
+    apr_pool_initialize();
+    apr_pool_t *v = NULL;
+    apr_pool_create(&v, NULL);
+
+    conn_rec conn;
+    conn.pool = v;
+    server_rec base_server;
+    conn.base_server = &base_server;
+    conn.bucket_alloc = apr_bucket_alloc_create(conn.pool);
+    ap_method_registry_init(conn.pool);
+
+    //server_rec server;
+
+    /* Simulate ap_read_request */
+    request_rec *r = NULL;
+    r = ap_create_request(&conn);
+
+    /* create a logs array for the request */
+    struct ap_logconf logs = {};
+    char *log_levels = calloc(1000, 1);
+    memset(log_levels, 0, 1000);
+    logs.module_levels = log_levels;
+    r->log = &logs;
+    if (r != NULL) {
+      apr_bucket_brigade *tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+      conn.keepalive = AP_CONN_UNKNOWN;
+
+      ap_run_pre_read_request(r, conn);
+
+      core_server_config conf_mod;
+      conf_mod.http_conformance   = (char)af_get_short(&data2, &size2);
+      conf_mod.http09_enable      = (char)af_get_short(&data2, &size2);
+      conf_mod.http_methods       = (char)af_get_short(&data2, &size2);
+      void **module_config_arr = malloc(1000);
+      module_config_arr[0] = &conf_mod;
+
+      r->server->module_config = module_config_arr;
+      ap_set_core_module_config(r->server->module_config, &conf_mod);
+
+      /* randomise content of request */
+      r->unparsed_uri           = new_str;
+      r->uri                    = new_str2;
+      r->server->server_scheme  = new_str3;
+      r->method                 = new_str4;
+      r->the_request            = new_str5;
+
+      /* main target */
+      ap_parse_request_line(r);
+
+      free(module_config_arr);
+    }
+    free(log_levels);
+    apr_pool_terminate();
+  }
+
+  af_gb_cleanup();
+  return 0;
+}
diff --git a/projects/apache-httpd/fuzz_tokenize.c b/projects/apache-httpd/fuzz_tokenize.c
new file mode 100644
index 0000000..1de6295
--- /dev/null
+++ b/projects/apache-httpd/fuzz_tokenize.c
@@ -0,0 +1,34 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "apr_strings.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  apr_pool_t *pool;
+  apr_pool_initialize();
+  if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+    abort();
+  }
+
+  char *arg_str = strndup((const char *)data, size);
+  char **argv_out;
+  apr_tokenize_to_argv(arg_str, &argv_out, pool);
+
+  free(arg_str);
+  apr_pool_destroy(pool);
+  apr_terminate();
+
+  return 0;
+}
diff --git a/projects/apache-httpd/fuzz_uri.c b/projects/apache-httpd/fuzz_uri.c
new file mode 100644
index 0000000..789b96f
--- /dev/null
+++ b/projects/apache-httpd/fuzz_uri.c
@@ -0,0 +1,65 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_poll.h"
+#include "apr_portable.h"
+#include "apr_proc_mutex.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_proc.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_file_io.h"
+#include "apr_fnmatch.h"
+#include "apr_want.h"
+
+#include "apr_poll.h"
+#include "apr_want.h"
+
+#include "apr_uri.h"
+
+#include "ap_config.h"
+#include "ap_expr.h"
+#include "ap_listen.h"
+#include "ap_provider.h"
+#include "ap_regex.h"
+
+#include "ada_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  af_gb_init();
+  const uint8_t *data2 = data;
+  size_t size2 = size;
+
+  // Get a NULL terminated string
+  char *cstr = af_gb_get_null_terminated(&data2, &size2);
+
+  // Fuzz URI routines
+  if (cstr && apr_pool_initialize() == APR_SUCCESS) {
+    apr_pool_t *pool = NULL;
+    apr_pool_create(&pool, NULL);
+
+    apr_uri_t tmp_uri;
+    if (apr_uri_parse(pool, cstr, &tmp_uri) == APR_SUCCESS) {
+      apr_uri_unparse(pool, &tmp_uri, 0);
+    }
+    apr_uri_parse_hostinfo(pool, cstr, &tmp_uri);
+
+    // Cleanup
+    apr_pool_terminate();
+  }
+
+  af_gb_cleanup();
+  return 0;
+}
diff --git a/projects/apache-httpd/fuzz_utils.c b/projects/apache-httpd/fuzz_utils.c
new file mode 100644
index 0000000..8fb2d25
--- /dev/null
+++ b/projects/apache-httpd/fuzz_utils.c
@@ -0,0 +1,182 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_poll.h"
+#include "apr_portable.h"
+#include "apr_proc_mutex.h"
+#include "apr_signal.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_proc.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_file_io.h"
+#include "apr_fnmatch.h"
+#include "apr_want.h"
+
+#include "apr_poll.h"
+#include "apr_want.h"
+
+#include "ap_config.h"
+#include "ap_expr.h"
+#include "ap_listen.h"
+#include "ap_provider.h"
+#include "ap_regex.h"
+
+#include "ada_fuzz_header.h"
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  // Initialize fuzzing garbage collector. We use this to easily
+  // get data types seeded with random input from the fuzzer.
+  af_gb_init();
+
+  const uint8_t *data2 = data;
+  size_t size2 = size;
+
+  char *new_str = af_gb_get_null_terminated(&data2, &size2);
+  char *new_dst = af_gb_get_null_terminated(&data2, &size2);
+  if (new_str != NULL && new_dst != NULL) {
+
+    // Targets that do not require a pool
+    ap_cstr_casecmp(new_str, new_str);
+    ap_getparents(new_str);
+    ap_unescape_url(new_str);
+    ap_unescape_urlencoded(new_str);
+    ap_strcmp_match(new_str, new_dst);
+
+    char *ns3 = af_gb_get_null_terminated(&data2, &size2);
+    if (ns3 != NULL) {
+      ap_no2slash(ns3);
+    }
+
+    char *ns11 = af_gb_get_null_terminated(&data2, &size2);
+    if (ns11) {
+      char *ns10 = malloc(strlen(ns11)*3+1); // big enough for worst-case URL-escaped input.
+      ap_escape_path_segment_buffer(ns10, ns11);
+      free(ns10);
+    }
+
+    // Pool initialisation
+    if (apr_pool_initialize() == APR_SUCCESS) {
+      apr_pool_t *pool = NULL;
+      apr_pool_create(&pool, NULL);
+
+      // Targets that require a pool
+      ns3 = af_gb_get_null_terminated(&data2, &size2);
+      if (ns3 != NULL) {
+        ap_make_dirstr_parent(pool, ns3);
+      }
+
+      ap_field_noparam(pool, new_str);
+
+      ap_escape_shell_cmd(pool, new_str);
+      ap_os_escape_path(pool, new_str, 0);
+      ap_escape_html2(pool, new_str, 0);
+      ap_escape_logitem(pool, new_str);
+
+      // This line causes some issues if something bad is allocated
+      ap_escape_quotes(pool, new_str);
+
+      if (size > 2) {
+        ap_cstr_casecmpn(new_str, new_str + 2, size - 2);
+      }
+
+      char *d = malloc(size * 2);
+      ap_escape_errorlog_item(d, new_str, size * 2);
+      free(d);
+
+      // base64
+      char *decoded = NULL;
+      decoded = ap_pbase64decode(pool, new_str);
+      ap_pbase64encode(pool, new_str);
+
+      char *ns12 = af_gb_get_null_terminated(&data2, &size2);
+      if (ns12 != NULL) {
+        char *d;
+        apr_size_t dlen;
+        ap_pbase64decode_strict(pool, ns12, &d, &dlen);
+      }
+
+      char *tmp_s = new_str;
+      ap_getword_conf2(pool, &tmp_s);
+
+      // str functions
+      ap_strcasecmp_match(tmp_s, new_dst);
+      ap_strcasestr(tmp_s, new_dst);
+
+      // List functions
+      tmp_s = new_str;
+      ap_get_list_item(pool, &tmp_s);
+      tmp_s = new_str;
+      ap_find_list_item(pool, &tmp_s, "kjahsdfkj");
+      ap_find_token(pool, tmp_s, "klsjdfk");
+      ap_find_last_token(pool, tmp_s, "sdadf");
+      ap_is_chunked(pool, tmp_s);
+
+      apr_array_header_t *offers = NULL;
+      ap_parse_token_list_strict(pool, new_str, &offers, 0);
+
+      char *tmp_null = NULL;
+      ap_pstr2_alnum(pool, new_str, &tmp_null);
+
+      // Word functions
+      tmp_s = new_str;
+      ap_getword(pool, &tmp_s, 0);
+
+      tmp_s = new_str;
+      ap_getword_white_nc(pool, &tmp_s);
+
+      tmp_s = new_str;
+      ap_get_token(pool, &tmp_s, 1);
+
+      tmp_s = new_str;
+      ap_escape_urlencoded(pool, tmp_s);
+
+      apr_interval_time_t timeout;
+      ap_timeout_parameter_parse(new_str, &timeout, "ms");
+
+      tmp_s = new_str;
+      ap_content_type_tolower(tmp_s);
+
+
+			char filename[256];
+			sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+			FILE *fp = fopen(filename, "wb");
+			fwrite(data, size, 1, fp);
+			fclose(fp);
+
+			// Fuzzer logic here
+			ap_configfile_t *cfg;
+			ap_pcfg_openfile(&cfg, pool, filename);
+      char tmp_line[100];
+      if ((af_get_short(&data2, &size2) % 2) == 0) {
+        ap_cfg_getline(tmp_line, 100, cfg);
+      }
+      else {
+        cfg->getstr = NULL;
+        ap_cfg_getline(tmp_line, 100, cfg);
+      }
+			// Fuzzer logic end
+
+			unlink(filename);
+
+      // Cleanup
+      apr_pool_terminate();
+    }
+  }
+
+  // Cleanup all of the memory allocated by the fuzz headers.
+  af_gb_cleanup();
+  return 0;
+}
diff --git a/projects/apache-httpd/patches.diff b/projects/apache-httpd/patches.diff
new file mode 100644
index 0000000..d93b12b
--- /dev/null
+++ b/projects/apache-httpd/patches.diff
@@ -0,0 +1,44 @@
+diff --git a/server/apreq_parser_header.c b/server/apreq_parser_header.c
+index 19588be..7067e58 100644
+--- a/server/apreq_parser_header.c
++++ b/server/apreq_parser_header.c
+@@ -89,7 +89,7 @@ static apr_status_t split_header_line(apreq_param_t **p,
+         if (s != APR_SUCCESS)
+             return s;
+ 
+-        assert(nlen >= len);
++	if (!(nlen >= len)) { return APR_EBADARG; } assert(nlen >= len);
+         end->iov_len = len;
+         nlen -= len;
+ 
+@@ -103,13 +103,13 @@ static apr_status_t split_header_line(apreq_param_t **p,
+         if (s != APR_SUCCESS)
+             return s;
+ 
+-        assert(glen >= dlen);
++	if (!(glen >= dlen)) { return APR_EBADARG; } assert(glen >= dlen);
+         glen -= dlen;
+         e = APR_BUCKET_NEXT(e);
+     }
+ 
+     /* copy value */
+-    assert(vlen > 0);
++    if (!(vlen > 0)) { return APR_EBADARG; } assert(vlen > 0);
+     dest = v->data;
+     while (vlen > 0) {
+ 
+@@ -119,12 +119,12 @@ static apr_status_t split_header_line(apreq_param_t **p,
+ 
+         memcpy(dest, data, dlen);
+         dest += dlen;
+-        assert(vlen >= dlen);
++	if (!(vlen >= dlen)) { return APR_EBADARG; } assert(vlen >= dlen);
+         vlen -= dlen;
+         e = APR_BUCKET_NEXT(e);
+     }
+ 
+-    assert(dest[-1] == '\n');
++    if (!(dest[-1] == '\n')) { return APR_EBADARG; } assert(dest[-1] == '\n');
+ 
+     if (dest[-2] == '\r')
+         --dest;
diff --git a/projects/apache-httpd/project.yaml b/projects/apache-httpd/project.yaml
new file mode 100644
index 0000000..4b7652b
--- /dev/null
+++ b/projects/apache-httpd/project.yaml
@@ -0,0 +1,8 @@
+homepage: "https://httpd.apache.org/"
+language: c
+primary_contact: "david@adalogics.com"
+auto_ccs:
+ - "stefan.eissing@gmail.com"
+ - "covener@gmail.com"
+ - "ylavic.dev@gmail.com"
+main_repo: "https://github.com/apache/httpd"
diff --git a/projects/assimp/Dockerfile b/projects/assimp/Dockerfile
index 88564a7..cf7ccd6 100644
--- a/projects/assimp/Dockerfile
+++ b/projects/assimp/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2019 Google Inc.
+# Copyright 2021 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/projects/assimp/build.sh b/projects/assimp/build.sh
index 55efcb7..4cb8bea 100644
--- a/projects/assimp/build.sh
+++ b/projects/assimp/build.sh
@@ -1,5 +1,5 @@
 #!/bin/bash -eu
-# Copyright 2019 Google Inc.
+# Copyright 2021 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
 ################################################################################
 
 # generate build env and build assimp
-cmake CMakeLists.txt -G "Ninja" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_ZLIB=ON -DASSIMP_BUILD_TESTS=OFF -DASSIMP_BUILD_ASSIMP_TOOLS=OFF -DASSIMP_BUILD_SAMPLES=OFF
+cmake CMakeLists.txt -G "Ninja" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_ZLIB=ON \
+                                -DASSIMP_BUILD_TESTS=OFF -DASSIMP_BUILD_ASSIMP_TOOLS=OFF \
+                                -DASSIMP_BUILD_SAMPLES=OFF
 cmake --build .
 
-# build the fuzzer
-$CXX $CXXFLAGS -std=c++11 -I$SRC/assimp/include \
-	fuzz/assimp_fuzzer.cc -o $OUT/assimp_fuzzer \
-	$LIB_FUZZING_ENGINE $SRC/assimp/lib/libassimp.a $SRC/assimp/lib/libIrrXML.a $SRC/assimp/lib/libzlibstatic.a
+# Build the fuzzer
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -std=c++11 -I$SRC/assimp/include \
+		fuzz/assimp_fuzzer.cc -o $OUT/assimp_fuzzer  \
+		./lib/libassimp.a ./contrib/zlib/libzlibstatic.a
diff --git a/projects/assimp/project.yaml b/projects/assimp/project.yaml
index 834e912..10d056f 100644
--- a/projects/assimp/project.yaml
+++ b/projects/assimp/project.yaml
@@ -3,7 +3,8 @@
 primary_contact: "kim.kulling@googlemail.com"
 sanitizers:
   - address
-  - memory:
-     experimental: True
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+#     experimental: True
   - undefined
 main_repo: 'https://github.com/assimp/assimp.git'
diff --git a/projects/assimp/project_proposed.yaml b/projects/assimp/project_proposed.yaml
deleted file mode 100644
index 612e75b..0000000
--- a/projects/assimp/project_proposed.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-homepage: "https://github.com/assimp/assimp"
-primary_contact: "kim.kulling@googlemail.com"
-auto_ccs:
-  - "kientzle@gmail.com"
-  - "martin@matuska.org"
-sanitizers:
-  - address
-  - memory:
-     experimental: True
-  - undefined
diff --git a/projects/bazel-rules-fuzzing-test-java/Dockerfile b/projects/bazel-rules-fuzzing-test-java/Dockerfile
new file mode 100644
index 0000000..89e8b87
--- /dev/null
+++ b/projects/bazel-rules-fuzzing-test-java/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN git clone https://github.com/bazelbuild/rules_fuzzing.git
+WORKDIR $SRC/rules_fuzzing/
+COPY build.sh $SRC/
diff --git a/projects/bazel-rules-fuzzing-test-java/build.sh b/projects/bazel-rules-fuzzing-test-java/build.sh
new file mode 100644
index 0000000..4698ebd
--- /dev/null
+++ b/projects/bazel-rules-fuzzing-test-java/build.sh
@@ -0,0 +1,27 @@
+#!/bin/bash -eu
+#
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Due to https://github.com/bazelbuild/bazel/issues/11128, affecting Bazel 4.0
+# or earlier, we cannot use the "@rules_fuzzing//" prefix for the label-typed
+# cc_engine configuration flag when fuzzing directly the rules_fuzzing workspace.
+#
+# This is NOT needed for any other Bazel repository that depends on
+# rules_fuzzing.
+export BAZEL_EXTRA_BUILD_FLAGS="--//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine"
+
+bazel_build_fuzz_tests
diff --git a/projects/bazel-rules-fuzzing-test-java/project.yaml b/projects/bazel-rules-fuzzing-test-java/project.yaml
new file mode 100644
index 0000000..888c37f
--- /dev/null
+++ b/projects/bazel-rules-fuzzing-test-java/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/bazelbuild/rules_fuzzing"
+language: jvm
+primary_contact: "test@example.com"
+
+fuzzing_engines:
+  - libfuzzer
+
+sanitizers:
+  - address
+  - undefined
+
+# This is a test project.
+disabled: true
diff --git a/projects/bazel-rules-fuzzing-test/build.sh b/projects/bazel-rules-fuzzing-test/build.sh
index 056e16b..4698ebd 100644
--- a/projects/bazel-rules-fuzzing-test/build.sh
+++ b/projects/bazel-rules-fuzzing-test/build.sh
@@ -16,7 +16,12 @@
 #
 ################################################################################
 
-# This is an example build script for projects using the rules_fuzzing library
-# for Bazel.
+# Due to https://github.com/bazelbuild/bazel/issues/11128, affecting Bazel 4.0
+# or earlier, we cannot use the "@rules_fuzzing//" prefix for the label-typed
+# cc_engine configuration flag when fuzzing directly the rules_fuzzing workspace.
+#
+# This is NOT needed for any other Bazel repository that depends on
+# rules_fuzzing.
+export BAZEL_EXTRA_BUILD_FLAGS="--//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine"
 
 bazel_build_fuzz_tests
diff --git a/projects/bearssl/Dockerfile b/projects/bearssl/Dockerfile
index 2a5d3e7..6f14e63 100644
--- a/projects/bearssl/Dockerfile
+++ b/projects/bearssl/Dockerfile
@@ -20,5 +20,5 @@
 RUN git clone --depth 1 https://github.com/randombit/botan.git
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
 COPY build.sh $SRC/
diff --git a/projects/bearssl/project.yaml b/projects/bearssl/project.yaml
index d9b20ae..720d457 100644
--- a/projects/bearssl/project.yaml
+++ b/projects/bearssl/project.yaml
@@ -6,7 +6,8 @@
 sanitizers:
  - address
  - undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 architectures:
  - x86_64
  - i386
diff --git a/projects/bignum-fuzzer/Dockerfile b/projects/bignum-fuzzer/Dockerfile
index 6b74836..b1c36eb 100644
--- a/projects/bignum-fuzzer/Dockerfile
+++ b/projects/bignum-fuzzer/Dockerfile
@@ -15,12 +15,12 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y software-properties-common python-software-properties wget curl sudo mercurial autoconf bison texinfo libboost-all-dev cmake
+RUN apt-get update && apt-get install -y software-properties-common curl sudo mercurial autoconf bison texinfo libboost-all-dev cmake wget
 
-RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.0.tar.gz
+RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.1.tar.gz
 RUN git clone --depth 1 https://github.com/guidovranken/bignum-fuzzer
 RUN git clone --depth 1 https://github.com/openssl/openssl
 RUN hg clone https://gmplib.org/repo/gmp/ libgmp/
 RUN git clone https://boringssl.googlesource.com/boringssl
-RUN git clone --depth 1 https://github.com/ARMmbed/mbedtls
+RUN git clone --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls
 COPY build.sh $SRC/
diff --git a/projects/bignum-fuzzer/build.sh b/projects/bignum-fuzzer/build.sh
index 8c29baf..7371200 100755
--- a/projects/bignum-fuzzer/build.sh
+++ b/projects/bignum-fuzzer/build.sh
@@ -20,8 +20,8 @@
 #source $HOME/.cargo/env
 
 # Build libmpdec
-tar zxf mpdecimal-2.5.0.tar.gz
-cd mpdecimal-2.5.0
+tar zxf mpdecimal-2.5.1.tar.gz
+cd mpdecimal-2.5.1
 ./configure && make -j$(nproc)
 
 cd $SRC/openssl
@@ -60,7 +60,7 @@
 
 # Build libmpdec module
 cd $SRC/bignum-fuzzer/modules/libmpdec
-LIBMPDEC_A_PATH=$SRC/mpdecimal-2.5.0/libmpdec/libmpdec.a LIBMPDEC_INCLUDE_PATH=$SRC/mpdecimal-2.5.0/libmpdec make
+LIBMPDEC_A_PATH=$SRC/mpdecimal-2.5.1/libmpdec/libmpdec.a LIBMPDEC_INCLUDE_PATH=$SRC/mpdecimal-2.5.1/libmpdec make
 
 BASE_CXXFLAGS=$CXXFLAGS
 
diff --git a/projects/binutils/build.sh b/projects/binutils/build.sh
index c5d9038..2b51424 100755
--- a/projects/binutils/build.sh
+++ b/projects/binutils/build.sh
@@ -29,7 +29,9 @@
 sed -i 's/fprintf (stderr/\/\//' elfcomm.c
 cd ../
 
-./configure --disable-gdb --enable-targets=all
+./configure --disable-gdb --disable-gdbserver --disable-gdbsupport \
+	    --disable-libdecnumber --disable-readline --disable-sim \
+	    --enable-targets=all --disable-werror
 make MAKEINFO=true && true
 
 # Make fuzzer directory
@@ -58,13 +60,16 @@
 done
 
 # Link the files
-## Readelf
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib -o fuzz_readelf fuzz_readelf.o version.o unwind-ia64.o dwarf.o elfcomm.o ../libctf/.libs/libctf-nobfd.a -L/src/binutils-gdb/zlib -lz ../libiberty/libiberty.a 
-mv fuzz_readelf $OUT/fuzz_readelf
+# Only link if they exist
+if ([ -f dwarf.o ] && [ -f elfcomm.o ] && [ -f version.o ]); then
+  ## Readelf
+  $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib -o fuzz_readelf fuzz_readelf.o version.o unwind-ia64.o dwarf.o elfcomm.o ../libctf/.libs/libctf-nobfd.a -L/src/binutils-gdb/zlib -lz ../libiberty/libiberty.a 
+  mv fuzz_readelf $OUT/fuzz_readelf
 
-### Set up seed corpus for readelf in the form of a single ELF file. 
-zip fuzz_readelf_seed_corpus.zip /src/fuzz_readelf_seed_corpus/simple_elf
-mv fuzz_readelf_seed_corpus.zip $OUT/ 
+  ### Set up seed corpus for readelf in the form of a single ELF file. 
+  zip fuzz_readelf_seed_corpus.zip /src/fuzz_readelf_seed_corpus/simple_elf
+  mv fuzz_readelf_seed_corpus.zip $OUT/ 
 
-## Copy over the options file
-cp $SRC/fuzz_readelf.options $OUT/fuzz_readelf.options
+  ## Copy over the options file
+  cp $SRC/fuzz_readelf.options $OUT/fuzz_readelf.options
+fi
diff --git a/projects/binutils/fuzz_readelf.c b/projects/binutils/fuzz_readelf.c
index a222e0c..9df34fd 100644
--- a/projects/binutils/fuzz_readelf.c
+++ b/projects/binutils/fuzz_readelf.c
@@ -28,18 +28,18 @@
 
 	fwrite(data, size, 1, fp);
 	fclose(fp);
-	do_syms = TRUE;
-	do_reloc = TRUE;
-	do_unwind = TRUE;
-	do_dynamic = TRUE;
-	do_header = TRUE;
-	do_sections = TRUE;
-	do_section_groups = TRUE;
-	do_segments = TRUE;
-	do_version = TRUE;
-	do_histogram = TRUE;
-	do_arch = TRUE;
-	do_notes = TRUE;
+	do_syms = true;
+	do_reloc = true;
+	do_unwind = true;
+	do_dynamic = true;
+	do_header = true;
+	do_sections = true;
+	do_section_groups = true;
+	do_segments = true;
+	do_version = true;
+	do_histogram = true;
+	do_arch = true;
+	do_notes = true;
 
     // Main fuzz entrypoint
 	process_file(filename);
diff --git a/projects/bitcoin-core/Dockerfile b/projects/bitcoin-core/Dockerfile
new file mode 100644
index 0000000..6197271
--- /dev/null
+++ b/projects/bitcoin-core/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+
+# Packages taken from:
+# * https://github.com/bitcoin/bitcoin/blob/master/doc/build-unix.md#dependency-build-instructions
+# * https://github.com/bitcoin/bitcoin/blob/master/depends/README.md#for-linux-including-i386-arm-cross-compilation
+RUN apt-get update && apt-get install -y \
+  build-essential libtool autotools-dev automake pkg-config bsdmainutils python3 \
+  make automake cmake curl g++-multilib libtool binutils-gold bsdmainutils pkg-config patch bison \
+  wget zip
+
+RUN git clone --depth=1 https://github.com/bitcoin/bitcoin.git bitcoin-core
+RUN git clone --depth=1 https://github.com/bitcoin-core/qa-assets bitcoin-core/assets
+RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
+RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git
+RUN git clone --depth 1 https://github.com/randombit/botan.git
+RUN git clone --depth 1 https://github.com/trezor/trezor-firmware.git
+RUN git clone --depth 1 https://github.com/google/wycheproof.git
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+WORKDIR bitcoin-core
+COPY build.sh $SRC/
+COPY build_cryptofuzz.sh $SRC/
diff --git a/projects/bitcoin-core/build.sh b/projects/bitcoin-core/build.sh
new file mode 100755
index 0000000..a89691a
--- /dev/null
+++ b/projects/bitcoin-core/build.sh
@@ -0,0 +1,97 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+$SRC/build_cryptofuzz.sh
+
+cd $SRC/bitcoin-core/
+
+# Build dependencies
+# This will also force static builds
+if [ "$ARCHITECTURE" = "i386" ]; then
+  export BUILD_TRIPLET="i686-pc-linux-gnu"
+else
+  export BUILD_TRIPLET="x86_64-pc-linux-gnu"
+fi
+(
+  cd depends
+  sed -i --regexp-extended '/.*rm -rf .*extract_dir.*/d' ./funcs.mk  # Keep extracted source
+  make HOST=$BUILD_TRIPLET DEBUG=1 NO_QT=1 NO_WALLET=1 NO_ZMQ=1 NO_UPNP=1 NO_NATPMP=1 boost_cxxflags="-std=c++17 -fvisibility=hidden -fPIC ${CXXFLAGS}" libevent_cflags="${CFLAGS}" -j$(nproc)
+)
+
+# Build the fuzz targets
+
+sed -i "s|PROVIDE_FUZZ_MAIN_FUNCTION|NEVER_PROVIDE_MAIN_FOR_OSS_FUZZ|g" "./configure.ac"
+./autogen.sh
+
+# Temporarily compile with O2 to work around clang-13 (and later) UBSan
+# -fsanitize=vptr,object-size false positive that only happens with -O1
+if [ "$SANITIZER" = "undefined" ]; then
+  export CFLAGS="$CFLAGS -O2"
+  export CXXFLAGS="$CXXFLAGS -O2"
+fi
+
+# OSS-Fuzz will provide CC, CXX, etc. So only set:
+# * --enable-fuzz, see https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md
+# * CONFIG_SITE, see https://github.com/bitcoin/bitcoin/blob/master/depends/README.md
+if [ "$SANITIZER" = "memory" ]; then
+  CONFIG_SITE="$PWD/depends/$BUILD_TRIPLET/share/config.site" ./configure --enable-fuzz SANITIZER_LDFLAGS="$LIB_FUZZING_ENGINE" --with-asm=no
+else
+  CONFIG_SITE="$PWD/depends/$BUILD_TRIPLET/share/config.site" ./configure --enable-fuzz SANITIZER_LDFLAGS="$LIB_FUZZING_ENGINE"
+fi
+
+
+if [ "$SANITIZER" = "memory" ]; then
+  # MemorySanitizer (MSAN) does not support tracking memory initialization done by
+  # using the Linux getrandom syscall. Avoid using getrandom by undefining
+  # HAVE_SYS_GETRANDOM. See https://github.com/google/sanitizers/issues/852 for
+  # details.
+  grep -v HAVE_SYS_GETRANDOM src/config/bitcoin-config.h > src/config/bitcoin-config.h.tmp
+  mv src/config/bitcoin-config.h.tmp src/config/bitcoin-config.h
+fi
+
+make -j$(nproc)
+
+WRITE_ALL_FUZZ_TARGETS_AND_ABORT="/tmp/a" "./src/test/fuzz/fuzz" || true
+readarray FUZZ_TARGETS < "/tmp/a"
+if [ -n "${OSS_FUZZ_CI-}" ]; then
+  # When running in CI, check the first targets only to save time and disk space
+  FUZZ_TARGETS=( ${FUZZ_TARGETS[@]:0:2} )
+fi
+
+# OSS-Fuzz requires a separate and self-contained binary for each fuzz target.
+# To inject the fuzz target name in the finished binary, compile the fuzz
+# executable with a "magic string" as the name of the fuzz target.
+#
+# An alternative to mocking the string in the finished binary would be to
+# replace the string in the source code and re-invoke 'make'. This is slower,
+# so use the hack.
+export MAGIC_STR="b5813eee2abc9d3358151f298b75a72264ffa119d2f71ae7fefa15c4b70b4bc5b38e87e3107a730f25891ea428b2b4fabe7a84f5bfa73c79e0479e085e4ff157"
+sed -i "s|.*std::getenv(\"FUZZ\").*|std::string fuzz_target{\"$MAGIC_STR\"};|g" "./src/test/fuzz/fuzz.cpp"
+sed -i "s|.find(fuzz_target)|.find(fuzz_target.c_str())|g"                      "./src/test/fuzz/fuzz.cpp"
+make -j$(nproc)
+
+# Replace the magic string with the actual name of each fuzz target
+for fuzz_target in ${FUZZ_TARGETS[@]}; do
+  python3 -c "c_str_target=b\"${fuzz_target}\x00\";c_str_magic=b\"$MAGIC_STR\";c=open('./src/test/fuzz/fuzz','rb').read();c=c.replace(c_str_magic, c_str_target+c_str_magic[len(c_str_target):]);open(\"$OUT/$fuzz_target\",'wb').write(c)"
+  chmod +x "$OUT/$fuzz_target"
+  (
+    cd assets/fuzz_seed_corpus
+    if [ -d "$fuzz_target" ]; then
+      zip --recurse-paths --quiet --junk-paths "$OUT/${fuzz_target}_seed_corpus.zip" "${fuzz_target}"
+    fi
+  )
+done
diff --git a/projects/bitcoin-core/build_cryptofuzz.sh b/projects/bitcoin-core/build_cryptofuzz.sh
new file mode 100755
index 0000000..4e6d91a
--- /dev/null
+++ b/projects/bitcoin-core/build_cryptofuzz.sh
@@ -0,0 +1,175 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL"
+export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE"
+
+# Install Boost headers
+cd $SRC/
+tar jxf boost_1_74_0.tar.bz2
+cd boost_1_74_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+export CXXFLAGS="$CXXFLAGS -I $SRC/boost_1_74_0/"
+
+# Preconfigure libsecp256k1
+cd $SRC/secp256k1/
+autoreconf -ivf
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SECP256K1"
+
+function build_libsecp256k1() {
+    # Build libsecp256k1
+    cd $SRC/secp256k1/
+
+    if test -f "Makefile"; then
+        # Remove old configuration if it exists
+        make clean
+
+        # Prevent the error:
+        # "configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build."
+        rm -f src/ecmult_static_pre_g.h
+    fi
+
+    SECP256K1_CONFIGURE_PARAMS="
+        --enable-static
+        --disable-tests
+        --disable-benchmark
+        --disable-exhaustive-tests
+        --enable-module-recovery
+        --enable-experimental
+        --enable-module-schnorrsig
+        --enable-module-ecdh"
+
+    if [[ $CFLAGS = *sanitize=memory* ]]
+    then
+        ./configure $SECP256K1_CONFIGURE_PARAMS --with-asm=no "$@"
+    else
+        ./configure $SECP256K1_CONFIGURE_PARAMS "$@"
+    fi
+    make
+
+    export SECP256K1_INCLUDE_PATH=$(realpath .)
+    export LIBSECP256K1_A_PATH=$(realpath .libs/libsecp256k1.a)
+
+    # Build libsecp256k1 Cryptofuzz module
+    cd $SRC/cryptofuzz/modules/secp256k1/
+    make -B -j$(nproc)
+}
+
+# Build Trezor firmware
+cd $SRC/trezor-firmware/crypto/
+# Rename blake2b_* functions to avoid symbol collisions with other libraries
+sed -i "s/\<blake2b_\([A-Za-z_]\)/trezor_blake2b_\1/g" *.c *.h
+sed -i 's/\<blake2b(/trezor_blake2b(/g' *.c *.h
+cd ../../
+export TREZOR_FIRMWARE_PATH=$(realpath trezor-firmware)
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_TREZOR_FIRMWARE"
+
+# Build Botan
+cd $SRC/botan
+if [[ $CFLAGS != *-m32* ]]
+then
+    ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation
+else
+    ./configure.py --cpu=x86_32 --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation
+fi
+make -j$(nproc)
+
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
+export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a"
+export BOTAN_INCLUDE_PATH="$SRC/botan/build/include"
+
+# Build Cryptofuzz
+cd $SRC/cryptofuzz
+python gen_repository.py
+rm extra_options.h
+echo -n '"' >>extra_options.h
+echo -n '--operations=' >>extra_options.h
+echo -n 'Digest,' >>extra_options.h
+echo -n 'HMAC,' >>extra_options.h
+echo -n 'KDF_HKDF,' >>extra_options.h
+echo -n 'SymmetricEncrypt,' >>extra_options.h
+echo -n 'SymmetricDecrypt,' >>extra_options.h
+echo -n 'ECC_PrivateToPublic,' >>extra_options.h
+echo -n 'ECC_ValidatePubkey,' >>extra_options.h
+echo -n 'ECC_Point_Add,' >>extra_options.h
+echo -n 'ECC_Point_Mul,' >>extra_options.h
+echo -n 'ECDSA_Sign,' >>extra_options.h
+echo -n 'ECDSA_Verify,' >>extra_options.h
+echo -n 'ECDSA_Recover,' >>extra_options.h
+echo -n 'Schnorr_Sign,' >>extra_options.h
+echo -n 'Schnorr_Verify,' >>extra_options.h
+echo -n 'ECDH_Derive,' >>extra_options.h
+echo -n 'BignumCalc_Mod_2Exp256 ' >>extra_options.h
+echo -n 'BignumCalc_Mod_SECP256K1 ' >>extra_options.h
+echo -n '--curves=secp256k1 ' >>extra_options.h
+echo -n '--digests=NULL,SHA1,SHA256,SHA512,RIPEMD160,SHA3-256,SIPHASH64 ' >>extra_options.h
+echo -n '--ciphers=CHACHA20,AES_256_CBC ' >>extra_options.h
+echo -n '--calcops=' >>extra_options.h
+# Bitcoin Core arith_uint256.cpp operations
+echo -n 'Add,And,Div,IsEq,IsGt,IsGte,IsLt,IsLte,IsOdd,Mul,NumBits,Or,Set,Sub,Xor,' >>extra_options.h
+# libsecp256k1 scalar operations
+echo -n 'IsZero,IsOne,IsEven,Add,Mul,InvMod,IsEq,CondSet,Bit,Set,RShift ' >>extra_options.h
+echo -n '"' >>extra_options.h
+cd modules/bitcoin/
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BITCOIN"
+make -B -j$(nproc)
+cd ../trezor/
+make -B -j$(nproc)
+cd ../botan/
+make -B -j$(nproc)
+
+cd ../schnorr_fun/
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SCHNORR_FUN"
+if [[ $CFLAGS != *-m32* ]]
+then
+    make
+else
+    make -f Makefile.i386
+fi
+
+cd ../../
+
+# Build with 3 configurations of libsecp256k1
+# Discussion: https://github.com/google/oss-fuzz/pull/5717#issuecomment-842765383
+
+build_libsecp256k1 "--with-ecmult-window=2" "--with-ecmult-gen-precision=2"
+cd $SRC/cryptofuzz/
+make -B -j$(nproc)
+cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w2-p2
+
+build_libsecp256k1 "--with-ecmult-window=15" "--with-ecmult-gen-precision=4"
+cd $SRC/cryptofuzz/
+rm cryptofuzz
+make
+cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w15-p4
+
+build_libsecp256k1 "--with-ecmult-window=20" "--with-ecmult-gen-precision=8"
+cd $SRC/cryptofuzz/
+rm cryptofuzz
+make
+cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w20-p8
+
+# Convert Wycheproof test vectors to Cryptofuzz corpus format
+mkdir $SRC/corpus-cryptofuzz-wycheproof/
+find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_secp256k1_*' -exec $SRC/cryptofuzz/cryptofuzz --from-wycheproof={},$SRC/corpus-cryptofuzz-wycheproof/ \;
+# Pack the Wycheproof test vectors
+zip -j cryptofuzz-bitcoin-cryptography_seed_corpus.zip $SRC/corpus-cryptofuzz-wycheproof/*
+# Use them as the seed corpus for each of the fuzzers
+cp cryptofuzz-bitcoin-cryptography_seed_corpus.zip $OUT/cryptofuzz-bitcoin-cryptography-w2-p2_seed_corpus.zip
+cp cryptofuzz-bitcoin-cryptography_seed_corpus.zip $OUT/cryptofuzz-bitcoin-cryptography-w15-p4_seed_corpus.zip
+cp cryptofuzz-bitcoin-cryptography_seed_corpus.zip $OUT/cryptofuzz-bitcoin-cryptography-w20-p8_seed_corpus.zip
diff --git a/projects/bitcoin-core/project.yaml b/projects/bitcoin-core/project.yaml
new file mode 100644
index 0000000..9d6f336
--- /dev/null
+++ b/projects/bitcoin-core/project.yaml
@@ -0,0 +1,22 @@
+homepage: "https://github.com/bitcoin/bitcoin"
+main_repo: 'https://github.com/bitcoin/bitcoin.git'
+language: c++
+primary_contact: "marco@chaincode.com"
+auto_ccs:
+  - "fanquake@gmail.com"
+  - "john@brink.dev"
+  - "jonas@chaincode.com"
+  - "laanwj@gmail.com"
+  - "pieter@chaincode.com"
+  - "thomas.j.bitcoin@protonmail.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+architectures:
+  - x86_64
+  - i386
+fuzzing_engines:
+  - libfuzzer
+  - honggfuzz
+  - afl
diff --git a/projects/blackfriday/Dockerfile b/projects/blackfriday/Dockerfile
new file mode 100644
index 0000000..66975f7
--- /dev/null
+++ b/projects/blackfriday/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 --branch v2 https://github.com/russross/blackfriday
+COPY build.sh render_fuzzer.go $SRC/
+WORKDIR $SRC/blackfriday
diff --git a/projects/blackfriday/build.sh b/projects/blackfriday/build.sh
new file mode 100644
index 0000000..791e35b
--- /dev/null
+++ b/projects/blackfriday/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cp $SRC/render_fuzzer.go .
+
+rm go.mod
+go mod init github.com/russross/blackfriday
+
+compile_go_fuzzer github.com/russross/blackfriday Fuzz render_fuzzer
diff --git a/projects/blackfriday/project.yaml b/projects/blackfriday/project.yaml
new file mode 100644
index 0000000..7499326
--- /dev/null
+++ b/projects/blackfriday/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/russross/blackfriday"
+main_repo: "https://github.com/russross/blackfriday"
+primary_contact: "security-tps@google.com"
+auto_ccs :
+  - "jvoisin@google.com"
+  - "Adam@adalogics.com"
+language: go
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
diff --git a/projects/blackfriday/render_fuzzer.go b/projects/blackfriday/render_fuzzer.go
new file mode 100644
index 0000000..851f3ce
--- /dev/null
+++ b/projects/blackfriday/render_fuzzer.go
@@ -0,0 +1,21 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package blackfriday
+
+func Fuzz(data []byte) int {
+	Run(data)
+	return 0
+}
diff --git a/projects/bleach/Dockerfile b/projects/bleach/Dockerfile
index 1d31647..b5b1f43 100644
--- a/projects/bleach/Dockerfile
+++ b/projects/bleach/Dockerfile
@@ -14,11 +14,11 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
 RUN git clone \
 	--depth 1 \
-	--branch master \
+	--branch main \
 	https://github.com/mozilla/bleach.git
 
 WORKDIR bleach
diff --git a/projects/bleach/build.sh b/projects/bleach/build.sh
index b3b6179..5428291 100644
--- a/projects/bleach/build.sh
+++ b/projects/bleach/build.sh
@@ -30,5 +30,5 @@
 this_dir=\$(dirname \"\$0\")
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/bleach/linkify_fuzzer.py b/projects/bleach/linkify_fuzzer.py
index 6a42b07..7de9764 100644
--- a/projects/bleach/linkify_fuzzer.py
+++ b/projects/bleach/linkify_fuzzer.py
@@ -16,7 +16,8 @@
 
 import sys
 import atheris
-import bleach
+with atheris.instrument_imports():
+  import bleach
 
 
 def TestOneInput(input_bytes):
diff --git a/projects/bleach/sanitize_fuzzer.py b/projects/bleach/sanitize_fuzzer.py
index 3337816..3ae4344 100644
--- a/projects/bleach/sanitize_fuzzer.py
+++ b/projects/bleach/sanitize_fuzzer.py
@@ -16,7 +16,8 @@
 
 import sys
 import atheris
-import bleach
+with atheris.instrument_imports():
+  import bleach
 
 
 def TestOneInput(input_bytes):
diff --git a/projects/bloaty/Dockerfile b/projects/bloaty/Dockerfile
index 7a08527..e47be56 100644
--- a/projects/bloaty/Dockerfile
+++ b/projects/bloaty/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y cmake ninja-build g++
+RUN apt-get update && apt-get install -y cmake ninja-build g++ libz-dev
 RUN git clone --depth 1 https://github.com/google/bloaty.git bloaty
 WORKDIR bloaty
 COPY build.sh $SRC/
diff --git a/projects/bls-signatures/Dockerfile b/projects/bls-signatures/Dockerfile
new file mode 100644
index 0000000..5faedbb
--- /dev/null
+++ b/projects/bls-signatures/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool wget python lzip libgmp-dev
+RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
+RUN git clone --depth 1 https://github.com/supranational/blst
+RUN git clone --depth 1 https://github.com/Chia-Network/bls-signatures.git
+RUN git clone --depth 1 https://github.com/herumi/mcl.git
+RUN git clone --depth 1 https://github.com/randombit/botan.git
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz
+RUN wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz
+COPY build.sh $SRC/
diff --git a/projects/bls-signatures/build.sh b/projects/bls-signatures/build.sh
new file mode 100755
index 0000000..2ba7f97
--- /dev/null
+++ b/projects/bls-signatures/build.sh
@@ -0,0 +1,250 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -D_LIBCPP_DEBUG=1"
+if [[ "$SANITIZER" = "memory" ]]
+then
+    export CXXFLAGS="$CXXFLAGS -DMSAN"
+fi
+export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE"
+export LINK_FLAGS=""
+
+# Install Boost headers
+cd $SRC/
+tar jxf boost_1_74_0.tar.bz2
+cd boost_1_74_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+cp -R boost/ /usr/include/
+
+# Configure Cryptofuzz
+cd $SRC/cryptofuzz/
+python gen_repository.py
+rm extra_options.h
+echo -n '"' >>extra_options.h
+echo -n "--force-module=blst " >>extra_options.h
+echo -n "--operations=" >>extra_options.h
+echo -n "BignumCalc," >>extra_options.h
+echo -n "BignumCalc_Fp2," >>extra_options.h
+echo -n "BignumCalc_Fp12," >>extra_options.h
+echo -n "BLS_BatchVerify," >>extra_options.h
+echo -n "BLS_FinalExp," >>extra_options.h
+echo -n "BLS_GenerateKeyPair," >>extra_options.h
+echo -n "BLS_HashToG1," >>extra_options.h
+echo -n "BLS_HashToG2," >>extra_options.h
+echo -n "BLS_IsG1OnCurve," >>extra_options.h
+echo -n "BLS_IsG2OnCurve," >>extra_options.h
+echo -n "BLS_Pairing," >>extra_options.h
+echo -n "BLS_PrivateToPublic," >>extra_options.h
+echo -n "BLS_PrivateToPublic_G2," >>extra_options.h
+echo -n "BLS_Sign," >>extra_options.h
+echo -n "BLS_Verify," >>extra_options.h
+echo -n "BLS_Compress_G1," >>extra_options.h
+echo -n "BLS_Compress_G2," >>extra_options.h
+echo -n "BLS_Decompress_G1," >>extra_options.h
+echo -n "BLS_Decompress_G2," >>extra_options.h
+echo -n "BLS_G1_Add," >>extra_options.h
+echo -n "BLS_G1_Mul," >>extra_options.h
+echo -n "BLS_G1_IsEq," >>extra_options.h
+echo -n "BLS_G1_Neg," >>extra_options.h
+echo -n "BLS_G2_Add," >>extra_options.h
+echo -n "BLS_G2_Mul," >>extra_options.h
+echo -n "BLS_G2_IsEq," >>extra_options.h
+echo -n "BLS_G2_Neg," >>extra_options.h
+echo -n "BLS_Aggregate_G1", >>extra_options.h
+echo -n "BLS_Aggregate_G2", >>extra_options.h
+echo -n "BignumCalc_Mod_BLS12_381_P," >>extra_options.h
+echo -n "BignumCalc_Mod_BLS12_381_R," >>extra_options.h
+echo -n "KDF_HKDF," >>extra_options.h
+echo -n "Misc " >>extra_options.h
+echo -n "--digests=SHA256 " >>extra_options.h
+echo -n '"' >>extra_options.h
+
+
+if [[ $CFLAGS = *-m32* ]]
+then
+    # Build and install libgmp
+    cd $SRC/
+    mkdir $SRC/libgmp-install
+    tar xf gmp-6.2.1.tar.lz
+    cd $SRC/gmp-6.2.1/
+    autoreconf -ivf
+    if [[ $CFLAGS != *-m32* ]]
+    then
+        ./configure --prefix="$SRC/libgmp-install/" --enable-cxx
+    else
+        setarch i386 ./configure --prefix="$SRC/libgmp-install/" --enable-cxx
+    fi
+    make -j$(nproc)
+    make install
+    export CXXFLAGS="$CXXFLAGS -I $SRC/libgmp-install/include/"
+fi
+
+function build_blst() {
+    if [[ "$SANITIZER" == "memory" ]]
+    then
+        # Patch to disable assembly
+        touch new_no_asm.h
+        echo "#if LIMB_T_BITS==32" >>new_no_asm.h
+        echo "typedef unsigned long long llimb_t;" >>new_no_asm.h
+        echo "#else" >>new_no_asm.h
+        echo "typedef __uint128_t llimb_t;" >>new_no_asm.h
+        echo "#endif" >>new_no_asm.h
+        cat src/no_asm.h >>new_no_asm.h
+        mv new_no_asm.h src/no_asm.h
+
+        CFLAGS="$CFLAGS -D__BLST_NO_ASM__ -D__BLST_PORTABLE__" ./build.sh
+    else
+        ./build.sh
+    fi
+
+    export BLST_LIBBLST_A_PATH=$(realpath libblst.a)
+    export BLST_INCLUDE_PATH=$(realpath bindings/)
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BLST"
+}
+
+# Build blst (normal)
+cp -R $SRC/blst/ $SRC/blst_normal/
+cd $SRC/blst_normal/
+build_blst
+
+# Build Chia
+if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]]
+then
+    # Build and install libsodium
+    cd $SRC/
+    mkdir $SRC/libsodium-install
+    tar zxf libsodium-1.0.18-stable.tar.gz
+    cd $SRC/libsodium-stable/
+    autoreconf -ivf
+    ./configure --prefix="$SRC/libsodium-install/"
+    make -j$(nproc)
+    make install
+    export CXXFLAGS="$CXXFLAGS -I $SRC/libsodium-install/include/"
+    export LINK_FLAGS="$LINK_FLAGS $SRC/libsodium-install/lib/libsodium.a"
+
+    cd $SRC/bls-signatures/
+    mkdir build/
+    cd build/
+    if [[ $CFLAGS = *-m32* ]]
+    then
+        export CHIA_ARCH="X86"
+    else
+        export CHIA_ARCH="X64"
+    fi
+    cmake .. -DBUILD_BLS_PYTHON_BINDINGS=0 -DBUILD_BLS_TESTS=0 -DBUILD_BLS_BENCHMARKS=0 -DARCH=$CHIA_ARCH
+    make -j$(nproc)
+    export CHIA_BLS_LIBBLS_A_PATH=$(realpath src/libbls.a)
+    export CHIA_BLS_LIBRELIC_S_A_PATH=$(realpath _deps/relic-build/lib/librelic_s.a)
+    export CHIA_BLS_LIBSODIUM_A_PATH=$(realpath _deps/sodium-build/libsodium.a)
+    export CHIA_BLS_INCLUDE_PATH=$(realpath ../src/)
+    export CHIA_BLS_RELIC_INCLUDE_PATH_1=$(realpath _deps/relic-build/include/)
+    export CHIA_BLS_RELIC_INCLUDE_PATH_2=$(realpath _deps/relic-src/include/)
+    export LINK_FLAGS="$LINK_FLAGS -lgmp"
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_CHIA_BLS"
+fi
+
+# Build mcl
+if [[ "$SANITIZER" != "memory" ]]
+then
+    cd $SRC/mcl/
+    mkdir build/
+    cd build/
+    if [[ $CFLAGS != *-m32* ]]
+    then
+        cmake .. -DMCL_STATIC_LIB=on
+        export LINK_FLAGS="$LINK_FLAGS -lgmp"
+    else
+        cmake .. -DMCL_STATIC_LIB=on \
+        -DGMP_INCLUDE_DIR="$SRC/libgmp-install/include/" \
+        -DGMP_LIBRARY="$SRC/libgmp-install/lib/libgmp.a" \
+        -DGMP_GMPXX_INCLUDE_DIR="$SRC/libgmp-install/include/" \
+        -DGMP_GMPXX_LIBRARY="$SRC/libgmp-install/lib/libgmpxx.a" \
+        -DMCL_USE_ASM=off
+        export LINK_FLAGS="$LINK_FLAGS $SRC/libgmp-install/lib/libgmp.a"
+    fi
+    make
+    export MCL_INCLUDE_PATH=$(realpath ../include/)
+    export MCL_LIBMCL_A_PATH=$(realpath lib/libmcl.a)
+    export MCL_LIBMCLBN384_A_PATH=$(realpath lib/libmclbn384.a)
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_MCL"
+fi
+
+# Build Botan
+cd $SRC/botan/
+if [[ $CFLAGS != *-m32* ]]
+then
+    ./configure.py --cc-bin=$CXX \
+    --cc-abi-flags="$CXXFLAGS" \
+    --disable-shared \
+    --disable-modules=locking_allocator,x509,tls \
+    --build-targets=static \
+    --without-documentation
+else
+    ./configure.py --cpu=x86_32 \
+    --cc-bin=$CXX \
+    --cc-abi-flags="$CXXFLAGS" \
+    --disable-shared \
+    --disable-modules=locking_allocator,x509,tls \
+    --build-targets=static \
+    --without-documentation
+fi
+make -j$(nproc)
+
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
+export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a"
+export BOTAN_INCLUDE_PATH="$SRC/botan/build/include"
+
+# Build modules
+cd $SRC/cryptofuzz/modules/botan/
+make -B
+
+cd $SRC/cryptofuzz/modules/blst/
+make -B
+
+if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]]
+then
+    cd $SRC/cryptofuzz/modules/chia_bls/
+    make -B
+fi
+
+if [[ "$SANITIZER" != "memory" ]]
+then
+    cd $SRC/cryptofuzz/modules/mcl/
+    make -B
+fi
+
+# Build Cryptofuzz
+cd $SRC/cryptofuzz/
+make -B -j
+
+cp cryptofuzz $OUT/cryptofuzz-bls-signatures
+
+# Build blst (optimized for size)
+cp -R $SRC/blst/ $SRC/blst_optimize_size/
+cd $SRC/blst_optimize_size/
+export CFLAGS="$CFLAGS -D__OPTIMIZE_SIZE__"
+build_blst
+
+cd $SRC/cryptofuzz/modules/blst/
+make -B
+
+# Build Cryptofuzz
+cd $SRC/cryptofuzz/
+rm entry.o; make
+
+cp cryptofuzz $OUT/cryptofuzz-bls-signatures_optimize_size
diff --git a/projects/bls-signatures/project.yaml b/projects/bls-signatures/project.yaml
new file mode 100644
index 0000000..a96f270
--- /dev/null
+++ b/projects/bls-signatures/project.yaml
@@ -0,0 +1,20 @@
+homepage: "https://github.com/supranational/blst"
+language: c++
+primary_contact: "guidovranken@gmail.com"
+main_repo: "https://github.com/supranational/blst.git"
+sanitizers:
+ - address
+ - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+architectures:
+ - x86_64
+ - i386
+auto_ccs:
+ - "kelly@supranational.net"
+ - "diederik.loerakker@ethereum.org"
+ - "hoffmang@chia.net"
+ - "bram@chia.net"
+ - "mariano@chia.net"
+ - "arvid@chia.net"
+ - "bill@chia.net"
diff --git a/projects/boost-json/Dockerfile b/projects/boost-json/Dockerfile
new file mode 100644
index 0000000..5aaa1f6
--- /dev/null
+++ b/projects/boost-json/Dockerfile
@@ -0,0 +1,49 @@
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+#RUN apt-get update && apt-get install -y g++
+
+RUN git clone --depth 1 --single-branch --branch master https://github.com/boostorg/boost.git
+RUN pwd
+RUN ls
+RUN git -C boost submodule update --init libs/json
+RUN git -C boost/libs/json checkout develop
+RUN git -C boost submodule update --init --depth 1 \
+libs/align/ \
+libs/assert \
+libs/config/ \
+libs/container \
+libs/container_hash/ \
+libs/core \
+libs/exception/ \
+libs/headers/ \
+libs/intrusive/ \
+libs/io \
+libs/move/ \
+libs/mp11/ \
+libs/smart_ptr/ \
+libs/static_assert \
+libs/system/ \
+libs/throw_exception/ \
+libs/type_traits/ \
+libs/utility/ \
+tools/boost_install \
+tools/build
+
+WORKDIR boost
+COPY build.sh $SRC/
+
diff --git a/projects/boost-json/build.sh b/projects/boost-json/build.sh
new file mode 100755
index 0000000..75c3a10
--- /dev/null
+++ b/projects/boost-json/build.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -eu
+# Copyright 2017 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+./bootstrap.sh --with-libraries=json
+
+echo "using clang : ossfuzz : $CXX : <compileflags>\"$CXXFLAGS\" <linkflags>\"$CXXFLAGS\" <linkflags>\"${LIB_FUZZING_ENGINE}\" ;" >user-config.jam
+
+./b2 --user-config=user-config.jam --toolset=clang-ossfuzz --prefix=$OUT --with-json link=static install
+
+for i in libs/json/fuzzing/*.cpp; do
+   fuzzer=$(basename $i .cpp)
+   $CXX $CXXFLAGS -pthread libs/json/fuzzing/$fuzzer.cpp -I $OUT/include/ $OUT/lib/*.a $LIB_FUZZING_ENGINE -o $OUT/$fuzzer
+done
+
diff --git a/projects/boost-json/project.yaml b/projects/boost-json/project.yaml
new file mode 100644
index 0000000..43e6325
--- /dev/null
+++ b/projects/boost-json/project.yaml
@@ -0,0 +1,8 @@
+homepage: "http://www.boost.org/"
+language: c++
+primary_contact: "pauldreikossfuzz@gmail.com"
+auto_ccs:  
+   - "vinnie.falco@gmail.com"
+   - "grisumbras@gmail.com"
+   - "pdimov@gmail.com"
+main_repo: 'https://github.com/boostorg/json.git'
diff --git a/projects/boost/Dockerfile b/projects/boost/Dockerfile
index ac2fe37..f05e6bb 100644
--- a/projects/boost/Dockerfile
+++ b/projects/boost/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y g++
+RUN apt-get update && apt-get install -y g++ python
 
 RUN git clone --recursive https://github.com/boostorg/boost.git
 WORKDIR boost
diff --git a/projects/boost/boost_regex_fuzzer.cc b/projects/boost/boost_regex_fuzzer.cc
index 018a04b..dbc5ea8 100644
--- a/projects/boost/boost_regex_fuzzer.cc
+++ b/projects/boost/boost_regex_fuzzer.cc
@@ -1,3 +1,14 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
 // From https://svn.boost.org/trac10/ticket/12818
 // This fuzz target can likely be enhanced to exercise more code.
 // The ideal place for this fuzz target is the boost repository.
@@ -25,16 +36,16 @@
   size_t regex_length = fuzzed_data.ConsumeIntegral<uint8_t>();
   // Second value is regexp string whose length is `regex_length`
   std::string regex_string = fuzzed_data.ConsumeBytesAsString(regex_length);
-  boost::regex e(regex_string);
-  // Last value is the text to be matched
-  std::string text = fuzzed_data.ConsumeRemainingBytesAsString();
+  try {
+    boost::regex e(regex_string);
+    // Last value is the text to be matched
+    std::string text = fuzzed_data.ConsumeRemainingBytesAsString();
 
 #ifdef DEBUG
     std::cout << "Regexp string: " << regex_string << "Size: " << regex_string.size() << std::endl;
     std::cout << "Text: " << text << "Size: " << text.size() << std::endl;
 #endif
 
-  try {
     boost::match_results<std::string::const_iterator> what;
     bool match = boost::regex_match(text, what, e,
                        boost::match_default | boost::match_partial);
diff --git a/projects/boost/build.sh b/projects/boost/build.sh
index b34d55f..37552ed 100755
--- a/projects/boost/build.sh
+++ b/projects/boost/build.sh
@@ -16,7 +16,9 @@
 ################################################################################
 
 # Build boost
-./bootstrap.sh && ./b2 headers
+CXXFLAGS="$CXXFLAGS -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" \
+    ./bootstrap.sh --with-toolset=clang --prefix=/usr;
+./b2 toolset=clang cxxflags="$CXXFLAGS -stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers;
 
 # Very simple build rule, but sufficient here.
 #boost regexp
diff --git a/projects/botan/project.yaml b/projects/botan/project.yaml
index becbd81..7a4c648 100644
--- a/projects/botan/project.yaml
+++ b/projects/botan/project.yaml
@@ -7,6 +7,7 @@
   - "norritt@bytefortress.de"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/randombit/botan.git'
+main_repo: 'https://github.com/randombit/botan.git'
\ No newline at end of file
diff --git a/projects/bs4/Dockerfile b/projects/bs4/Dockerfile
index 9a0de07..9e7454a 100644
--- a/projects/bs4/Dockerfile
+++ b/projects/bs4/Dockerfile
@@ -14,9 +14,9 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
-RUN apt install -y bzr python-lxml python-html5lib
+RUN apt-get install -y bzr python-lxml python-html5lib
 RUN pip3 install 2to3 soupsieve html5lib lxml
 RUN pip3 install bzr+lp:beautifulsoup
 
diff --git a/projects/bs4/bs4_fuzzer.py b/projects/bs4/bs4_fuzzer.py
index 1194261..b512512 100644
--- a/projects/bs4/bs4_fuzzer.py
+++ b/projects/bs4/bs4_fuzzer.py
@@ -14,12 +14,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
 import sys
-import warnings
 import atheris
 
-from bs4 import BeautifulSoup
+with atheris.instrument_imports():
+  import logging
+  import warnings
+  from bs4 import BeautifulSoup
 
 
 try:
@@ -33,6 +34,7 @@
     pass
 
 
+@atheris.instrument_func
 def TestOneInput(data):
   """TestOneInput gets random data from the fuzzer, and throws it at bs4."""
   if len(data) < 1:
diff --git a/projects/bs4/build.sh b/projects/bs4/build.sh
index 111be46..2fec546 100644
--- a/projects/bs4/build.sh
+++ b/projects/bs4/build.sh
@@ -29,5 +29,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/caddy/Dockerfile b/projects/caddy/Dockerfile
new file mode 100644
index 0000000..95949c0
--- /dev/null
+++ b/projects/caddy/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+
+RUN git clone --depth 1  https://github.com/caddyserver/caddy $GOPATH/src/github.com/caddyserver/caddy/v2
+
+COPY build.sh $SRC/
+WORKDIR $SRC/caddy
diff --git a/projects/caddy/build.sh b/projects/caddy/build.sh
new file mode 100644
index 0000000..add1a06
--- /dev/null
+++ b/projects/caddy/build.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd "$GOPATH"/src/github.com/caddyserver/caddy/v2
+
+find . -name '*_fuzz.go' | while read -r target
+do
+# Arguments are :
+#     path of the package with the fuzz target
+#     name of the fuzz function
+#     name of the fuzzer to be built
+#     optional tag to be used by go build and such
+
+    fuzzed_func=$(grep -o "Fuzz[a-zA-Z]\+" "$target")
+    fuzzer_name=$(echo "$fuzzed_func" | sed -E 's/([A-Z])/-\L\1/g' | sed 's/^-//')
+    # find the relative directory and remove the first `.` (`./` is removed for root)
+    target_dir=$(dirname "$target"); target_dir="${target_dir//.}";
+    target_corpus_name="${fuzzer_name}_seed_corpus.zip"
+
+    curl -s -f -O "https://raw.githubusercontent.com/caddyserver/caddy/fuzz-seed-corpus/${target_corpus_name}" || true
+    compile_go_fuzzer github.com/caddyserver/caddy/v2"$target_dir" "$fuzzed_func" "$fuzzer_name" gofuzz
+done
diff --git a/projects/caddy/project.yaml b/projects/caddy/project.yaml
new file mode 100644
index 0000000..d229dba
--- /dev/null
+++ b/projects/caddy/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://caddyserver.com/"
+language: go
+primary_contact: "msaa1990@gmail.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: "https://github.com/caddyserver/caddy.git"
\ No newline at end of file
diff --git a/projects/cairo/Dockerfile b/projects/cairo/Dockerfile
index 7463bbd..671fa74 100644
--- a/projects/cairo/Dockerfile
+++ b/projects/cairo/Dockerfile
@@ -14,8 +14,8 @@
 #
 ################################################################################
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y python3-pip gtk-doc-tools libffi-dev
-RUN pip3 install -U meson==0.55.3 ninja
+RUN apt-get update && apt-get install -y python3-pip gtk-doc-tools libffi-dev autotools-dev libtool gperf
+RUN pip3 install -U meson==0.56.0 ninja
 
 RUN git clone --depth 1 git://git.sv.nongnu.org/freetype/freetype2.git
 ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.64/glib-2.64.2.tar.xz $SRC
diff --git a/projects/capnproto/Dockerfile b/projects/capnproto/Dockerfile
index dffaa45..b95cda7 100644
--- a/projects/capnproto/Dockerfile
+++ b/projects/capnproto/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y cmake zlib1g-dev
+RUN apt-get update && apt-get install -y autoconf automake libtool zlib1g-dev
 RUN git clone --depth 1 https://github.com/capnproto/capnproto
 WORKDIR $SRC/capnproto
 COPY build.sh $SRC/
diff --git a/projects/capnproto/build.sh b/projects/capnproto/build.sh
index 176418d..8bb8063 100755
--- a/projects/capnproto/build.sh
+++ b/projects/capnproto/build.sh
@@ -16,8 +16,9 @@
 ################################################################################
 
 # build project
-mkdir build
-cd build
-cmake -DBUILD_SHARED_LIBS=OFF ..
+cd c++
+autoreconf -i
+./configure --disable-shared
 make -j$(nproc)
-cp c++/src/capnp/*fuzzer* $OUT/
+make -j$(nproc) capnp-llvm-fuzzer-testcase
+cp *fuzzer* $OUT/
diff --git a/projects/capnproto/project.yaml b/projects/capnproto/project.yaml
index e8cffba..5d9f841 100644
--- a/projects/capnproto/project.yaml
+++ b/projects/capnproto/project.yaml
@@ -3,6 +3,8 @@
 primary_contact: "security@sandstorm.io"
 auto_ccs:
   - "p.antoine@catenacyber.fr"
+  - "kenton@cloudflare.com"
 sanitizers:
   - address
+  - undefined
 main_repo: 'https://github.com/capnproto/capnproto'
diff --git a/projects/cascadia/Dockerfile b/projects/cascadia/Dockerfile
index 094b5e1..6f4f5d7 100644
--- a/projects/cascadia/Dockerfile
+++ b/projects/cascadia/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone https://github.com/andybalholm/cascadia
 
 COPY build.sh $SRC/
diff --git a/projects/casync/project.yaml b/projects/casync/project.yaml
index e2d38b8..e664b04 100644
--- a/projects/casync/project.yaml
+++ b/projects/casync/project.yaml
@@ -4,9 +4,10 @@
 sanitizers:
   - address
   - undefined
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 auto_ccs:
   - zbyszek@in.waw.pl
   - poettering@gmail.com
   - fsumsal@redhat.com
-main_repo: 'https://github.com/systemd/casync'
+main_repo: 'https://github.com/systemd/casync'
\ No newline at end of file
diff --git a/projects/cel-cpp/Dockerfile b/projects/cel-cpp/Dockerfile
index 6c4b67e..a95e740 100644
--- a/projects/cel-cpp/Dockerfile
+++ b/projects/cel-cpp/Dockerfile
@@ -16,6 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 
+RUN apt-get update && apt-get install python openjdk-11-jdk -y
 RUN git clone --depth 1 https://github.com/google/cel-cpp/
 COPY build.sh $SRC/
 RUN mkdir $SRC/cel-cpp/fuzz/
@@ -23,5 +24,5 @@
 COPY WORKSPACE .bazelrc $SRC/
 RUN cat WORKSPACE >> $SRC/cel-cpp/WORKSPACE
 RUN cat .bazelrc >> $SRC/cel-cpp/.bazelrc
-RUN echo "4.0.0" > $SRC/cel-cpp/.bazelversion
+RUN echo "4.1.0" > $SRC/cel-cpp/.bazelversion
 WORKDIR $SRC/cel-cpp
diff --git a/projects/cel-cpp/build.sh b/projects/cel-cpp/build.sh
index 5a6315a..b204d1c 100755
--- a/projects/cel-cpp/build.sh
+++ b/projects/cel-cpp/build.sh
@@ -15,18 +15,4 @@
 #
 ################################################################################
 
-declare -r QUERY='
-    let all_fuzz_tests = attr(tags, "fuzz-test", "//...") in
-    $all_fuzz_tests - attr(tags, "no-oss-fuzz", $all_fuzz_tests)
-'
-
-declare -r PACKAGE_SUFFIX="_oss_fuzz"
-declare -r OSS_FUZZ_TESTS="$(bazel query "${QUERY}" | sed "s/$/${PACKAGE_SUFFIX}/")"
-
-bazel build -c opt --config=oss-fuzz --linkopt=-lc++ \
-    --action_env=CC="${CC}" --action_env=CXX="${CXX}" \
-    ${OSS_FUZZ_TESTS[*]}
-
-for oss_fuzz_archive in $(find bazel-bin/ -name "*${PACKAGE_SUFFIX}.tar"); do
-    tar -xvf "${oss_fuzz_archive}" -C "${OUT}"
-done
+bazel_build_fuzz_tests
diff --git a/projects/cel-cpp/fuzz_parse.cc b/projects/cel-cpp/fuzz_parse.cc
index f4755d3..8aaba0b 100644
--- a/projects/cel-cpp/fuzz_parse.cc
+++ b/projects/cel-cpp/fuzz_parse.cc
@@ -16,14 +16,17 @@
 
 #include <string>
 
+#include "parser/options.h"
 #include "parser/parser.h"
 
 #define MAX_RECURSION 0x100
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     std::string str (reinterpret_cast<const char*>(data), size);
+    google::api::expr::parser::ParserOptions options;
+    options.max_recursion_depth = MAX_RECURSION;
     try {
-        auto parse_status = google::api::expr::parser::Parse(str, "fuzzinput", MAX_RECURSION);
+        auto parse_status = google::api::expr::parser::Parse(str, "fuzzinput", options);
         if (!parse_status.ok()) {
             parse_status.status().message();
         }
diff --git a/projects/cel-cpp/project.yaml b/projects/cel-cpp/project.yaml
index ad4bf90..14fb2f1 100644
--- a/projects/cel-cpp/project.yaml
+++ b/projects/cel-cpp/project.yaml
@@ -7,5 +7,6 @@
 
 sanitizers:
 - address
-- memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
 main_repo: 'https://github.com/google/cel-cpp'
diff --git a/projects/cel-go/Dockerfile b/projects/cel-go/Dockerfile
new file mode 100644
index 0000000..cac4a1e
--- /dev/null
+++ b/projects/cel-go/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/google/cel-go
+
+RUN apt-get update && apt-get install -y protobuf-compiler libprotobuf-dev binutils cmake \
+   ninja-build liblzma-dev libz-dev pkg-config autoconf libtool
+RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git
+RUN mkdir LPM; \
+  cd LPM; \
+  cmake $SRC/libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release; \
+  ninja;
+
+RUN git clone --depth 1 https://github.com/mdempsky/go114-fuzz-build.git
+
+RUN go get google.golang.org/protobuf/cmd/protoc-gen-go
+
+COPY go-lpm.cc $SRC/
+
+COPY fuzz*.go $SRC/cel-go/cel/
+COPY build.sh $SRC/
+COPY *.proto $SRC/
+WORKDIR $SRC/cel-go
diff --git a/projects/cel-go/build.sh b/projects/cel-go/build.sh
new file mode 100755
index 0000000..f27842b
--- /dev/null
+++ b/projects/cel-go/build.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir fuzzlpm
+$SRC/LPM/external.protobuf/bin/protoc --cpp_out=fuzzlpm/ -I$SRC/ $SRC/cel-go-lpm.proto
+
+$CXX $CXXFLAGS -c -I fuzzlpm/ -I $SRC/LPM/external.protobuf/include fuzzlpm/cel-go-lpm.pb.cc
+$CXX $CXXFLAGS -c -I. -I ../libprotobuf-mutator/ -I $SRC/LPM/external.protobuf/include $SRC/go-lpm.cc
+
+(
+cd $SRC/go114-fuzz-build
+sed -i -e 's/LLVMFuzzerTestOneInput/LPMFuzzerTestOneInput/' main.go
+go build
+)
+
+$SRC/LPM/external.protobuf/bin/protoc --go_out=fuzzlpm/ -I$SRC/ $SRC/cel-go-lpm.proto
+cp fuzzlpm/github.com/google/cel-go/cel/*.pb.go cel/
+
+$SRC/go114-fuzz-build/go114-fuzz-build -func FuzzEval -o fuzz_lpm.a github.com/google/cel-go/cel
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE cel-go-lpm.pb.o go-lpm.o fuzz_lpm.a  $SRC/LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a $SRC/LPM/src/libprotobuf-mutator.a $SRC/LPM/external.protobuf/lib/libprotobuf.a -o $OUT/fuzz_lpm
+
+compile_go_fuzzer github.com/google/cel-go/cel FuzzCompile fuzz_compile
diff --git a/projects/cel-go/cel-go-lpm.proto b/projects/cel-go/cel-go-lpm.proto
new file mode 100644
index 0000000..5bcfeeb
--- /dev/null
+++ b/projects/cel-go/cel-go-lpm.proto
@@ -0,0 +1,25 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+syntax = "proto3";
+package celgolpm;
+
+option go_package = "github.com/google/cel-go/cel";
+
+message FuzzVariables {
+  string expr = 1;
+  map<string,string> inputs = 2;
+}
diff --git a/projects/cel-go/fuzz_compile.go b/projects/cel-go/fuzz_compile.go
new file mode 100644
index 0000000..a7398da
--- /dev/null
+++ b/projects/cel-go/fuzz_compile.go
@@ -0,0 +1,18 @@
+package cel
+
+func FuzzCompile(data []byte) int {
+	env, err := NewEnv()
+	if err != nil {
+		panic("impossible to create env")
+	}
+	ast, issues := env.Compile(string(data))
+	if issues != nil && issues.Err() != nil {
+		return 0
+	}
+	_, err = env.Program(ast)
+	if err != nil {
+		return 0
+	}
+
+	return 1
+}
diff --git a/projects/cel-go/fuzz_eval.go b/projects/cel-go/fuzz_eval.go
new file mode 100644
index 0000000..8b2764c
--- /dev/null
+++ b/projects/cel-go/fuzz_eval.go
@@ -0,0 +1,39 @@
+package cel
+
+import (
+	"github.com/golang/protobuf/proto"
+
+	"github.com/google/cel-go/checker/decls"
+	exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+)
+
+func FuzzEval(data []byte) int {
+	gen := &FuzzVariables{}
+	err := proto.Unmarshal(data, gen)
+	if err != nil {
+		panic("Failed to unmarshal LPM generated variables")
+	}
+
+	declares := make([]*exprpb.Decl, 0, len(gen.Inputs))
+	for k, _ := range gen.Inputs {
+		declares = append(declares, decls.NewVar(k, decls.String))
+	}
+	env, err := NewEnv(Declarations(declares...))
+	if err != nil {
+		panic("impossible to create env")
+	}
+
+	ast, issues := env.Compile(gen.Expr)
+	if issues != nil && issues.Err() != nil {
+		return 0
+	}
+	prg, err := env.Program(ast)
+	if err != nil {
+		return 0
+	}
+	//fmt.Printf("loltry %#+v\n", gen)
+
+	_, _, err = prg.Eval(gen.Inputs)
+
+	return 1
+}
diff --git a/projects/cel-go/go-lpm.cc b/projects/cel-go/go-lpm.cc
new file mode 100644
index 0000000..9a341bc
--- /dev/null
+++ b/projects/cel-go/go-lpm.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include "fuzzlpm/cel-go-lpm.pb.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+extern "C" void  LPMFuzzerTestOneInput(const uint8_t *buffer, size_t size);
+
+DEFINE_PROTO_FUZZER(const celgolpm::FuzzVariables& input) {
+    size_t size = input.ByteSizeLong();
+    if (size > 0) {
+        uint8_t *buffer = (uint8_t *) malloc(size);
+        //printf("debugs %d: %s\n", size, input.DebugString().c_str());
+        input.SerializeToArray((uint8_t *) buffer, size);
+        LPMFuzzerTestOneInput(buffer, size);
+        free(buffer);
+    }
+}
diff --git a/projects/cel-go/project.yaml b/projects/cel-go/project.yaml
new file mode 100644
index 0000000..ad7f632
--- /dev/null
+++ b/projects/cel-go/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://opensource.google/projects/cel"
+primary_contact: "tswadell@google.com"
+auto_ccs:
+  - "p.antoine@catenacyber.fr"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: 'https://github.com/google/cel-go'
diff --git a/projects/cfengine/Dockerfile b/projects/cfengine/Dockerfile
new file mode 100644
index 0000000..24b70d8
--- /dev/null
+++ b/projects/cfengine/Dockerfile
@@ -0,0 +1,26 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y \
+    build-essential autoconf automake libssl-dev \
+    libpcre3 libpcre3-dev bison libbison-dev \
+    libacl1 libacl1-dev libpq-dev lmdb-utils \
+    liblmdb-dev libpam0g-dev flex libtool
+
+RUN git clone --depth 1 https://github.com/cfengine/core --recursive
+WORKDIR core
+COPY build.sh string_fuzzer.c $SRC/
diff --git a/projects/cfengine/build.sh b/projects/cfengine/build.sh
new file mode 100755
index 0000000..4a2d542
--- /dev/null
+++ b/projects/cfengine/build.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+./autogen.sh
+./configure
+make V=1 -j$(nproc)
+
+cd libpromises
+mv $SRC/string_fuzzer.c .
+find . -name "*.o" -exec ar rcs fuzz_lib.a {} \;
+$CC $CFLAGS -I./ -c string_fuzzer.c -o string_fuzzer.o
+$CC $CXXFLAGS $LIB_FUZZING_ENGINE string_fuzzer.o \
+    -o $OUT/string_fuzzer fuzz_lib.a \
+    ../libntech/libutils/.libs/libutils.a
diff --git a/projects/cfengine/project.yaml b/projects/cfengine/project.yaml
new file mode 100644
index 0000000..4db793d
--- /dev/null
+++ b/projects/cfengine/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/cfengine/core"
+main_repo: "https://github.com/cfengine/core"
+language: c++
+primary_contact: "vratislav.podzimek@northern.tech"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
diff --git a/projects/cfengine/string_fuzzer.c b/projects/cfengine/string_fuzzer.c
new file mode 100644
index 0000000..b7d5cfb
--- /dev/null
+++ b/projects/cfengine/string_fuzzer.c
@@ -0,0 +1,40 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string_expressions.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+    if(size<4) {
+        return 0;
+    }
+    for (int i=0; i<size; i++) {
+        if(data[i]==0) {
+            return 0;
+        }
+    }
+    char *new_str = (char *)malloc(size+1);
+    if (new_str == NULL){
+        return 0;
+    }
+    memcpy(new_str, data, size);
+    new_str[size] = '\0';
+    int len = strlen(new_str);
+
+    StringParseResult res = ParseStringExpression(new_str, 0, len);
+
+    FreeStringExpression(res.result);
+    free(new_str);
+    return 0;
+}
diff --git a/projects/cilium/Dockerfile b/projects/cilium/Dockerfile
index 89f2f00..e263f36 100644
--- a/projects/cilium/Dockerfile
+++ b/projects/cilium/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN apt-get update && apt-get install -y wget
 RUN wget https://raw.githubusercontent.com/google/AFL/master/dictionaries/json.dict -O $OUT/fuzz.dict
 
diff --git a/projects/cilium/project.yaml b/projects/cilium/project.yaml
index 0d75f44..ff788e2 100644
--- a/projects/cilium/project.yaml
+++ b/projects/cilium/project.yaml
@@ -2,9 +2,13 @@
 language: go
 primary_contact: "security@cilium.io"
 auto_ccs:
-- "tom@isovalent.com"
+- "andre@isovalent.com"
+- "joe@isovalent.com"
 - "natalia@isovalent.com"
+- "robin@isovalent.com"
+- "tom.payne@isovalent.com"
 - "adam@adalogics.com"
+main_repo: "https://github.com/cilium/cilium.git"
 fuzzing_engines:
 - libfuzzer
 sanitizers:
diff --git a/projects/civetweb/project.yaml b/projects/civetweb/project.yaml
index f191b2a..f09c3f8 100755
--- a/projects/civetweb/project.yaml
+++ b/projects/civetweb/project.yaml
@@ -4,7 +4,6 @@
 fuzzing_engines:
   - libfuzzer
   - honggfuzz
-  - dataflow
 auto_ccs:
   - "xt4ubq@gmail.com"
   - "david@adalogics.com"
diff --git a/projects/clamav/Dockerfile b/projects/clamav/Dockerfile
index 0d4cc03..6295958 100644
--- a/projects/clamav/Dockerfile
+++ b/projects/clamav/Dockerfile
@@ -28,7 +28,7 @@
 
 RUN mkdir /mussels
 RUN cd ${SRC}/clamav-mussels-cookbook && \
-    msl build clamav_deps -t host-static -w /mussels/work -i /mussels/install
+    msl build libclamav_deps -t host-static -w /mussels/work -i /mussels/install
 
 # Collect clamav source & fuzz corpus
 RUN git clone --depth 1 https://github.com/Cisco-Talos/clamav-devel.git
diff --git a/projects/clamav/build.sh b/projects/clamav/build.sh
index 1f7e902..826021b 100755
--- a/projects/clamav/build.sh
+++ b/projects/clamav/build.sh
@@ -42,7 +42,7 @@
     -DOPENSSL_CRYPTO_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libcrypto.a"    \
     -DOPENSSL_SSL_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libssl.a"          \
     -DZLIB_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libssl.a"                 \
-    -DLIBXML2_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include"               \
+    -DLIBXML2_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include/libxml2"       \
     -DLIBXML2_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libxml2.a"             \
     -DPCRE2_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include"                 \
     -DPCRE2_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libpcre2-8.a"            \
diff --git a/projects/clib/Dockerfile b/projects/clib/Dockerfile
index 92e1490..d46f752 100644
--- a/projects/clib/Dockerfile
+++ b/projects/clib/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make cmake ninja libcurl4-gnutls-dev -qq
+RUN apt-get update && apt-get install -y make cmake libcurl4-gnutls-dev -qq
 RUN git clone https://github.com/clibs/clib
 WORKDIR $SRC/
 COPY build.sh $SRC/
diff --git a/projects/clib/build.sh b/projects/clib/build.sh
index c48ba9d..166ee45 100644
--- a/projects/clib/build.sh
+++ b/projects/clib/build.sh
@@ -29,8 +29,10 @@
 	-I./deps/asprintf
 
 $CC $CFLAGS $LIB_FUZZING_ENGINE fuzz_manifest.o \
-	-o $OUT/fuzz_manifest src/common/clib-package.c \
+	-o $OUT/fuzz_manifest src/common/clib-settings.c src/common/clib-package.c \
 	src/common/clib-cache.c src/clib-configure.c \
 	-I./deps/asprintf -I./deps -I./asprintf \
 	fuzz_lib.a -L/usr/lib/x86_64-linux-gnu -lcurl
 
+echo "[libfuzzer]" > $OUT/fuzz_manifest.options
+echo "detect_leaks=0" >> $OUT/fuzz_manifest.options
diff --git a/projects/clickhouse/Dockerfile b/projects/clickhouse/Dockerfile
new file mode 100644
index 0000000..cd835be
--- /dev/null
+++ b/projects/clickhouse/Dockerfile
@@ -0,0 +1,40 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN apt-get update -y \
+    && env DEBIAN_FRONTEND=noninteractive \
+        apt-get install --yes --no-install-recommends \
+            bash \
+            wget \
+            curl \
+            ccache \
+            expect \
+            ninja-build \
+            perl \
+            pkg-config \
+            python3 \
+            python3-lxml \
+            python3-requests \
+            python3-termcolor \
+            sudo \
+            tzdata
+
+RUN git clone -j 8 --recursive https://github.com/ClickHouse/ClickHouse $SRC/ClickHouse
+WORKDIR $SRC/ClickHouse
+
+COPY build.sh $SRC/
diff --git a/projects/clickhouse/build.sh b/projects/clickhouse/build.sh
new file mode 100755
index 0000000..a0415f0
--- /dev/null
+++ b/projects/clickhouse/build.sh
@@ -0,0 +1,107 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir $SRC/ClickHouse/build
+cd $SRC/ClickHouse/build
+
+sed -i -e '/warnings.cmake)/d' $SRC/ClickHouse/CMakeLists.txt
+
+# It will be hard to maintain any compilation fails (if any) in two repositories.
+# Also ClickHouse won't compile without this.
+# It is very strange, because we have as many warnings as you could imagine.
+sed -i -e 's/add_warning(/no_warning(/g' $SRC/ClickHouse/CMakeLists.txt
+
+# ClickHouse uses libcxx from contrib.
+# Enabling this manually will cause duplicate symbols at linker stage.
+CXXFLAGS=${CXXFLAGS//-stdlib=libc++/}
+
+CLICKHOUSE_CMAKE_FLAGS=(
+    "-DCMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache"
+    "-DCMAKE_C_COMPILER=$CC"
+    "-DCMAKE_CXX_COMPILER=$CXX"
+    "-DCMAKE_BUILD_TYPE=RelWithDebInfo"
+    "-DLIB_FUZZING_ENGINE:STRING=$LIB_FUZZING_ENGINE"
+    "-DENABLE_EMBEDDED_COMPILER=0"
+    "-DENABLE_THINLTO=0"
+    "-DENABLE_TESTS=0"
+    "-DENABLE_EXAMPLES=0"
+    "-DENABLE_UTILS=0"
+    "-DENABLE_JEMALLOC=0"
+    "-DENABLE_FUZZING=1"
+    "-DENABLE_CLICKHOUSE_ODBC_BRIDGE=OFF"
+    "-DENABLE_LIBRARIES=0"
+    "-DENABLE_SSL=1"
+    "-DUSE_INTERNAL_SSL_LIBRARY=1"
+    "-DUSE_UNWIND=ON"
+    "-DGLIBC_COMPATIBILITY=OFF"
+)
+
+if [ "$SANITIZER" = "coverage" ]; then
+    cmake  -G Ninja $SRC/ClickHouse ${CLICKHOUSE_CMAKE_FLAGS[@]} -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_C_FLAGS="$CFLAGS" -DWITH_COVERAGE=1
+else
+    cmake  -G Ninja $SRC/ClickHouse ${CLICKHOUSE_CMAKE_FLAGS[@]} -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_C_FLAGS="$CFLAGS" -DWITH_COVERAGE=1 -DSANITIZE=$SANITIZER
+fi
+
+NUM_JOBS=$(($(nproc || grep -c ^processor /proc/cpuinfo) / 2))
+
+TARGETS=$(find $SRC/ClickHouse/src -name '*_fuzzer.cpp' -execdir basename {} .cpp ';' | tr '\n' ' ')
+
+for FUZZER_TARGET in $TARGETS
+do
+    ninja -j $NUM_JOBS $FUZZER_TARGET
+    # Find this binary in build directory and strip it
+    TEMP=$(find $SRC/ClickHouse/build -name $FUZZER_TARGET)
+    strip --strip-unneeded $TEMP
+done
+
+# copy out fuzzer binaries
+find $SRC/ClickHouse/build -name '*_fuzzer' -exec cp -v '{}' $OUT ';'
+
+# copy out fuzzer options and dictionaries
+cp $SRC/ClickHouse/tests/fuzz/*.dict $OUT/
+cp $SRC/ClickHouse/tests/fuzz/*.options $OUT/
+
+# prepare corpus dirs
+mkdir $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/
+mkdir $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/
+mkdir $SRC/ClickHouse/tests/fuzz/create_parser_fuzzer.in/
+
+# prepare corpus
+cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/
+cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/
+cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/create_parser_fuzzer.in/
+cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/
+cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/
+cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/create_parser_fuzzer.in/
+
+# copy out corpus
+cd $SRC/ClickHouse/tests/fuzz
+for dir in *_fuzzer.in; do
+    fuzzer=$(basename $dir .in)
+    zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${dir}/"
+done
+
+# copy sources for code coverage if required
+if [ "$SANITIZER" = "coverage" ]; then
+    mkdir -p $OUT/src/ClickHouse/
+    cp -rL --parents $SRC/ClickHouse/src $OUT
+    cp -rL --parents $SRC/ClickHouse/base $OUT
+    cp -rL --parents $SRC/ClickHouse/programs $OUT
+fi
+
+# Just check binaries size
+BINARIES_SIZE=$(find $SRC/ClickHouse/build -name '*_fuzzer' -exec du -sh '{}' ';')
diff --git a/projects/clickhouse/project.yaml b/projects/clickhouse/project.yaml
index 9c0c7cf..9e505f2 100644
--- a/projects/clickhouse/project.yaml
+++ b/projects/clickhouse/project.yaml
@@ -1,6 +1,18 @@
 homepage: "https://clickhouse.tech/"
 language: c++
-primary_contact: "clickhouse-feedback@yandex-team.com"
+primary_contact: "clickhouse-security@yandex-team.com"
 auto_ccs:
  - "security@yandex-team.com"
  - "kyprizel@gmail.com"
+ - "jakalletti@gmail.com"
+ - "man2gm@gmail.com"
+ - "kochetovnicolai@gmail.com"
+ - "hq.zero.iq@gmail.com"
+ - "pn.cheremushkin@gmail.com"
+sanitizers:
+ - address
+ - memory
+ - undefined
+fuzzing_engines:
+ - libfuzzer
+main_repo: 'https://github.com/ClickHouse/ClickHouse.git'
diff --git a/projects/cmake/project.yaml b/projects/cmake/project.yaml
index 8ab3533..17c5b3e 100644
--- a/projects/cmake/project.yaml
+++ b/projects/cmake/project.yaml
@@ -7,4 +7,5 @@
 sanitizers:
   - address
   - undefined
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
diff --git a/projects/containerd/Dockerfile b/projects/containerd/Dockerfile
new file mode 100644
index 0000000..7ae4246
--- /dev/null
+++ b/projects/containerd/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN apt-get update && apt-get install -y btrfs-progs libc-dev pkg-config libseccomp-dev gcc wget libbtrfs-dev
+RUN git clone --depth 1 https://github.com/containerd/containerd
+COPY build.sh $SRC/
+WORKDIR $SRC/containerd
diff --git a/projects/containerd/build.sh b/projects/containerd/build.sh
new file mode 100644
index 0000000..e5a1e6b
--- /dev/null
+++ b/projects/containerd/build.sh
@@ -0,0 +1,19 @@
+#/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+$SRC/containerd/contrib/fuzz/oss_fuzz_build.sh
+
diff --git a/projects/containerd/project.yaml b/projects/containerd/project.yaml
new file mode 100644
index 0000000..4875cd6
--- /dev/null
+++ b/projects/containerd/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/containerd/containerd"
+main_repo: "https://github.com/containerd/containerd"
+primary_contact: "security@containerd.io"
+auto_ccs :
+  - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/cosign/Dockerfile b/projects/cosign/Dockerfile
index f0282dd..bb09492 100644
--- a/projects/cosign/Dockerfile
+++ b/projects/cosign/Dockerfile
@@ -14,7 +14,8 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN apt-get update && apt-get install -y pkg-config libpcsclite-dev
 RUN git clone --depth 1 https://github.com/sigstore/cosign
 
 COPY build.sh $SRC/
diff --git a/projects/cosmos-sdk/Dockerfile b/projects/cosmos-sdk/Dockerfile
new file mode 100644
index 0000000..0e5fe8b
--- /dev/null
+++ b/projects/cosmos-sdk/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --single-branch --branch fuzz-packages https://github.com/cosmos/cosmos-sdk
+
+COPY build.sh $SRC
+WORKDIR $SRC/cosmos-sdk
diff --git a/projects/cosmos-sdk/build.sh b/projects/cosmos-sdk/build.sh
new file mode 100755
index 0000000..a865114
--- /dev/null
+++ b/projects/cosmos-sdk/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+bash -x ./fuzz/oss-fuzz-build.sh
diff --git a/projects/cosmos-sdk/project.yaml b/projects/cosmos-sdk/project.yaml
new file mode 100644
index 0000000..fbe2cd1
--- /dev/null
+++ b/projects/cosmos-sdk/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/cosmos/cosmos-sdk"
+primary_contact: "fuzzing@orijtech.com"
+auto_ccs:
+  - emmanuel@orijtech.com
+  - cuong@orijtech.com
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: "https://github.com/cosmos/cosmos-sdk"
diff --git a/projects/cpp-httplib/project.yaml b/projects/cpp-httplib/project.yaml
index 0c90fa0..9043e40 100644
--- a/projects/cpp-httplib/project.yaml
+++ b/projects/cpp-httplib/project.yaml
@@ -9,7 +9,7 @@
   - "ankitlohia@google.com"
 sanitizers:
   - address
-  - dataflow
   - undefined
-  - memory
-main_repo: 'https://github.com/yhirose/cpp-httplib.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: 'https://github.com/yhirose/cpp-httplib.git'
\ No newline at end of file
diff --git a/projects/cpython3/Dockerfile b/projects/cpython3/Dockerfile
index 6ca60d4..972ed6f 100644
--- a/projects/cpython3/Dockerfile
+++ b/projects/cpython3/Dockerfile
@@ -1,3 +1,18 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
 FROM gcr.io/oss-fuzz-base/base-builder
 
 RUN apt-get update
diff --git a/projects/cpython3/project.yaml b/projects/cpython3/project.yaml
index 7edfd24..e454e36 100644
--- a/projects/cpython3/project.yaml
+++ b/projects/cpython3/project.yaml
@@ -6,5 +6,6 @@
  - "ammar@ammaraskar.com"
 sanitizers:
  - address
- - memory
- - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+ - undefined
\ No newline at end of file
diff --git a/projects/cras/Dockerfile b/projects/cras/Dockerfile
index 71b2b12..3a533f6 100644
--- a/projects/cras/Dockerfile
+++ b/projects/cras/Dockerfile
@@ -19,7 +19,7 @@
 ################################################################################
 # Defines a docker image that can build cras fuzzers.
 #
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN apt-get -y update && \
       apt-get install -y \
@@ -40,6 +40,7 @@
       libtool \
       libudev-dev \
       wget \
+      vim \
       zip
 RUN apt-get clean
 RUN cd /tmp && git clone https://github.com/ndevilla/iniparser.git && \
diff --git a/projects/cras/build.sh b/projects/cras/build.sh
index 84f50b1..410ade7 100755
--- a/projects/cras/build.sh
+++ b/projects/cras/build.sh
@@ -44,3 +44,5 @@
 
 zip -j ${OUT}/rclient_message_corpus.zip ${SRC}/adhd/cras/src/fuzz/corpus/*
 cp "${SRC}/adhd/cras/src/fuzz/cras_hfp_slc.dict" "${OUT}/cras_hfp_slc.dict"
+# Add *.rs soft link for coverage build
+ln -s ${SRC}/adhd/cras/src/server/rust/src/* ${SRC}
diff --git a/projects/cras/project.yaml b/projects/cras/project.yaml
index 330b025..3e0c9f6 100644
--- a/projects/cras/project.yaml
+++ b/projects/cras/project.yaml
@@ -1,12 +1,16 @@
 homepage: "https://www.chromium.org"
 language: c++
-primary_contact: "dgreid@chromium.org"
+primary_contact: "paulhsia@chromium.org"
 auto_ccs:
   - "hychao@chromium.org"
   - "cychiang@chromium.org"
-  - "paulhsia@chromium.org"
   - "yuhsuan@chromium.org"
   - "enshuo@chromium.org"
-  - "tzungbi@chromium.org"
   - "cujomalainey@chromium.org"
+  - "benzh@chromium.org"
+  - "judyhsiao@chromium.org"
+  - "johnylin@chromium.org"
+  - "aaronyu@chromium.org"
+  - "hunghsienchen@chromium.org"
+builds_per_day: 2
 main_repo: 'https://chromium.googlesource.com/chromiumos/third_party/adhd'
diff --git a/projects/cryptofuzz/Dockerfile b/projects/cryptofuzz/Dockerfile
index 7ed5d42..1a1cb9a 100644
--- a/projects/cryptofuzz/Dockerfile
+++ b/projects/cryptofuzz/Dockerfile
@@ -14,14 +14,13 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+ENV GOPATH /root/go
+ENV PATH $PATH:/root/.go/bin:$GOPATH/bin
+RUN install_go.sh
 
 RUN apt-get update && \
-    apt-get install -y apt-transport-https ca-certificates gnupg software-properties-common wget && \
-    wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add - && \
-    apt-add-repository 'deb https://apt.kitware.com/ubuntu/ xenial main' && \
-    apt-get update && \
-    apt-get install -y software-properties-common python-software-properties make autoconf automake libtool build-essential cmake mercurial gyp ninja-build zlib1g-dev libsqlite3-dev bison flex texinfo
+    apt-get install -y software-properties-common wget make autoconf automake libtool build-essential cmake mercurial gyp ninja-build zlib1g-dev libsqlite3-dev bison flex texinfo
 
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
@@ -36,15 +35,14 @@
 RUN git clone --depth 1 https://github.com/google/cityhash.git
 RUN git clone --depth 1 https://github.com/randombit/botan.git
 RUN git clone --depth 1 https://github.com/wolfSSL/wolfssl.git
-RUN git clone --depth 1 https://github.com/ARMmbed/mbedtls.git
+RUN git clone --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls.git
 RUN hg clone https://hg.mozilla.org/projects/nspr
-RUN hg clone https://hg.mozilla.org/projects/nss
+#RUN hg clone https://hg.mozilla.org/projects/nss
 RUN git clone --depth 1 https://github.com/jedisct1/libsodium.git
 RUN git clone --depth 1 https://github.com/libtom/libtomcrypt.git
-RUN git clone --depth 1 https://github.com/microsoft/SymCrypt.git
-RUN git clone --depth 1 https://git.lysator.liu.se/nettle/nettle
+#RUN git clone --depth 1 https://github.com/microsoft/SymCrypt.git
 RUN hg clone https://gmplib.org/repo/gmp/ libgmp/
-RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.0.tar.gz
+RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.1.tar.gz
 RUN git clone --depth 1 https://github.com/indutny/bn.js.git
 RUN git clone --depth 1 https://github.com/MikeMcl/bignumber.js.git
 RUN git clone --depth 1 https://github.com/guidovranken/libfuzzer-js.git
@@ -52,8 +50,14 @@
 RUN git clone --depth 1 https://github.com/LoupVaillant/Monocypher.git
 RUN git clone --depth 1 https://github.com/trezor/trezor-firmware.git
 RUN git clone --depth 1 https://github.com/Cyan4973/xxHash.git
+RUN git clone --depth 1 https://github.com/paulmillr/noble-ed25519.git
+RUN git clone --depth 1 https://github.com/paulmillr/noble-bls12-381.git
+RUN git clone --depth 1 https://github.com/paulmillr/noble-secp256k1.git
+RUN git clone --depth 1 https://github.com/supranational/blst.git
+RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git
 RUN apt-get remove -y libunwind8
 RUN apt-get install -y libssl-dev
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://nodejs.org/dist/v14.17.1/node-v14.17.1-linux-x64.tar.xz
 
 COPY build.sh xxd.c $SRC/
diff --git a/projects/cryptofuzz/build.sh b/projects/cryptofuzz/build.sh
index 9aa3c94..3df9218 100755
--- a/projects/cryptofuzz/build.sh
+++ b/projects/cryptofuzz/build.sh
@@ -20,6 +20,15 @@
 
 export GO111MODULE=off
 
+if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]]
+then
+    # Install nodejs/npm
+    # It is required for building noble-bls12-381
+    cd $SRC/
+    tar Jxf node-v14.17.1-linux-x64.tar.xz
+    export PATH="$PATH:$SRC/node-v14.17.1-linux-x64/bin/"
+fi
+
 # Compile xxd
 $CC $SRC/xxd.c -o /usr/bin/xxd
 
@@ -50,9 +59,6 @@
 # This enables runtime checks for C++-specific undefined behaviour.
 export CXXFLAGS="$CXXFLAGS -D_GLIBCXX_DEBUG"
 
-# Prevent Boost compilation error with -std=c++17
-export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR"
-
 export CXXFLAGS="$CXXFLAGS -I $SRC/cryptofuzz/fuzzing-headers/include"
 if [[ $CFLAGS = *sanitize=memory* ]]
 then
@@ -87,23 +93,23 @@
 fi
 
 # Compile NSS
-if [[ $CFLAGS != *-m32* ]]
-then
-    mkdir $SRC/nss-nspr
-    mv $SRC/nss $SRC/nss-nspr/
-    mv $SRC/nspr $SRC/nss-nspr/
-    cd $SRC/nss-nspr/
-
-    CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" nss/build.sh --enable-fips --static --disable-tests --fuzz=oss
-
-    export NSS_NSPR_PATH=$(realpath $SRC/nss-nspr/)
-    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NSS"
-    export LINK_FLAGS="$LINK_FLAGS -lsqlite3"
-
-    # Compile Cryptofuzz NSS module
-    cd $SRC/cryptofuzz/modules/nss
-    make -B
-fi
+#if [[ $CFLAGS != *-m32* ]]
+#then
+#    mkdir $SRC/nss-nspr
+#    mv $SRC/nss $SRC/nss-nspr/
+#    mv $SRC/nspr $SRC/nss-nspr/
+#    cd $SRC/nss-nspr/
+#
+#    CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" nss/build.sh --enable-fips --static --disable-tests --fuzz=oss
+#
+#    export NSS_NSPR_PATH=$(realpath $SRC/nss-nspr/)
+#    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NSS"
+#    export LINK_FLAGS="$LINK_FLAGS -lsqlite3"
+#
+#    # Compile Cryptofuzz NSS module
+#    cd $SRC/cryptofuzz/modules/nss
+#    make -B
+#fi
 
 # Compile Monocypher
 cd $SRC/Monocypher/
@@ -141,53 +147,93 @@
     make -B
 fi
 
-# Compile SymCrypt
-cd $SRC/SymCrypt/
-if [[ $CFLAGS != *sanitize=array-bounds* ]]
+## Build blst
+#cd $SRC/blst/
+## Patch to disable assembly
+## This is to prevent false positives, see:
+## https://github.com/google/oss-fuzz/issues/5914
+#touch new_no_asm.h
+#echo "#if LIMB_T_BITS==32" >>new_no_asm.h
+#echo "typedef unsigned long long llimb_t;" >>new_no_asm.h
+#echo "#else" >>new_no_asm.h
+#echo "typedef __uint128_t llimb_t;" >>new_no_asm.h
+#echo "#endif" >>new_no_asm.h
+#cat src/no_asm.h >>new_no_asm.h
+#mv new_no_asm.h src/no_asm.h
+#CFLAGS="$CFLAGS -D__BLST_NO_ASM__ -D__BLST_PORTABLE__" ./build.sh
+#export BLST_LIBBLST_A_PATH=$(realpath libblst.a)
+#export BLST_INCLUDE_PATH=$(realpath bindings/)
+#export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BLST"
+#
+## Compile Cryptofuzz blst module
+#cd $SRC/cryptofuzz/modules/blst/
+#make -B -j$(nproc)
+
+# Build libsecp256k1
+cd $SRC/secp256k1/
+autoreconf -ivf
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SECP256K1"
+if [[ $CFLAGS = *sanitize=memory* ]]
 then
-    # Unittests don't build with clang and are not needed anyway
-    sed -i "s/^add_subdirectory(unittest)$//g" CMakeLists.txt
+    ./configure --enable-static --disable-tests --disable-benchmark --disable-exhaustive-tests --enable-module-recovery --enable-experimental --enable-module-schnorrsig --enable-module-ecdh --with-asm=no
+else
+    ./configure --enable-static --disable-tests --disable-benchmark --disable-exhaustive-tests --enable-module-recovery --enable-experimental --enable-module-schnorrsig --enable-module-ecdh
+fi
+make
+export SECP256K1_INCLUDE_PATH=$(realpath .)
+export LIBSECP256K1_A_PATH=$(realpath .libs/libsecp256k1.a)
 
-    mkdir b/
-    cd b/
-    cmake ../
-    make -j$(nproc)
+# Compile Cryptofuzz libsecp256k1 module
+cd $SRC/cryptofuzz/modules/secp256k1/
+make -B -j$(nproc)
 
-    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SYMCRYPT"
-    export SYMCRYPT_INCLUDE_PATH=$(realpath ../inc/)
-    export LIBSYMCRYPT_COMMON_A_PATH=$(realpath lib/x86_64/Generic/libsymcrypt_common.a)
-    export SYMCRYPT_GENERIC_A_PATH=$(realpath lib/x86_64/Generic/symcrypt_generic.a)
+if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]]
+then
+    # noble-secp256k1
+    cd $SRC/cryptofuzz/modules/noble-secp256k1/
+    export NOBLE_SECP256K1_PATH="$SRC/noble-secp256k1/index.js"
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_SECP256K1"
+    make -B
 
-    # Compile Cryptofuzz SymCrypt module
-    cd $SRC/cryptofuzz/modules/symcrypt
+    # noble-bls12-381
+    cd $SRC/noble-bls12-381/
+    cp math.ts new_index.ts
+    $(awk '/^export/ {print "tail -n +"FNR+1" index.ts"; exit}' index.ts) >>new_index.ts
+    mv new_index.ts index.ts
+    npm install && npm run build
+    export NOBLE_BLS12_381_PATH=$(realpath index.js)
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_BLS12_381"
+    cd $SRC/cryptofuzz/modules/noble-bls12-381/
+    make -B
+
+    # noble-ed25519
+    cd $SRC/cryptofuzz/modules/noble-ed25519/
+    export NOBLE_ED25519_PATH="$SRC/noble-ed25519/index.js"
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_ED25519"
     make -B
 fi
 
-# Compile Nettle
-mkdir $SRC/nettle-install/
-cd $SRC/nettle/
-bash .bootstrap
-if [[ $CFLAGS != *sanitize=memory* ]]
-then
-    ./configure --disable-documentation --disable-openssl --prefix=`realpath ../nettle-install`
-else
-    ./configure --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-install`
-fi
-make -j$(nproc)
-make install
-if [[ $CFLAGS != *-m32* ]]
-then
-export LIBNETTLE_A_PATH=`realpath ../nettle-install/lib/libnettle.a`
-export LIBHOGWEED_A_PATH=`realpath ../nettle-install/lib/libhogweed.a`
-else
-export LIBNETTLE_A_PATH=`realpath ../nettle-install/lib32/libnettle.a`
-export LIBHOGWEED_A_PATH=`realpath ../nettle-install/lib32/libhogweed.a`
-fi
-export NETTLE_INCLUDE_PATH=`realpath ../nettle-install/include`
-export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NETTLE"
-# Compile Cryptofuzz Nettle module
-cd $SRC/cryptofuzz/modules/nettle
-make -B
+## Compile SymCrypt
+#cd $SRC/SymCrypt/
+#if [[ $CFLAGS != *sanitize=array-bounds* ]]
+#then
+#    # Unittests don't build with clang and are not needed anyway
+#    sed -i "s/^add_subdirectory(unittest)$//g" CMakeLists.txt
+#
+#    mkdir b/
+#    cd b/
+#    cmake ../
+#    make -j$(nproc)
+#
+#    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SYMCRYPT"
+#    export SYMCRYPT_INCLUDE_PATH=$(realpath ../inc/)
+#    export LIBSYMCRYPT_COMMON_A_PATH=$(realpath lib/x86_64/Generic/libsymcrypt_common.a)
+#    export SYMCRYPT_GENERIC_A_PATH=$(realpath lib/x86_64/Generic/symcrypt_generic.a)
+#
+#    # Compile Cryptofuzz SymCrypt module
+#    cd $SRC/cryptofuzz/modules/symcrypt
+#    make -B
+#fi
 
 # Compile libgmp
 if [[ $CFLAGS != *sanitize=memory* ]]
@@ -211,8 +257,8 @@
 
 # Compile mpdecimal
 cd $SRC/
-tar zxf mpdecimal-2.5.0.tar.gz
-cd mpdecimal-2.5.0/
+tar zxf mpdecimal-2.5.1.tar.gz
+cd mpdecimal-2.5.1/
 ./configure
 cd libmpdec/
 make libmpdec.a -j$(nproc)
@@ -403,27 +449,27 @@
     make -B
 fi
 
-if [[ $CFLAGS != *-m32* ]]
-then
-    # Compile Cryptofuzz (NSS-based)
-    cd $SRC/cryptofuzz
-    LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL $INCLUDE_PATH_FLAGS" make -B -j$(nproc)
-
-    # Generate dictionary
-    ./generate_dict
-
-    # Copy fuzzer
-    cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-nss
-    # Copy dictionary
-    cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-nss.dict
-    # Copy seed corpus
-    cp $SRC/cryptofuzz-corpora/libressl_latest.zip $OUT/cryptofuzz-nss_seed_corpus.zip
-
-    rm $SRC/cryptofuzz/modules/nss/module.a
-
-    CXXFLAGS=${CXXFLAGS//"-DCRYPTOFUZZ_NSS"/}
-    LINK_FLAGS=${LINK_FLAGS//"-lsqlite3"/}
-fi
+#if [[ $CFLAGS != *-m32* ]]
+#then
+#    # Compile Cryptofuzz (NSS-based)
+#    cd $SRC/cryptofuzz
+#    LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL $INCLUDE_PATH_FLAGS" make -B -j$(nproc)
+#
+#    # Generate dictionary
+#    ./generate_dict
+#
+#    # Copy fuzzer
+#    cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-nss
+#    # Copy dictionary
+#    cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-nss.dict
+#    # Copy seed corpus
+#    cp $SRC/cryptofuzz-corpora/libressl_latest.zip $OUT/cryptofuzz-nss_seed_corpus.zip
+#
+#    rm $SRC/cryptofuzz/modules/nss/module.a
+#
+#    CXXFLAGS=${CXXFLAGS//"-DCRYPTOFUZZ_NSS"/}
+#    LINK_FLAGS=${LINK_FLAGS//"-lsqlite3"/}
+#fi
 
 if [[ $CFLAGS != *sanitize=memory* ]]
 then
diff --git a/projects/dart/project.yaml b/projects/dart/project.yaml
index 155fe23..fe43ad4 100644
--- a/projects/dart/project.yaml
+++ b/projects/dart/project.yaml
@@ -6,4 +6,6 @@
 
 sanitizers:
 - address
+fuzzing_engines:
+- libfuzzer
 main_repo: 'https://github.com/dart-lang/sdk.git'
diff --git a/projects/dav1d/Dockerfile b/projects/dav1d/Dockerfile
index 81a4e59..0df0a5b 100644
--- a/projects/dav1d/Dockerfile
+++ b/projects/dav1d/Dockerfile
@@ -15,10 +15,6 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-
-ADD nasm.list /etc/apt/sources.list.d/nasm.list
-ADD nasm_apt.pin /etc/apt/preferences
-
 RUN apt-get update && \
     apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel nasm && \
     pip3 install meson ninja
diff --git a/projects/dav1d/nasm.list b/projects/dav1d/nasm.list
deleted file mode 100644
index 673ee99..0000000
--- a/projects/dav1d/nasm.list
+++ /dev/null
@@ -1,2 +0,0 @@
-# use nasm from a newer ubuntu release
-deb http://archive.ubuntu.com/ubuntu/ focal universe
diff --git a/projects/dav1d/nasm_apt.pin b/projects/dav1d/nasm_apt.pin
deleted file mode 100644
index d1932e9..0000000
--- a/projects/dav1d/nasm_apt.pin
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: *
-Pin: release n=focal
-Pin-Priority: 1
-
-Package: nasm
-Pin: release n=focal
-Pin-Priority: 555
diff --git a/projects/dav1d/project.yaml b/projects/dav1d/project.yaml
index 76c2349..3ef83d8 100644
--- a/projects/dav1d/project.yaml
+++ b/projects/dav1d/project.yaml
@@ -6,8 +6,9 @@
   - "kempfjb@gmail.com"
   - "b@rr-dav.id.au"
   - "dav1d-fuzz@videolan.org"
+  - "psilokos@twoorioles.com"
+  - "gramner@twoorioles.com"
 vendor_ccs:
-  - "negge@mozilla.com"
   - "twsmith@mozilla.com"
 sanitizers:
   - address
diff --git a/projects/dgraph/Dockerfile b/projects/dgraph/Dockerfile
new file mode 100644
index 0000000..1f63ea4
--- /dev/null
+++ b/projects/dgraph/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/dgraph-io/dgraph
+COPY build.sh $SRC/
+WORKDIR $SRC/dgraph
diff --git a/projects/dgraph/build.sh b/projects/dgraph/build.sh
new file mode 100644
index 0000000..f8c215b
--- /dev/null
+++ b/projects/dgraph/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+compile_go_fuzzer github.com/dgraph-io/dgraph/gql Fuzz parser_fuzzer
diff --git a/projects/dgraph/project.yaml b/projects/dgraph/project.yaml
new file mode 100644
index 0000000..74971ba
--- /dev/null
+++ b/projects/dgraph/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://dgraph.io"
+main_repo: "https://github.com/dgraph-io/dgraph"
+primary_contact: "Adam@adalogics.com"
+auto_ccs :
+  - "pawan@dgraph.io"
+  - "manish@dgraph.io"
+  - "ibrahim@dgraph.io"
+  - "daniel@dgraph.io"
+  - "vvbalaji@dgraph.io"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/django/Dockerfile b/projects/django/Dockerfile
index a73872f..25af431 100644
--- a/projects/django/Dockerfile
+++ b/projects/django/Dockerfile
@@ -15,7 +15,8 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get install -y build-essential libncursesw5-dev libreadline-dev libssl-dev libgdbm-dev libc6-dev libsqlite3-dev tk-dev libbz2-dev zlib1g-dev libffi-dev wget
+RUN apt-get update && \
+    apt-get install -y build-essential libncursesw5-dev libreadline-dev libssl-dev libgdbm-dev libc6-dev libsqlite3-dev tk-dev libbz2-dev zlib1g-dev libffi-dev wget
 RUN wget -q https://github.com/python/cpython/archive/v3.8.7.tar.gz
 RUN git clone --depth 1 https://github.com/django/django-fuzzers.git
 RUN git clone --depth 1 https://github.com/django/django.git
diff --git a/projects/django/build.sh b/projects/django/build.sh
index b4e25a4..962b9f9 100755
--- a/projects/django/build.sh
+++ b/projects/django/build.sh
@@ -61,7 +61,7 @@
 
 rm -rf $OUT/django-dependencies
 mkdir $OUT/django-dependencies
-$CPYTHON_INSTALL_PATH/bin/pip3 install asgiref pytz sqlparse -t $OUT/django-dependencies
+$CPYTHON_INSTALL_PATH/bin/pip3 install asgiref pytz sqlparse backports.zoneinfo -t $OUT/django-dependencies
 
 cd $SRC/django-fuzzers
 rm $CPYTHON_INSTALL_PATH/lib/python3.8/lib-dynload/_tkinter*.so
diff --git a/projects/dlplibs/project.yaml b/projects/dlplibs/project.yaml
index 7d3ed33..4e5b6d3 100644
--- a/projects/dlplibs/project.yaml
+++ b/projects/dlplibs/project.yaml
@@ -3,5 +3,6 @@
 primary_contact: "dtardon@redhat.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
   - undefined
diff --git a/projects/dng_sdk/Dockerfile b/projects/dng_sdk/Dockerfile
new file mode 100644
index 0000000..976e9dd
--- /dev/null
+++ b/projects/dng_sdk/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y wget cmake libjpeg-turbo8-dev zlib1g-dev
+RUN git clone https://android.googlesource.com/platform/external/dng_sdk/
+COPY build.sh $SRC/
+WORKDIR dng_sdk
diff --git a/projects/dng_sdk/build.sh b/projects/dng_sdk/build.sh
new file mode 100755
index 0000000..9d7af38
--- /dev/null
+++ b/projects/dng_sdk/build.sh
@@ -0,0 +1,30 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# compile source
+cd ./source
+rm dng_xmp*
+find . -name "*.cpp" -exec $CXX $CXXFLAGS -DqDNGUseLibJPEG=1 -DqDNGUseXMP=0 -DqDNGThreadSafe=1 -c {} \;
+ar cr libdns_sdk.a *.o
+
+# compile fuzzer
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE ../fuzzer/dng_parser_fuzzer.cpp -o $OUT/dng_parser_fuzzer \
+  ./libdns_sdk.a -I./ -l:libjpeg.a -lz
+
+# move seeds
+cd ../fuzzer/seeds/CVE_2020_9589
+zip -q $OUT/dng_parser_fuzzer_seed_corpus.zip *.dng
diff --git a/projects/dng_sdk/project.yaml b/projects/dng_sdk/project.yaml
new file mode 100644
index 0000000..616b70f
--- /dev/null
+++ b/projects/dng_sdk/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://android.googlesource.com/platform/external/dng_sdk/"
+language: c++
+primary_contact: "adaubert@google.com"
+auto_ccs:
+  - david@adalogics.com
+main_repo: 'https://android.googlesource.com/platform/external/dng_sdk/'
diff --git a/projects/dnsmasq/Dockerfile b/projects/dnsmasq/Dockerfile
new file mode 100644
index 0000000..6ab50ce
--- /dev/null
+++ b/projects/dnsmasq/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool
+RUN git clone --depth 1 git://thekelleys.org.uk/dnsmasq.git dnsmasq    
+WORKDIR dnsmasq
+COPY build.sh $SRC/
+COPY fuzz*.c $SRC/
+COPY fuzz*.h $SRC/
+
+COPY fuzz_patch.patch $SRC/
diff --git a/projects/dnsmasq/build.sh b/projects/dnsmasq/build.sh
new file mode 100755
index 0000000..8fc7b21
--- /dev/null
+++ b/projects/dnsmasq/build.sh
@@ -0,0 +1,57 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+export ASAN_OPTIONS="detect_leaks=0"
+
+git apply  --ignore-space-change --ignore-whitespace $SRC/fuzz_patch.patch 
+
+export OSS_CFLAGS="$CFLAGS -g"
+
+sed -i 's/CFLAGS        =/CFLAGS        = ${OSS_CFLAGS} /g' ./Makefile
+sed -i 's/LDFLAGS       =/LDFLAGS       = ${OSS_CFLAGS} /g' ./Makefile
+
+# Do some modificatiosn to the source
+sed -i 's/recvmsg(/fuzz_recvmsg(/g' ./src/dhcp-common.c 
+sed -i 's/recvmsg(/fuzz_recvmsg(/g' ./src/netlink.c 
+sed -i 's/ioctl(/fuzz_ioctl(/g' ./src/dhcp.c
+sed -i 's/ioctl(/fuzz_ioctl(/g' ./src/network.c
+
+sed -i 's/if (errno != 0/if (errno == 123123/g' ./src/netlink.c
+
+echo "" >> ./src/dnsmasq.c 
+echo "ssize_t fuzz_recvmsg(int sockfd, struct msghdr *msg, int flags) {return -1;}" >> ./src/dnsmasq.c
+echo "int fuzz_ioctl(int fd, unsigned long request, void *arg) {return -1;}" >> ./src/dnsmasq.c
+make
+
+# Remove main function and create an archive
+cd ./src
+sed -i 's/int main (/int main2 (/g' ./dnsmasq.c
+sed -i 's/fuzz_recvmsg(/fuzz_recvmsg2(/g' ./dnsmasq.c
+sed -i 's/fuzz_ioctl(/fuzz_ioctl2(/g' ./dnsmasq.c
+
+rm dnsmasq.o
+$CC $CFLAGS -c dnsmasq.c -o dnsmasq.o -I./ -DVERSION=\'\"UNKNOWN\"\' 
+ar cr libdnsmasq.a *.o
+
+sed -i 's/class/class2/g' ./dnsmasq.h
+sed -i 's/new/new2/g' ./dnsmasq.h
+
+# Build the fuzzers
+for fuzz_name in dhcp6 rfc1035 auth dhcp util; do
+    $CC $CFLAGS -c $SRC/fuzz_${fuzz_name}.c -I./ -I$SRC/ -DVERSION=\'\"UNKNOWN\"\' -g
+    $CC $CFLAGS $LIB_FUZZING_ENGINE ./fuzz_${fuzz_name}.o libdnsmasq.a -o $OUT/fuzz_${fuzz_name}
+done
diff --git a/projects/dnsmasq/fuzz_auth.c b/projects/dnsmasq/fuzz_auth.c
new file mode 100644
index 0000000..4a233e1
--- /dev/null
+++ b/projects/dnsmasq/fuzz_auth.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/* 
+ * Targets answer_auth
+ */
+void FuzzAuth(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+  
+  int i1 = get_int(&data, &size);
+  int i2 = get_int(&data, &size);
+  int i3 = get_int(&data, &size);
+
+  if (size > (sizeof(struct dns_header) +50)) {
+    char *new_data = malloc(size+1);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    new_data[size] = '\0';
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    time_t now;
+		union mysockaddr peer_addr;
+		answer_auth((struct dns_header *)new_data, new_data + size, size, now, &peer_addr, i1, i2, i3);
+  }
+}
+
+/*
+ * Fuzzer entrypoint.
+ */ 
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  daemon = NULL;
+  if (size < 1) {
+    return 0;
+  }
+
+  // Initialize mini garbage collector
+  gb_init();
+
+  // Get a value we can use to decide which target to hit.
+  int i = (int)data[0];
+  data += 1;
+  size -= 1;
+
+  int succ = init_daemon(&data, &size);
+
+  if (succ == 0) {
+    cache_init();
+    blockdata_init();
+
+		FuzzAuth(&data, &size);
+
+    cache_start_insert();
+    fuzz_blockdata_cleanup();
+  }
+
+  // Free data in mini garbage collector.
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/projects/dnsmasq/fuzz_dhcp.c b/projects/dnsmasq/fuzz_dhcp.c
new file mode 100644
index 0000000..4ba61ca
--- /dev/null
+++ b/projects/dnsmasq/fuzz_dhcp.c
@@ -0,0 +1,87 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/* 
+ * Targets answer_auth
+ */
+void FuzzDhcp(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+  time_t now;
+  int pxe_fd = 0;
+
+  struct iovec *dhpa = malloc(sizeof(struct iovec));
+  if (dhpa == NULL) return;
+
+  char *content = malloc(300);
+  if (content == NULL) {
+    free(dhpa);
+    return;
+  }
+  
+  dhpa->iov_base = content;
+  dhpa->iov_len = 300;
+
+  daemon->dhcp_packet = *dhpa;
+
+  syscall_data = data;
+  syscall_size = size;
+  
+  dhcp_packet(now, pxe_fd);
+
+  // dnsmasq may change the iov_base if the buffer needs expansion.
+  // Do not free in that case, only free if the buffer stays that same.
+  if (daemon->dhcp_packet.iov_base == content) {
+    free(content);
+  }
+  else{
+    free(daemon->dhcp_packet.iov_base);
+  }
+
+  free(dhpa);
+}
+
+/*
+ * Fuzzer entrypoint.
+ */ 
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  daemon = NULL;
+  if (size < 1) {
+    return 0;
+  }
+
+  // Initialize mini garbage collector
+  gb_init();
+
+  // Get a value we can use to decide which target to hit.
+  int i = (int)data[0];
+  data += 1;
+  size -= 1;
+
+  int succ = init_daemon(&data, &size);
+
+  if (succ == 0) {
+    cache_init();
+    blockdata_init();
+
+		FuzzDhcp(&data, &size);
+
+    cache_start_insert();
+    fuzz_blockdata_cleanup();
+  }
+
+  // Free data in mini garbage collector.
+  gb_cleanup();
+  return 0;
+}
diff --git a/projects/dnsmasq/fuzz_dhcp6.c b/projects/dnsmasq/fuzz_dhcp6.c
new file mode 100644
index 0000000..fd7a858
--- /dev/null
+++ b/projects/dnsmasq/fuzz_dhcp6.c
@@ -0,0 +1,83 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/* 
+ * Targets answer_auth
+ */
+  static int val213 = 0;
+void FuzzDhcp(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+  
+
+  time_t now;
+  int pxe_fd = 0;
+
+  struct iovec *dhpa = malloc(sizeof(struct iovec));
+  if (dhpa == NULL) return;
+
+  char *content = malloc(300);
+  if (content == NULL) {
+    free(dhpa);
+    return;
+  }
+  
+  dhpa->iov_base = content;
+  dhpa->iov_len = 300;
+
+  daemon->dhcp_packet = *dhpa;
+
+  syscall_data = data;
+  syscall_size = size;
+
+  dhcp6_packet(now);
+
+  free(dhpa);
+  free(content);
+}
+
+/*
+ * Fuzzer entrypoint.
+ */ 
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  daemon = NULL;
+  if (size < 1) {
+    return 0;
+  }
+
+  // Initialize mini garbage collector
+  gb_init();
+
+  // Get a value we can use to decide which target to hit.
+  int i = (int)data[0];
+  data += 1;
+  size -= 1;
+
+  int succ = init_daemon(&data, &size);
+
+  if (succ == 0) {
+    cache_init();
+    blockdata_init();
+
+		FuzzDhcp(&data, &size);
+
+    cache_start_insert();
+    fuzz_blockdata_cleanup();
+  }
+
+  // Free data in mini garbage collector.
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/projects/dnsmasq/fuzz_header.h b/projects/dnsmasq/fuzz_header.h
new file mode 100644
index 0000000..748e709
--- /dev/null
+++ b/projects/dnsmasq/fuzz_header.h
@@ -0,0 +1,579 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "dnsmasq.h"
+
+extern void fuzz_blockdata_cleanup();
+
+// Simple garbage collector 
+#define GB_SIZE 100
+
+void *pointer_arr[GB_SIZE];
+static int pointer_idx = 0;
+
+// If the garbage collector is used then this must be called as first thing
+// during a fuzz run.
+void gb_init() {
+  pointer_idx = 0;
+
+   for (int i = 0; i < GB_SIZE; i++) {
+     pointer_arr[i] = NULL;
+   }
+}
+
+void gb_cleanup() {
+  for(int i = 0; i < GB_SIZE; i++) {
+    if (pointer_arr[i] != NULL) {
+      free(pointer_arr[i]);
+    }
+  }
+}
+
+char *get_null_terminated(const uint8_t **data, size_t *size) {
+#define STR_SIZE 75
+  if (*size < STR_SIZE || (int)*size < 0) {
+    return NULL;
+  }
+
+  char *new_s = malloc(STR_SIZE + 1);
+  memcpy(new_s, *data, STR_SIZE);
+  new_s[STR_SIZE] = '\0';
+
+  *data = *data+STR_SIZE;
+  *size -= STR_SIZE;
+  return new_s;
+}
+
+char *gb_get_random_data(const uint8_t **data, size_t *size, size_t to_get) {
+  if (*size < to_get || (int)*size < 0) {
+    return NULL;
+  }
+
+  char *new_s = malloc(to_get);
+  memcpy(new_s, *data, to_get);
+
+  pointer_arr[pointer_idx++] = (void*)new_s;
+  
+  *data = *data + to_get;
+  *size -= to_get;
+
+  return new_s;
+}
+
+char *gb_get_null_terminated(const uint8_t **data, size_t *size) {
+
+  char *nstr = get_null_terminated(data, size);
+  if (nstr == NULL) {
+    return NULL;
+  }
+  pointer_arr[pointer_idx++] = (void*)nstr;
+  return nstr;
+}
+
+char *gb_alloc_data(size_t len) {
+  char *ptr = calloc(1, len);
+  pointer_arr[pointer_idx++] = (void*)ptr;
+  
+  return ptr;
+}
+
+short get_short(const uint8_t **data, size_t *size) {
+  if (*size <= 0) return 0;
+  short c = (short)(*data)[0];
+  *data += 1;
+  *size-=1;
+  return c;
+}
+
+int get_int(const uint8_t **data, size_t *size) {
+  if (*size <= 4) return 0;
+  const uint8_t *ptr = *data;
+  int val = *((int*)ptr);
+  *data += 4;
+  *size -= 4;
+  return val;
+}
+// end simple garbage collector.
+
+const uint8_t *syscall_data = NULL;
+size_t syscall_size = 0;
+
+
+int fuzz_ioctl(int fd, unsigned long request, void *arg) {
+  int fd2 = fd;
+  unsigned long request2 = request;
+  void *arg_ptr = arg;
+
+  // SIOCGSTAMP
+  if (request == SIOCGSTAMP) {
+    struct timeval *tv = (struct timeval*)arg_ptr;
+    if (tv == NULL) {
+      return 0;
+    }
+
+    char *rand_tv = gb_get_random_data(&syscall_data, &syscall_size, sizeof(struct timeval));
+    if (rand_tv == NULL) {
+      return -1;
+    }
+
+    memcpy(tv, rand_tv, sizeof(struct timeval));
+    return 0;
+  }
+
+  if (request == SIOCGIFNAME) {
+    //printf("We got a SIOCGIFNAME\n");
+    struct ifreq *ifr = (struct ifreq*)arg_ptr;
+    if (ifr == NULL) {
+      return -1;
+    }
+    for (int i = 0; i < IF_NAMESIZE; i++) {
+      if (syscall_size > 0 && syscall_data != NULL) {
+        ifr->ifr_name[i] = (char)*syscall_data;
+        syscall_data += 1;
+        syscall_size -= 1;
+      }
+      else {
+        ifr->ifr_name[i] = 'A';
+      }
+    }
+    ifr->ifr_name[IF_NAMESIZE-1] = '\0';
+    return 0;
+    //return -1;
+  }
+  if (request == SIOCGIFFLAGS) {
+    return 0;
+  }
+  if (request == SIOCGIFADDR) {
+    return 0;
+  }
+
+  // 
+  int retval = ioctl(fd2, request2, arg_ptr); 
+  return retval;
+}
+
+
+// Sysytem call wrappers
+static char v = 0;
+ssize_t fuzz_recvmsg(int sockfd, struct msghdr *msg, int flags) {
+  
+  struct iovec *target = msg->msg_iov;
+
+  //printf("recvmsg 1 \n");
+  if (syscall_size > 1) {
+    char r = *syscall_data;
+    syscall_data += 1;
+    syscall_size -= 1;
+
+    if (r == 12) {
+      //printf("recvmsg 2\n");
+      return -1;
+    }
+  }
+
+  int j = 0;
+  if (msg->msg_control != NULL) {
+    for (;j < CMSG_SPACE(sizeof(struct in_pktinfo)); j++)
+    {
+      if (syscall_size > 0 && syscall_data != NULL) {
+        ((char*)msg->msg_control)[j] = *syscall_data;
+        syscall_data += 1;
+        syscall_size -= 1;
+      }
+      else {
+        ((char*)msg->msg_control)[j] = 'A';
+      }
+    }
+  }
+
+  int i = 0;
+  for (; i < target->iov_len; i++) {
+    if (syscall_size > 0 && syscall_data != NULL) {
+      ((char*)target->iov_base)[i] = *syscall_data;
+      syscall_data += 1;
+      syscall_size -= 1;
+    }
+    else {
+      ((char*)target->iov_base)[i] = 'A';
+    }
+  }
+
+  if (msg->msg_namelen > 0) {
+    memset(msg->msg_name, 0, msg->msg_namelen);
+  }
+
+  return i;
+}
+
+
+// dnsmasq specific stuff
+int init_daemon(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  int retval = 0;
+
+#define CLEAN_IF_NULL(arg) if (arg == NULL) goto cleanup;
+
+  // Initialize daemon
+  daemon = (struct daemon*)gb_alloc_data(sizeof(struct daemon));
+  CLEAN_IF_NULL(daemon)
+
+  // daemon misc
+  daemon->max_ttl = get_int(&data, &size);
+  daemon->neg_ttl = get_int(&data, &size);
+  daemon->local_ttl = get_int(&data, &size);
+  daemon->min_cache_ttl = get_int(&data, &size);
+
+  // daemon->namebuff.
+  char *daemon_namebuff = gb_get_null_terminated(&data, &size);
+  daemon->namebuff = daemon_namebuff;
+
+  // daemon->naptr
+  struct naptr *naptr_ptr = (struct naptr*)gb_alloc_data(sizeof(struct naptr));
+  char *naptr_name = gb_get_null_terminated(&data, &size);
+  char *naptr_replace = gb_get_null_terminated(&data, &size);
+  char *naptr_regexp = gb_get_null_terminated(&data, &size);
+  char *naptr_services = gb_get_null_terminated(&data, &size);
+  char *naptr_flags = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(naptr_ptr)
+  CLEAN_IF_NULL(naptr_name)
+  CLEAN_IF_NULL(naptr_replace)
+  CLEAN_IF_NULL(naptr_regexp)
+  CLEAN_IF_NULL(naptr_services)
+  CLEAN_IF_NULL(naptr_flags)
+
+  naptr_ptr->name = naptr_name;
+  naptr_ptr->replace = naptr_replace;
+  naptr_ptr->regexp = naptr_regexp;
+  naptr_ptr->services = naptr_services;
+  naptr_ptr->flags = naptr_flags;
+
+  daemon->naptr = naptr_ptr;
+
+  // daemon->int_names
+  struct interface_name *int_namses = (struct interface_name*)gb_alloc_data(sizeof(struct interface_name));
+
+  char *int_name = gb_get_null_terminated(&data, &size);
+  char *int_intr = gb_get_null_terminated(&data, &size);
+  CLEAN_IF_NULL(int_namses)
+  CLEAN_IF_NULL(int_name)
+  CLEAN_IF_NULL(int_intr)
+  int_namses->name = int_name;
+  int_namses->intr = int_intr;
+
+  struct addrlist *d_addrlist = (struct addrlist*)gb_alloc_data(sizeof(struct addrlist));
+  CLEAN_IF_NULL(d_addrlist)
+  d_addrlist->flags = get_int(&data, &size);
+  d_addrlist->prefixlen = get_int(&data, &size);
+  int_namses->addr = d_addrlist;
+
+  daemon->int_names = int_namses;
+
+  if (size > *size2) {
+    goto cleanup;
+  }
+
+  // daemon->addrbuf
+  char *adbuf = gb_alloc_data(200);
+  CLEAN_IF_NULL(adbuf)
+  daemon->addrbuff = adbuf;
+
+  // daemon->auth_zones
+  struct auth_zone *d_az = (struct auth_zone*)gb_alloc_data(sizeof(struct auth_zone));
+  char *auth_domain = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(d_az)
+  CLEAN_IF_NULL(auth_domain)
+  d_az->domain = auth_domain;
+  daemon->auth_zones = d_az;
+
+  // deamon->mxnames
+  struct mx_srv_record *mx_srv_rec = (struct mx_srv_record*)gb_alloc_data(sizeof(struct mx_srv_record));
+  char *mx_name = gb_get_null_terminated(&data, &size);
+  char *mx_target = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(mx_srv_rec)
+  CLEAN_IF_NULL(mx_target)
+  CLEAN_IF_NULL(mx_name)
+
+  mx_srv_rec->next = daemon->mxnames;
+  daemon->mxnames = mx_srv_rec;
+  mx_srv_rec->name = mx_name;
+  mx_srv_rec->target = mx_target;
+  mx_srv_rec->issrv = get_int(&data, &size);
+  mx_srv_rec->weight = get_int(&data, &size);
+  mx_srv_rec->priority = get_int(&data, &size);
+  mx_srv_rec->srvport = get_int(&data, &size);
+  //data += 40;
+  //size -= 40;
+
+  if (size > *size2) {
+    goto cleanup;
+  }
+
+  // daemon->txt
+  struct txt_record *txt_record = (struct txt_record *)gb_alloc_data(sizeof(struct txt_record));
+  char *txt_record_name =  gb_get_null_terminated(&data, &size);
+  char *txt_record_txt = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(txt_record)
+  CLEAN_IF_NULL(txt_record_name)
+  CLEAN_IF_NULL(txt_record_txt)
+
+  txt_record->name = txt_record_name;
+  txt_record->txt = (unsigned char*)txt_record_txt;
+  txt_record->class2 = (get_short(&data, &size) % 10);
+  daemon->txt = txt_record;
+
+  // daemon->rr
+  struct txt_record *rr_record = (struct txt_record *)gb_alloc_data(sizeof(struct txt_record));
+  char *rr_record_name =  gb_get_null_terminated(&data, &size);
+  char *rr_record_txt = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(rr_record)
+  CLEAN_IF_NULL(rr_record_name)
+  CLEAN_IF_NULL(rr_record_txt)
+
+  rr_record->name = rr_record_name;
+  rr_record->txt = (unsigned char*)rr_record_txt;
+  rr_record->class2 = (get_short(&data, &size) % 10);
+  daemon->rr = rr_record;
+
+  if (size > *size2) {
+    goto cleanup;
+  }
+
+  // daemon->relay4
+  //struct dhcp_relay *dr = (struct dhcp_relay*)gb_alloc_data(sizeof(struct dhcp_relay));
+  struct dhcp_relay *dr = (struct dhcp_relay*)gb_get_random_data(&data, &size, sizeof(struct dhcp_relay));
+  char *dr_interface = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(dr)
+  CLEAN_IF_NULL(dr_interface)
+  dr->interface = dr_interface;
+  dr->next = NULL;
+  dr->current = NULL;
+  daemon->relay4 = dr;
+
+  // deamon->bridges
+  struct dhcp_bridge *db = (struct dhcp_bridge*)gb_alloc_data(sizeof(struct dhcp_bridge));
+  char *db_interface = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(db)
+  CLEAN_IF_NULL(db_interface)
+
+  if (strlen(db_interface) > IF_NAMESIZE) {
+    for (int i = 0; i < IF_NAMESIZE; i++) {
+      db->iface[i] = db_interface[i];
+    }
+  } else {
+    for (int i = 0; i < strlen(db_interface); i++) {
+      db->iface[i] = db_interface[i];
+    }
+  }
+
+
+  struct dhcp_bridge *db_alias = (struct dhcp_bridge*)gb_alloc_data(sizeof(struct dhcp_bridge));
+  //struct dhcp_bridge *db_alias = (struct dhcp_bridge*)gb_get_random_data(&data, &size, sizeof(struct dhcp_bridge));
+  char *db_alias_interface = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(db_alias)
+  CLEAN_IF_NULL(db_alias_interface)
+
+  if (strlen(db_alias_interface) > IF_NAMESIZE) {
+    for (int i = 0; i < IF_NAMESIZE; i++) {
+      db_alias->iface[i] = db_alias_interface[i];
+    }
+  } else {
+    for (int i = 0; i < strlen(db_alias_interface); i++) {
+      db_alias->iface[i] = db_alias_interface[i];
+    }
+  }
+  db->alias = db_alias;
+  daemon->bridges = db;
+
+  // daemon->if_names
+  struct iname *in = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+  char *iname_name = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(in)
+  CLEAN_IF_NULL(iname_name)
+
+  in->name = iname_name;
+  in->next = NULL;
+
+  daemon->if_names = in;
+
+  // daemon->if_addrs
+  struct iname *in_addr = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+  char *iname_name_addr = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(in_addr)
+  CLEAN_IF_NULL(iname_name_addr)
+
+  in_addr->name = iname_name_addr;
+  in_addr->next = NULL;
+
+  daemon->if_addrs = in_addr;
+
+  // daemon->if_except
+  struct iname *in_except = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+  char *iname_name_except = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(in_except)
+  CLEAN_IF_NULL(iname_name_except)
+
+  in_except->name = iname_name_except;
+  in_except->next = NULL;
+
+  daemon->if_except = in_except;
+
+  // daemon->dhcp_except
+  struct iname *except = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+  char *name_except = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(except)
+  CLEAN_IF_NULL(name_except)
+
+  except->name = name_except;
+  except->next = NULL;
+
+  daemon->dhcp_except = except;
+
+  // daemon->authinterface
+  struct iname *auth_interface = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+  char *auth_name = gb_get_null_terminated(&data, &size);
+  
+  CLEAN_IF_NULL(auth_interface)
+  CLEAN_IF_NULL(auth_name)
+
+  auth_interface->name = auth_name;
+  auth_interface->next = NULL;
+
+  daemon->authinterface = auth_interface;
+
+
+  // daemon->cnames
+  struct cname *cn = (struct cname*)gb_alloc_data(sizeof(struct cname));
+  char *cname_alias = gb_get_null_terminated(&data, &size);
+  char *cname_target = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(cn)
+  CLEAN_IF_NULL(cname_alias)
+  CLEAN_IF_NULL(cname_target)
+
+  cn->alias = cname_alias;
+  cn->target = cname_target;
+  daemon->cnames = cn;
+
+
+  // daemon->ptr
+  struct ptr_record *ptr = (struct ptr_record *)gb_alloc_data(sizeof(struct ptr_record));
+  CLEAN_IF_NULL(ptr)
+
+  char *ptr_name = gb_get_null_terminated(&data, &size);
+  CLEAN_IF_NULL(ptr_name)
+  ptr->name = ptr_name;
+  daemon->ptr = ptr;
+
+  if (size > *size2) {
+    goto cleanup;
+  }
+
+  // daemon->dhcp
+  struct dhcp_context *dhcp_c = (struct dhcp_context *) gb_get_random_data(&data, &size, sizeof(struct dhcp_context));
+  
+  char *dhcp_c_temp_in = gb_get_null_terminated(&data, &size);
+
+  struct dhcp_netid *dhcp_c_netid = (struct dhcp_netid *) gb_alloc_data(sizeof(struct dhcp_netid));
+  char *dhcp_netid_net = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(dhcp_c)
+  CLEAN_IF_NULL(dhcp_c_temp_in)
+  CLEAN_IF_NULL(dhcp_c_netid)
+  CLEAN_IF_NULL(dhcp_netid_net)
+
+  dhcp_c->next = NULL;
+  dhcp_c->current = NULL;
+  dhcp_c_netid->net = dhcp_netid_net;
+  dhcp_c->filter = dhcp_c_netid;
+  dhcp_c->template_interface = dhcp_c_temp_in;
+
+  daemon->dhcp = dhcp_c;
+
+
+  // daemon->dhcp6
+  struct dhcp_context *dhcp6_c = (struct dhcp_context *) gb_get_random_data(&data, &size, sizeof(struct dhcp_context));
+  
+  char *dhcp6_c_temp_in = gb_get_null_terminated(&data, &size);
+
+  struct dhcp_netid *dhcp6_c_netid = (struct dhcp_netid *) gb_alloc_data(sizeof(struct dhcp_netid));
+  char *dhcp6_netid_net = gb_get_null_terminated(&data, &size);
+
+  CLEAN_IF_NULL(dhcp6_c)
+  CLEAN_IF_NULL(dhcp6_c_temp_in)
+  CLEAN_IF_NULL(dhcp6_c_netid)
+  CLEAN_IF_NULL(dhcp6_netid_net)
+
+  dhcp6_c->next = NULL;
+  dhcp6_c->current = NULL;
+  dhcp6_c_netid->net = dhcp6_netid_net;
+  dhcp6_c->filter = dhcp6_c_netid;
+  dhcp6_c->template_interface = dhcp6_c_temp_in;
+
+  daemon->dhcp6 = dhcp6_c;
+
+  // daemon->doing_dhcp6
+  daemon->doing_dhcp6 = 1;
+
+  // daemon->dhcp_buffs
+  char *dhcp_buff = gb_alloc_data(DHCP_BUFF_SZ);
+  char *dhcp_buff2 = gb_alloc_data(DHCP_BUFF_SZ);
+  char *dhcp_buff3 = gb_alloc_data(DHCP_BUFF_SZ);
+
+  CLEAN_IF_NULL(dhcp_buff)
+  CLEAN_IF_NULL(dhcp_buff2)
+  CLEAN_IF_NULL(dhcp_buff3)
+
+  daemon->dhcp_buff = dhcp_buff;
+  daemon->dhcp_buff2 = dhcp_buff2;
+  daemon->dhcp_buff3 = dhcp_buff3;
+
+
+
+  // daemon->ignore_addr
+  struct bogus_addr *bb = (struct bogus_addr *)gb_alloc_data(sizeof(struct bogus_addr));
+  CLEAN_IF_NULL(bb)
+
+  daemon->ignore_addr = bb;
+
+  // daemon->doctors
+  if (size > *size2) {
+    goto cleanup;
+  }
+
+  struct doctor *doctors = (struct doctor *)gb_alloc_data(sizeof(struct doctor));
+  CLEAN_IF_NULL(doctors)
+
+  doctors->next = NULL;
+  daemon->doctors = doctors;
+
+  retval = 0;
+  goto ret;
+cleanup:
+  retval = -1;
+
+ret:
+  return retval;
+}
diff --git a/projects/dnsmasq/fuzz_patch.patch b/projects/dnsmasq/fuzz_patch.patch
new file mode 100644
index 0000000..50f7cab
--- /dev/null
+++ b/projects/dnsmasq/fuzz_patch.patch
@@ -0,0 +1,170 @@
+diff --git a/src/blockdata.c b/src/blockdata.c
+index 0986285..852c961 100644
+--- a/src/blockdata.c
++++ b/src/blockdata.c
+@@ -15,16 +15,22 @@
+ */
+ 
+ #include "dnsmasq.h"
++#include <assert.h>
+ 
+ static struct blockdata *keyblock_free;
+ static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
+ 
++void *total_allocated[200] = {0};
++static int fuzz_total_alloc_ptr = 0;
++
+ static void blockdata_expand(int n)
+ {
+   struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
+   
+   if (new)
+     {
++      assert(fuzz_total_alloc_ptr < 200);
++      total_allocated[fuzz_total_alloc_ptr++] = (void*)new;
+       int i;
+       
+       new[n-1].next = keyblock_free;
+@@ -45,11 +51,23 @@ void blockdata_init(void)
+   blockdata_count = 0;
+   blockdata_hwm = 0;
+ 
++  fuzz_total_alloc_ptr = 0;
++  for (int m = 0; m < 200; m++)
++	  total_allocated[m] = NULL;
++
+   /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */  
+   if (option_bool(OPT_DNSSEC_VALID))
+     blockdata_expand(daemon->cachesize);
+ }
+ 
++void fuzz_blockdata_cleanup() {
++	for (int i = 0; i < 200; i++) {
++		if (total_allocated[i] != NULL) {
++			free(total_allocated[i]);
++		}
++	}
++}
++
+ void blockdata_report(void)
+ {
+   my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"), 
+diff --git a/src/dhcp.c b/src/dhcp.c
+index e500bc2..7215590 100644
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -183,18 +183,26 @@ void dhcp_packet(time_t now, int pxe_fd)
+     recvtime = tv.tv_sec;
+ 
+   if (msg.msg_controllen >= sizeof(struct cmsghdr))
+-    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+-      if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
+-	{
+-	  union {
+-	    unsigned char *c;
+-	    struct in_pktinfo *p;
+-	  } p;
+-	  p.c = CMSG_DATA(cmptr);
+-	  iface_index = p.p->ipi_ifindex;
+-	  if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
+-	    unicast_dest = 1;
+-	}
++  {
++    int tmp_val = 0;
++      for (cmptr = CMSG_FIRSTHDR(&msg); 
++          cmptr && tmp_val < 1; 
++          tmp_val++) {
++          //cmptr = CMSG_NXTHDR(&msg, cmptr)) {
++      tmp_val++;
++          if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
++      {
++        union {
++          unsigned char *c;
++          struct in_pktinfo *p;
++        } p;
++        p.c = CMSG_DATA(cmptr);
++        iface_index = p.p->ipi_ifindex;
++        if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
++          unicast_dest = 1;
++      }
++    }
++  }
+ 
+ #elif defined(HAVE_BSD_NETWORK) 
+   if (msg.msg_controllen >= sizeof(struct cmsghdr))
+diff --git a/src/dhcp6.c b/src/dhcp6.c
+index ae1f5c1..ce7397d 100644
+--- a/src/dhcp6.c
++++ b/src/dhcp6.c
+@@ -116,10 +116,14 @@ void dhcp6_packet(time_t now)
+   msg.msg_iov =  &daemon->dhcp_packet;
+   msg.msg_iovlen = 1;
+   
+-  if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
++  if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1){
+     return;
+-  
+-  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
++  }
++
++  int tmp_val = 0;
++//  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) {
++  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr && tmp_val < 1; tmp_val++) {
++    tmp_val++;
+     if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
+       {
+ 	union {
+@@ -131,9 +135,11 @@ void dhcp6_packet(time_t now)
+ 	if_index = p.p->ipi6_ifindex;
+ 	dst_addr = p.p->ipi6_addr;
+       }
++  }
+ 
+-  if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
++  if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name)) {
+     return;
++  }
+ 
+   if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
+     {
+diff --git a/src/netlink.c b/src/netlink.c
+index 7840ef9..2419897 100644
+--- a/src/netlink.c
++++ b/src/netlink.c
+@@ -197,8 +197,13 @@ int iface_enumerate(int family, void *parm, int (*callback)())
+   if (errno != 0)
+     return 0;
+     
++  int valval = 0;
+   while (1)
+     {
++      valval++;
++      if (valval > 300) {
++        return -1;
++      }
+       if ((len = netlink_recv(0)) == -1)
+ 	{
+ 	  if (errno == ENOBUFS)
+diff --git a/src/network.c b/src/network.c
+index 296c7bd..c03961a 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -697,6 +697,7 @@ int enumerate_interfaces(int reset)
+   struct auth_zone *zone;
+ #endif
+   struct server *serv;
++  int iteration = 0;
+   
+   /* Do this max once per select cycle  - also inhibits netlink socket use
+    in TCP child processes. */
+@@ -734,6 +735,10 @@ int enumerate_interfaces(int reset)
+       }
+     
+ again:
++  if (iteration > 100) {
++    return 0;
++  }
++  iteration += 1;
+   /* Mark interfaces for garbage collection */
+   for (iface = daemon->interfaces; iface; iface = iface->next) 
+     iface->found = 0;
diff --git a/projects/dnsmasq/fuzz_rfc1035.c b/projects/dnsmasq/fuzz_rfc1035.c
new file mode 100644
index 0000000..fb563f8
--- /dev/null
+++ b/projects/dnsmasq/fuzz_rfc1035.c
@@ -0,0 +1,271 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/*
+ *  Targets "extract_addresses"
+ */
+void FuzzExtractTheAddress(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  char *new_name = NULL;
+  new_name = get_null_terminated(&data, &size);
+  pointer_arr[pointer_idx++] = (void*)new_name;
+
+  int is_sign = get_int(&data, &size);
+  int check_rebind = get_int(&data, &size);
+  int secure =  get_int(&data, &size);
+
+  if (size > (sizeof(struct dns_header) +50)) {
+    char *new_data = malloc(size);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    pointer_arr[pointer_idx++] = (void*)new_data;
+    
+    time_t now; 
+    int doctored = 0;
+    extract_addresses((struct dns_header *)new_data, size, new_name, now, NULL, NULL, is_sign, check_rebind, 0, secure, &doctored);
+  }
+}
+
+
+/*
+ * Targets "answer_request"
+ */
+void FuzzAnswerTheRequest(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  struct in_addr local_addr;
+  struct in_addr local_netmask;
+  time_t now;
+
+  int i1 = get_int(&data, &size);
+  int i2 = get_int(&data, &size);
+  int i3 = get_int(&data, &size);
+
+  if (size > (sizeof(struct dns_header) +50)) {
+    char *new_data = malloc(size);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    answer_request((struct dns_header *)new_data, new_data+size, size, local_addr, local_netmask, now, i1, i2, i3);
+  }
+
+}
+
+/*
+ * Targets "check_for_ignored_address"
+ */
+void FuzzIgnoredAddress(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  if (size > (sizeof(struct dns_header) +50)) {
+    //return 0;
+    char *new_data = malloc(size);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    check_for_ignored_address((struct dns_header *)new_data, size);
+  }
+}
+
+/*
+ * Targets "check_for_local_domain"
+ */
+void FuzzCheckLocalDomain(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  
+    char *new_data = malloc(size+1);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    new_data[size] = '\0';
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    time_t now;
+    check_for_local_domain(new_data, now);
+}
+
+/*
+ * Targets "extract_request"
+ */
+void FuzzExtractRequest(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  char *new_name = NULL;
+  new_name = get_null_terminated(&data, &size);
+
+  if (new_name == NULL) {
+    return ;
+  }
+  pointer_arr[pointer_idx++] = (void*)new_name;
+
+  if (size > (sizeof(struct dns_header) +50)) {
+    char *new_data = malloc(size+1);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    new_data[size] = '\0';
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    unsigned short typeb;
+    extract_request((struct dns_header *)new_data, size, new_name, &typeb);
+  }
+}
+
+
+/*
+ * Targets "in_arpa_name_2_addr"
+ */
+void FuzzArpaName2Addr(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  char *new_name = NULL;
+  new_name = get_null_terminated(&data, &size);
+
+  if (new_name == NULL) {
+    return ;
+  }
+  pointer_arr[pointer_idx++] = (void*)new_name;
+  union all_addr addr;
+  in_arpa_name_2_addr(new_name, &addr);
+  return;
+}
+
+void FuzzResizePacket(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+
+  char *new_packet = malloc(50);
+
+  if (size > (sizeof(struct dns_header) + 50)) {
+    char *new_data = malloc(size+1);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    new_data[size] = '\0';
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    resize_packet((struct dns_header *)new_data, size, (unsigned char*)new_packet, 50);    
+  }
+  free(new_packet);
+}
+
+void FuzzSetupReply(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+  
+  if (size > (sizeof(struct dns_header) + 50)) {
+    char *new_data = malloc(size+1);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    new_data[size] = '\0';
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    setup_reply((struct dns_header *)new_data, 0, 0);
+  }
+}
+
+
+void FuzzCheckForBogusWildcard(const uint8_t **data2, size_t *size2) {
+  const uint8_t *data = *data2;
+  size_t size = *size2;
+  
+  char *nname = gb_get_null_terminated(&data, &size);
+  if (nname == NULL) {
+    return;
+  }
+
+
+  if (size > (sizeof(struct dns_header) + 50)) {
+    char *new_data = malloc(size+1);
+    memset(new_data, 0, size);
+    memcpy(new_data, data, size);
+    new_data[size] = '\0';
+    pointer_arr[pointer_idx++] = (void*)new_data;
+
+    time_t now;
+    check_for_bogus_wildcard((struct dns_header *)new_data, size, nname, now);
+  }
+}
+
+
+/*
+ * Fuzzer entrypoint.
+ */ 
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  daemon = NULL;
+  //printf("Running fuzzer\n");
+  if (size < 1) {
+    return 0;
+  }
+
+  // Initialize mini garbage collector
+  gb_init();
+
+  // Get a value we can use to decide which target to hit.
+  int i = (int)data[0];
+  data += 1;
+  size -= 1;
+
+  int succ = init_daemon(&data, &size);
+
+  if (succ == 0) {
+    cache_init();
+    blockdata_init();
+
+    //i = 7;
+#define TS 9
+    if ((i % TS) == 0) {
+      FuzzExtractTheAddress(&data,&size);
+    }
+    else if ((i % TS) == 1) {
+      FuzzAnswerTheRequest(&data,&size);
+    }
+    else if ((i % TS) == 2) {
+      FuzzCheckLocalDomain(&data, &size);
+    }
+    else if ((i % TS) == 3) {
+      FuzzExtractRequest(&data, &size);
+    }
+    else if ((i % TS) == 4) {
+      FuzzArpaName2Addr(&data, &size);
+    }
+    else if ((i %TS) == 5) {
+      FuzzResizePacket(&data, &size);
+    }
+    else if ((i %TS) == 6) {
+      FuzzSetupReply(&data, &size);
+    }
+    else if ((i % TS) == 7) {
+      FuzzCheckForBogusWildcard(&data, &size);
+    }
+    else {
+      FuzzIgnoredAddress(&data, &size);
+    } 
+    cache_start_insert();
+    fuzz_blockdata_cleanup();
+  }
+
+  // Free data in mini garbage collector.
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/projects/dnsmasq/fuzz_util.c b/projects/dnsmasq/fuzz_util.c
new file mode 100644
index 0000000..7ab723c
--- /dev/null
+++ b/projects/dnsmasq/fuzz_util.c
@@ -0,0 +1,66 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  // init fuzz garbage collector
+  gb_init();
+
+  int succ = init_daemon(&data, &size);
+  if (succ == 0) {
+    char *t1 = gb_get_null_terminated(&data, &size);
+    char *t2 = gb_get_null_terminated(&data, &size);
+    if (t1 != NULL && t2 != NULL) {
+
+      // Util logic
+      hostname_isequal(t1, t2);
+
+      legal_hostname(t1);
+      char *tmp = canonicalise(t2, NULL);
+      if (tmp != NULL) {
+        free(tmp);
+      }
+
+      char *tmp_out = (char *)malloc(30);
+      int mac_type;
+      parse_hex(t1, (unsigned char *)tmp_out, 30, NULL, NULL);
+      parse_hex(t1, (unsigned char *)tmp_out, 30, NULL, &mac_type);
+      free(tmp_out);
+
+      wildcard_match(t1, t2);
+      if (strlen(t1) < strlen(t2)) {
+        wildcard_matchn(t1, t2, strlen(t1));
+      } else {
+        wildcard_matchn(t1, t2, strlen(t2));
+      }
+      hostname_issubdomain(t1, t2);
+
+      union all_addr addr1;
+      memset(&addr1, 0, sizeof(union all_addr));
+      is_name_synthetic(0, t1, &addr1);
+
+      if (size > sizeof(struct dns_header)) {
+        hash_questions(data, size, t2);
+
+        rrfilter(data, size, 0);
+      }
+    }
+
+    fuzz_blockdata_cleanup();
+  }
+
+  // cleanup
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/projects/dnsmasq/project.yaml b/projects/dnsmasq/project.yaml
new file mode 100644
index 0000000..51d7e1e
--- /dev/null
+++ b/projects/dnsmasq/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://thekelleys.org.uk/dnsmasq/doc.html"
+language: c
+primary_contact: "simon@thekelleys.org.uk"
+main_repo: "git://thekelleys.org.uk/dnsmasq.git"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/draco/project.yaml b/projects/draco/project.yaml
index 04ef12e..96396bf 100644
--- a/projects/draco/project.yaml
+++ b/projects/draco/project.yaml
@@ -4,4 +4,7 @@
 auto_ccs:
   - "ostava@google.com"
   - "vytyaz@google.com"
+fuzzing_engines:
+  - libfuzzer
+  - honggfuzz
 main_repo: 'https://github.com/google/draco'
diff --git a/projects/dragonfly/Dockerfile b/projects/dragonfly/Dockerfile
index 46870a6..1399802 100644
--- a/projects/dragonfly/Dockerfile
+++ b/projects/dragonfly/Dockerfile
@@ -14,20 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN go get	github.com/go-openapi/swag \
-		github.com/go-openapi/validate \
-		gopkg.in/warnings.v0 \
-		github.com/gorilla/mux \
-		github.com/prometheus/client_golang/prometheus \ 
-		github.com/pkg/errors \
-		github.com/sirupsen/logrus \
-		gopkg.in/gcfg.v1 \
-		github.com/valyala/fasthttp \
-		gopkg.in/natefinch/lumberjack.v2 \
-		github.com/emirpasic/gods/maps/treemap \
-		github.com/emirpasic/gods/utils \
-		github.com/willf/bitset
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone https://github.com/dragonflyoss/Dragonfly
 COPY build.sh $SRC/
 WORKDIR $SRC/Dragonfly
diff --git a/projects/duckdb/Dockerfile b/projects/duckdb/Dockerfile
new file mode 100644
index 0000000..b084a74
--- /dev/null
+++ b/projects/duckdb/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN git clone https://github.com/duckdb/duckdb duckdb
+WORKDIR duckdb
+COPY build.sh $SRC/
+COPY parse_fuzz_test.cpp $SRC/duckdb/parse_fuzz_test.cpp
diff --git a/projects/duckdb/build.sh b/projects/duckdb/build.sh
new file mode 100755
index 0000000..0961473
--- /dev/null
+++ b/projects/duckdb/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+make
+THIRD_PARTY_LIBS=$(find ./build/release/third_party/ -name "*.a")
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./parse_fuzz_test.cpp \
+    -o $OUT/parse_fuzz_test -I./ -I./src/include \
+    ./build/release/src/libduckdb_static.a \
+    ${THIRD_PARTY_LIBS}
diff --git a/projects/duckdb/parse_fuzz_test.cpp b/projects/duckdb/parse_fuzz_test.cpp
new file mode 100644
index 0000000..fdae6bd
--- /dev/null
+++ b/projects/duckdb/parse_fuzz_test.cpp
@@ -0,0 +1,23 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "duckdb/parser/parser.hpp"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    std::string input(reinterpret_cast<const char*>(data), size);
+    duckdb::Parser parser;
+    try {
+       parser.ParseQuery(input);
+    } catch (std::exception &e) {}
+
+    return 0;
+}
diff --git a/projects/duckdb/project.yaml b/projects/duckdb/project.yaml
new file mode 100644
index 0000000..3de096c
--- /dev/null
+++ b/projects/duckdb/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://duckdb.org/"
+language: c++
+primary_contact: "quack@duckdb.org"
+main_repo: "https://github.com/duckdb/duckdb/"
+auto_ccs: 
+  - "hannes.muehleisen@gmail.com"
+  - "david@adalogics.com"
diff --git a/projects/easywsclient/project.yaml b/projects/easywsclient/project.yaml
index c3be9c4..d7822c8 100644
--- a/projects/easywsclient/project.yaml
+++ b/projects/easywsclient/project.yaml
@@ -3,9 +3,10 @@
 primary_contact: "dhbaird@gmail.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 architectures:
   - x86_64
   - i386
-main_repo: 'https://github.com/dhbaird/easywsclient'
+main_repo: 'https://github.com/dhbaird/easywsclient'
\ No newline at end of file
diff --git a/projects/ecc-diff-fuzzer/Dockerfile b/projects/ecc-diff-fuzzer/Dockerfile
index 0ea8a4e..6defc00 100644
--- a/projects/ecc-diff-fuzzer/Dockerfile
+++ b/projects/ecc-diff-fuzzer/Dockerfile
@@ -14,7 +14,10 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+ENV GOPATH /root/go
+ENV PATH $PATH:/root/.go/bin:$GOPATH/bin
+RUN install_go.sh
 RUN apt-get update && apt-get install -y make cmake bzip2 autoconf automake gettext libtool python curl
 RUN rustup target add i686-unknown-linux-gnu
 #use different package sources for recent npm
@@ -23,9 +26,9 @@
 RUN apt install -y nodejs
 RUN npm install -g browserify
 RUN npm install elliptic
-RUN git clone --depth 1 https://github.com/horhof/quickjs quickjs
+RUN git clone --depth 1 https://github.com/bellard/quickjs quickjs
 RUN git clone --depth 1 https://github.com/catenacyber/elliptic-curve-differential-fuzzer.git ecfuzzer
-RUN git clone --recursive --depth 1 https://github.com/ARMmbed/mbedtls.git mbedtls
+RUN git clone --recursive --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls.git mbedtls
 RUN git clone --depth 1 https://github.com/ANSSI-FR/libecc.git libecc
 RUN git clone --depth 1 https://github.com/openssl/openssl.git openssl
 RUN git clone --depth 1 git://git.gnupg.org/libgpg-error.git libgpg-error
diff --git a/projects/ecc-diff-fuzzer/build.sh b/projects/ecc-diff-fuzzer/build.sh
index 9b951ca..d05c14a 100755
--- a/projects/ecc-diff-fuzzer/build.sh
+++ b/projects/ecc-diff-fuzzer/build.sh
@@ -123,6 +123,7 @@
 cp libquickjs.a /usr/local/lib/
 )
 
+export CARGO_BUILD_TARGET="x86_64-unknown-linux-gnu"
 #build fuzz target
 cd ecfuzzer
 if [ "$ARCHITECTURE" = 'i386' ]; then
diff --git a/projects/eigen/solver_fuzzer.cc b/projects/eigen/solver_fuzzer.cc
index 86651ec..0cd8b6c 100644
--- a/projects/eigen/solver_fuzzer.cc
+++ b/projects/eigen/solver_fuzzer.cc
@@ -18,7 +18,6 @@
 #include <string>
 
 #include "Eigen/Core"
-#include "Eigen/src/Core/Matrix.h"
 
 using ::Eigen::Matrix;
 using ::Eigen::Dynamic;
diff --git a/projects/envoy/build.sh b/projects/envoy/build.sh
index 09086a2..6c188fc 100755
--- a/projects/envoy/build.sh
+++ b/projects/envoy/build.sh
@@ -38,9 +38,64 @@
 export FUZZING_CFLAGS="$CFLAGS"
 export FUZZING_CXXFLAGS="$CXXFLAGS"
 
+# Disable instrumentation in various external libraries. These 
+# are fuzzed elsewhere.
+# The following disables both coverage-instrumentation and other sanitizer instrumentation.
+# We disable instrumentation in:
+#  antlr4
+#  google_protobuf
+#  absl
+#  googltest
+#  grpc
+#  boringssl
+#  re2
+#  upb
+#  brotli
+#  cel_cpp
+#  yaml_cpp
+#  wasm_cpp_host
+#  libprotobuf-mutator
+#  google_url (gurl)
+#  lightstep_tracer
+# In addition to this, we disable instrumentation in all *.pb.cc (protobuf-generated files)
+# and everything in the bazel-out directory.
+declare -r DI="$(
+if [ "$SANITIZER" != "coverage" ]
+then
+# Envoy code. Disable coverage instrumentation
+  echo " --per_file_copt=^.*source/extensions/access_loggers/.*\.cc\$@-fsanitize-coverage=0" 
+  echo " --per_file_copt=^.*source/common/protobuf/.*\.cc\$@-fsanitize-coverage=0"
+
+# Envoy test code. Disable coverage instrumentation
+  echo " --per_file_copt=^.*test/.*\.cc\$@-fsanitize-coverage=0"
+
+# External dependencies. Disable all instrumentation.
+  echo " --per_file_copt=^.*antlr4_runtimes.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_google_protobuf.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_google_absl.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*googletest.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_github_grpc_grpc.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*boringssl.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_googlesource_code_re2.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*upb.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*org_brotli.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_google_cel_cpp.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_github_jbeder_yaml_cpp.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*proxy_wasm_cpp_host/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_github_google_libprotobuf_mutator/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_googlesource_googleurl/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*com_lightstep_tracer_cpp/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+
+# All protobuf code and code in bazel-out
+  echo " --per_file_copt=^.*\.pb\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+  echo " --per_file_copt=^.*bazel-out/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all"
+fi
+)"
+
+
 # Benchmark about 3 GB per CPU (10 threads for 28.8 GB RAM)
 # TODO(asraa): Remove deprecation warnings when Envoy and deps moves to C++17
-bazel build --verbose_failures --dynamic_mode=off \
+bazel build --verbose_failures --dynamic_mode=off ${DI} \
   --spawn_strategy=standalone --genrule_strategy=standalone \
   --local_cpu_resources=HOST_CPUS*0.32 \
   --//source/extensions/wasm_runtime/v8:enabled=false \
diff --git a/projects/envoy/project.yaml b/projects/envoy/project.yaml
index 5fae149..bb9481c 100644
--- a/projects/envoy/project.yaml
+++ b/projects/envoy/project.yaml
@@ -12,11 +12,12 @@
   - "asraa@google.com"
   - "adip@google.com"
   - "avd@google.com"
-  - "skerner@google.com"
-  - "rdsmith@google.com"
   - "chaoqinli@google.com"
   - "yanjunxiang@google.com"
-  - "arquebus@appspot.gserviceaccount.com"
   - "david@adalogics.com"
+  - "kbaichoo@google.com"
+  - "pcrao@google.com"
+  - "tyxia@google.com"
+  - "krajshiva@google.com"
 coverage_extra_args: -ignore-filename-regex=.*\.cache.*envoy_deps_cache.*
 main_repo: 'https://github.com/envoyproxy/envoy.git'
diff --git a/projects/espeak-ng/Dockerfile b/projects/espeak-ng/Dockerfile
new file mode 100644
index 0000000..674c629
--- /dev/null
+++ b/projects/espeak-ng/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt install -y automake autoconf libtool pkg-config
+RUN git clone --depth 1 https://github.com/espeak-ng/espeak-ng
+COPY build.sh $SRC
+WORKDIR $SRC/espeak-ng
diff --git a/projects/espeak-ng/build.sh b/projects/espeak-ng/build.sh
new file mode 100755
index 0000000..079db4d
--- /dev/null
+++ b/projects/espeak-ng/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+# build project
+export ASAN_OPTIONS=detect_leaks=0
+./autogen.sh
+./configure --with-libfuzzer=yes --disable-shared --with-speechplayer=no
+make check || true
+cp tests/ssml-fuzzer.test $OUT/ssml-fuzzer
+cp -r espeak-ng-data/ $OUT/
diff --git a/projects/espeak-ng/project.yaml b/projects/espeak-ng/project.yaml
new file mode 100644
index 0000000..142a78d
--- /dev/null
+++ b/projects/espeak-ng/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://github.com/espeak-ng/espeak-ng"
+language: c++
+primary_contact: "msclrhd@googlemail.com"
+auto_ccs:
+- "valdis.vitolins@gmail.com"
+- "p.antoine@catenacyber.fr"
+- "sascha.brawer@gmail.com"
+
+sanitizers:
+- address
+fuzzing_engines:
+- libfuzzer
+- afl
+main_repo: 'https://github.com/espeak-ng/espeak-ng'
diff --git a/projects/etcd/Dockerfile b/projects/etcd/Dockerfile
new file mode 100644
index 0000000..789f755
--- /dev/null
+++ b/projects/etcd/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/etcd-io/etcd
+COPY wal_fuzzer.go build.sh $SRC/
+WORKDIR $SRC/etcd
diff --git a/projects/etcd/build.sh b/projects/etcd/build.sh
new file mode 100644
index 0000000..6df485b
--- /dev/null
+++ b/projects/etcd/build.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mv $SRC/wal_fuzzer.go $SRC/etcd/server/storage/wal/
+compile_go_fuzzer go.etcd.io/etcd/server/v3/storage/wal FuzzWalCreate fuzz_wal_create
+
diff --git a/projects/etcd/project.yaml b/projects/etcd/project.yaml
new file mode 100644
index 0000000..4470f5c
--- /dev/null
+++ b/projects/etcd/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://etcd.io"
+main_repo: "https://github.com/etcd-io/etcd"
+primary_contact: "ptab@google.com"
+auto_ccs :
+  - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/etcd/wal_fuzzer.go b/projects/etcd/wal_fuzzer.go
new file mode 100644
index 0000000..8b21e38
--- /dev/null
+++ b/projects/etcd/wal_fuzzer.go
@@ -0,0 +1,58 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package wal
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+
+	"go.etcd.io/etcd/raft/v3/raftpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
+	"go.uber.org/zap"
+)
+
+func FuzzWalCreate(data []byte) int {
+	p, err := ioutil.TempDir("/tmp", "waltest")
+	if err != nil {
+		return -1
+	}
+	defer os.RemoveAll(p)
+	w, err := Create(zap.NewExample(), p, data)
+	if err != nil {
+		return 0
+	}
+	if err = w.SaveSnapshot(walpb.Snapshot{}); err != nil {
+		return 0
+	}
+	if err = w.Save(raftpb.HardState{}, []raftpb.Entry{{Index: 0}}); err != nil {
+		return 0
+	}
+	w.Close()
+	neww, err := Open(zap.NewExample(), p, walpb.Snapshot{})
+	if err != nil {
+		return 0
+	}
+	defer neww.Close()
+	metadata, _, _, err := neww.ReadAll()
+	if err != nil {
+		return 0
+	}
+	if !bytes.Equal(data, metadata) {
+		panic("data and metadata are not equal, but they should be")
+	}
+	return 1
+}
diff --git a/projects/exiv2/Dockerfile b/projects/exiv2/Dockerfile
new file mode 100644
index 0000000..1540fe4
--- /dev/null
+++ b/projects/exiv2/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN apt-get update && apt-get install -y cmake make ccache python3 libexpat1-dev zlib1g-dev libssh-dev libcurl4-openssl-dev libxml2-utils
+RUN git clone https://github.com/Exiv2/exiv2 exiv2
+WORKDIR exiv2
+
+COPY build.sh $SRC/
diff --git a/projects/exiv2/build.sh b/projects/exiv2/build.sh
new file mode 100755
index 0000000..568d851
--- /dev/null
+++ b/projects/exiv2/build.sh
@@ -0,0 +1,38 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Added to fix a false positive result: https://github.com/google/oss-fuzz/issues/6489
+CXXFLAGS="${CXXFLAGS} -fno-sanitize=float-divide-by-zero"
+
+# Build Exiv2
+mkdir -p build
+cd build
+cmake -DEXIV2_ENABLE_PNG=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=OFF -DEXIV2_ENABLE_BMFF=ON -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_COMPILER="${CXX}" -DCMAKE_CXX_FLAGS="${CXXFLAGS}" -DEXIV2_BUILD_FUZZ_TESTS=ON -DEXIV2_TEAM_OSS_FUZZ=ON -DLIB_FUZZING_ENGINE="${LIB_FUZZING_ENGINE}" ..
+make -j $(nproc)
+
+# Copy binary and dictionary to $OUT
+cp ./bin/fuzz-read-print-write $OUT
+cp ../fuzz/exiv2.dict $OUT/fuzz-read-print-write.dict
+
+# Initialize the corpus, using the files in test/data
+mkdir corpus
+for f in $(find ../test/data -type f -size -20k); do
+    s=$(sha1sum "$f" | awk '{print $1}')
+    cp $f corpus/$s
+done
+
+zip -j $OUT/fuzz-read-print-write.zip corpus/*
diff --git a/projects/exiv2/project.yaml b/projects/exiv2/project.yaml
new file mode 100644
index 0000000..29838ab
--- /dev/null
+++ b/projects/exiv2/project.yaml
@@ -0,0 +1,9 @@
+homepage: "https://www.exiv2.org"
+language: c++
+primary_contact: "kevinbackhouse@github.com"
+sanitizers:
+  - address
+  - undefined
+architectures:
+  - x86_64
+main_repo: 'https://github.com/Exiv2/exiv2'
diff --git a/projects/exprtk/project.yaml b/projects/exprtk/project.yaml
index ac0747e..ec2f750 100644
--- a/projects/exprtk/project.yaml
+++ b/projects/exprtk/project.yaml
@@ -10,5 +10,6 @@
 sanitizers:
     - address
     - undefined
-    - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
 main_repo: 'https://github.com/ArashPartow/exprtk.git'
diff --git a/projects/fast-dds/Dockerfile b/projects/fast-dds/Dockerfile
index df5782e..414d421 100644
--- a/projects/fast-dds/Dockerfile
+++ b/projects/fast-dds/Dockerfile
@@ -21,6 +21,5 @@
 RUN git clone --depth 1 https://github.com/eProsima/Fast-CDR.git
 RUN git clone --depth 1 https://github.com/eProsima/foonathan_memory_vendor.git
 RUN git clone --depth 1 https://github.com/eProsima/Fast-DDS.git
-COPY patch.diff $SRC
 COPY build.sh $SRC
 WORKDIR $SRC/Fast-DDS
diff --git a/projects/fast-dds/build.sh b/projects/fast-dds/build.sh
index 6831dff..74c460f 100755
--- a/projects/fast-dds/build.sh
+++ b/projects/fast-dds/build.sh
@@ -18,6 +18,7 @@
 
 (
 cd ../tinyxml2
+make clean
 make -j$(nproc) all
 cp libtinyxml2.a /usr/local/lib/
 cp *.h /usr/local/include/
@@ -46,7 +47,6 @@
 )
 
 # build project
-git apply ../patch.diff
 mkdir build && cd build
 cmake .. -DBUILD_SHARED_LIBS=OFF
 make -j $(nproc)
diff --git a/projects/fast-dds/patch.diff b/projects/fast-dds/patch.diff
deleted file mode 100644
index e4f0ba2..0000000
--- a/projects/fast-dds/patch.diff
+++ /dev/null
@@ -1,74 +0,0 @@
-diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index b7fb777..615e955 100644
---- a/src/cpp/CMakeLists.txt
-+++ b/src/cpp/CMakeLists.txt
-@@ -484,6 +484,11 @@ elseif(NOT EPROSIMA_INSTALLER)
-     endif()
- endif()
- 
-+if(DEFINED ENV{LIB_FUZZING_ENGINE})
-+  add_executable(fuzz_processCDRMsg rtps/messages/fuzz_processCDRMsg.cpp)
-+  target_link_libraries(fuzz_processCDRMsg ${PROJECT_NAME} $ENV{LIB_FUZZING_ENGINE})
-+endif()
-+
- ###############################################################################
- # Packaging
- ###############################################################################
-diff --git a/src/cpp/rtps/messages/MessageReceiver.cpp b/src/cpp/rtps/messages/MessageReceiver.cpp
-index 962ca9b..0e82082 100644
---- a/src/cpp/rtps/messages/MessageReceiver.cpp
-+++ b/src/cpp/rtps/messages/MessageReceiver.cpp
-@@ -324,7 +324,11 @@ void MessageReceiver::processCDRMsg(
- 
-     reset();
- 
-+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+    GuidPrefix_t participantGuidPrefix;
-+#else
-     GuidPrefix_t participantGuidPrefix = participant_->getGuid().guidPrefix;
-+#endif
-     dest_guid_prefix_ = participantGuidPrefix;
- 
-     msg->pos = 0; //Start reading at 0
-@@ -513,7 +517,9 @@ void MessageReceiver::processCDRMsg(
-         submessage->pos = next_msg_pos;
-     }
- 
-+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-     participant_->assert_remote_participant_liveliness(source_guid_prefix_);
-+#endif
- }
- 
- bool MessageReceiver::checkRTPSHeader(
-diff --git a/src/cpp/rtps/messages/fuzz_processCDRMsg.cpp b/src/cpp/rtps/messages/fuzz_processCDRMsg.cpp
-new file mode 100644
-index 0000000..6a71817
---- /dev/null
-+++ b/src/cpp/rtps/messages/fuzz_processCDRMsg.cpp
-@@ -0,0 +1,26 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <stdarg.h>
-+#include <string.h>
-+
-+#include <fastrtps/rtps/messages/MessageReceiver.h>
-+#include <fastdds/rtps/attributes/RTPSParticipantAttributes.h>
-+
-+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-+    const eprosima::fastrtps::rtps::Locator_t remoteLocator;
-+    eprosima::fastrtps::rtps::MessageReceiver* rcv = new eprosima::fastrtps::rtps::MessageReceiver(NULL, 4096);
-+
-+    eprosima::fastrtps::rtps::CDRMessage_t msg(0);
-+    msg.wraps = true;
-+    msg.buffer = const_cast<eprosima::fastrtps::rtps::octet*>(data);
-+    msg.length = size;
-+    msg.max_size = size;
-+    msg.reserved_size = size;
-+
-+    // TODO: Should we unlock in case UnregisterReceiver is called from callback ?
-+    rcv->processCDRMsg(remoteLocator, &msg);
-+    delete rcv;
-+    return 0;
-+}
-+
diff --git a/projects/fasthttp/Dockerfile b/projects/fasthttp/Dockerfile
index 3684706..6edf310 100644
--- a/projects/fasthttp/Dockerfile
+++ b/projects/fasthttp/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/valyala/fasthttp
 
 COPY build.sh $SRC/
diff --git a/projects/fastjson/Dockerfile b/projects/fastjson/Dockerfile
index 9c19614..a616333 100644
--- a/projects/fastjson/Dockerfile
+++ b/projects/fastjson/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/valyala/fastjson
 
 COPY build.sh $SRC/
diff --git a/projects/fastjson2/Dockerfile b/projects/fastjson2/Dockerfile
index e8c9f4e..ba6eae0 100644
--- a/projects/fastjson2/Dockerfile
+++ b/projects/fastjson2/Dockerfile
@@ -15,7 +15,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
 RUN apt-get update && apt-get install -y maven
 
 RUN git clone --depth 1 https://github.com/google/fuzzing && \
diff --git a/projects/fastjson2/build.sh b/projects/fastjson2/build.sh
index 121c324..56f2f2d 100644
--- a/projects/fastjson2/build.sh
+++ b/projects/fastjson2/build.sh
@@ -47,5 +47,5 @@
 --target_class=$fuzzer_basename \
 --jvm_args=\"-Xmx2048m\" \
 \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/ffmpeg/Dockerfile b/projects/ffmpeg/Dockerfile
index bb0bb58..552cd32 100644
--- a/projects/ffmpeg/Dockerfile
+++ b/projects/ffmpeg/Dockerfile
@@ -15,11 +15,9 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-ADD bionic.list /etc/apt/sources.list.d/bionic.list
-ADD nasm_apt.pin /etc/apt/preferences
 RUN apt-get update && apt-get install -y make autoconf automake libtool build-essential \
     libass-dev libfreetype6-dev libsdl1.2-dev \
-    libvdpau-dev libxcb1-dev libxcb-shm0-dev \
+    libvdpau-dev libxcb1-dev libxcb-shm0-dev libdrm-dev \
     pkg-config texinfo libbz2-dev zlib1g-dev yasm cmake mercurial wget \
     xutils-dev libpciaccess-dev nasm rsync
 
@@ -28,7 +26,6 @@
 RUN wget https://www.alsa-project.org/files/pub/lib/alsa-lib-1.1.0.tar.bz2
 RUN git clone --depth 1 https://github.com/mstorsjo/fdk-aac.git
 RUN git clone --depth 1 git://anongit.freedesktop.org/xorg/lib/libXext
-RUN git clone --depth 1 git://anongit.freedesktop.org/git/xorg/lib/libXfixes
 RUN git clone --depth 1 https://github.com/intel/libva
 RUN git clone --depth 1 -b libvdpau-1.2 git://people.freedesktop.org/~aplattner/libvdpau
 RUN git clone --depth 1 https://chromium.googlesource.com/webm/libvpx
diff --git a/projects/ffmpeg/bionic.list b/projects/ffmpeg/bionic.list
deleted file mode 100644
index 8621803..0000000
--- a/projects/ffmpeg/bionic.list
+++ /dev/null
@@ -1,2 +0,0 @@
-# use nasm 2.13.02 from bionic
-deb http://archive.ubuntu.com/ubuntu/ bionic universe
diff --git a/projects/ffmpeg/build.sh b/projects/ffmpeg/build.sh
index 90da59c..2e43242 100755
--- a/projects/ffmpeg/build.sh
+++ b/projects/ffmpeg/build.sh
@@ -29,6 +29,7 @@
 cd $SRC
 bzip2 -f -d alsa-lib-*
 tar xf alsa-lib-*
+rm alsa-lib-*.tar
 cd alsa-lib-*
 ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-shared
 make clean
@@ -50,13 +51,6 @@
 make -j$(nproc)
 make install
 
-cd $SRC/libXfixes
-./autogen.sh
-./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static
-make clean
-make -j$(nproc)
-make install
-
 cd $SRC/libva
 ./autogen.sh
 ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-shared
@@ -145,7 +139,7 @@
 make clean
 make -j$(nproc) install
 
-# Download test sampes, will be used as seed corpus.
+# Download test samples, will be used as seed corpus.
 # DISABLED.
 # TODO: implement a better way to maintain a minimized seed corpora
 # for all targets. As of 2017-05-04 now the combined size of corpora
@@ -162,6 +156,10 @@
 export TEMP_VAR_CODEC_TYPE="VIDEO"
 
 CONDITIONALS=`grep 'BSF 1$' config.h | sed 's/#define CONFIG_\(.*\)_BSF 1/\1/'`
+if [ -n "${OSS_FUZZ_CI-}" ]; then
+  # When running in CI, check the first targets only to save time and disk space
+  CONDITIONALS=( ${CONDITIONALS[@]:0:2} )
+fi
 for c in $CONDITIONALS ; do
   fuzzer_name=ffmpeg_BSF_${c}_fuzzer
   symbol=`echo $c | sed "s/.*/\L\0/"`
@@ -172,6 +170,10 @@
 
 # Build fuzzers for decoders.
 CONDITIONALS=`grep 'DECODER 1$' config.h | sed 's/#define CONFIG_\(.*\)_DECODER 1/\1/'`
+if [ -n "${OSS_FUZZ_CI-}" ]; then
+  # When running in CI, check the first targets only to save time and disk space
+  CONDITIONALS=( ${CONDITIONALS[@]:0:2} )
+fi
 for c in $CONDITIONALS ; do
   fuzzer_name=ffmpeg_AV_CODEC_ID_${c}_fuzzer
   symbol=`echo $c | sed "s/.*/\L\0/"`
@@ -192,6 +194,7 @@
 rm `find fate-suite -name '*.pcm'`
 
 zip -r $OUT/${fuzzer_name}_seed_corpus.zip fate-suite
+zip -r $OUT/ffmpeg_AV_CODEC_ID_HEVC_fuzzer_seed_corpus.zip fate-suite/hevc fate-suite/hevc-conformance
 
 # Build fuzzer for demuxer fed at IO level
 fuzzer_name=ffmpeg_IO_DEMUXER_fuzzer
@@ -229,6 +232,10 @@
     --disable-demuxer=rtp,rtsp,sdp \
 
 CONDITIONALS=`grep 'DEMUXER 1$' config.h | sed 's/#define CONFIG_\(.*\)_DEMUXER 1/\1/'`
+if [ -n "${OSS_FUZZ_CI-}" ]; then
+  # When running in CI, check the first targets only to save time and disk space
+  CONDITIONALS=( ${CONDITIONALS[@]:0:2} )
+fi
 for c in $CONDITIONALS ; do
   fuzzer_name=ffmpeg_dem_${c}_fuzzer
   symbol=`echo $c | sed "s/.*/\L\0/"`
diff --git a/projects/ffmpeg/nasm_apt.pin b/projects/ffmpeg/nasm_apt.pin
deleted file mode 100644
index 6909902..0000000
--- a/projects/ffmpeg/nasm_apt.pin
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: *
-Pin: release n=bionic
-Pin-Priority: 1
-
-Package: nasm
-Pin: release n=bionic
-Pin-Priority: 555
diff --git a/projects/file/project.yaml b/projects/file/project.yaml
index d051847..e148c56 100644
--- a/projects/file/project.yaml
+++ b/projects/file/project.yaml
@@ -3,7 +3,8 @@
 primary_contact: "zoulasc@gmail.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
   - undefined
 architectures:
   - x86_64
diff --git a/projects/firefox/Dockerfile b/projects/firefox/Dockerfile
index 1d19ca8..515e9df 100644
--- a/projects/firefox/Dockerfile
+++ b/projects/firefox/Dockerfile
@@ -15,13 +15,16 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
-RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
-  gawk \
-  libstdc++6 \
-  m4 \
-  python \
-  software-properties-common
+RUN apt-get update && \
+    apt-get install -y software-properties-common && \
+    add-apt-repository -y ppa:ubuntu-toolchain-r/test && \
+    apt-get update && \
+    apt-get upgrade -y && \
+    apt-get install -y --no-install-recommends \
+      gawk \
+      libstdc++6 \
+      m4 \
+      python
 
 # This wrapper of cargo seems to interfere with our build system.
 RUN rm -f /usr/local/bin/cargo
diff --git a/projects/flac/build.sh b/projects/flac/build.sh
index c94ba22..3ccf549 100755
--- a/projects/flac/build.sh
+++ b/projects/flac/build.sh
@@ -53,7 +53,7 @@
 
 # Build fuzzers
 cd $SRC/flac-fuzzers/
-$CXX $CXXFLAGS -I $SRC/flac/include/ -I $SRC/ExoPlayer/extensions/flac/src/main/jni/ -I /usr/lib/jvm/java-8-openjdk-amd64/include/ -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux/ fuzzer_exo.cpp \
+$CXX $CXXFLAGS -I $SRC/flac/include/ -I $SRC/ExoPlayer/extensions/flac/src/main/jni/ -I /usr/lib/jvm/java-11-openjdk-amd64/include/ -I /usr/lib/jvm/java-11-openjdk-amd64/include/linux/ fuzzer_exo.cpp \
     $SRC/flac/src/libFLAC++/.libs/libFLAC++.a $SRC/flac/src/libFLAC/.libs/libFLAC.a $SRC/libogg-install/lib/libogg.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer_exo
 $CXX $CXXFLAGS -I $SRC/flac/include/ fuzzer_decoder.cpp $SRC/flac/src/libFLAC++/.libs/libFLAC++.a $SRC/flac/src/libFLAC/.libs/libFLAC.a $SRC/libogg-install/lib/libogg.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer_decoder
 $CXX $CXXFLAGS -I $SRC/flac/include/ fuzzer_encoder.cpp $SRC/flac/src/libFLAC++/.libs/libFLAC++.a $SRC/flac/src/libFLAC/.libs/libFLAC.a $SRC/libogg-install/lib/libogg.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer_encoder
diff --git a/projects/flatbuffers/Dockerfile b/projects/flatbuffers/Dockerfile
index d51dac7..83caf67 100644
--- a/projects/flatbuffers/Dockerfile
+++ b/projects/flatbuffers/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make cmake ninja
+RUN apt-get update && apt-get install -y make cmake
 RUN git clone https://github.com/google/flatbuffers
 
 WORKDIR $SRC/
diff --git a/projects/flate2-rs/Dockerfile b/projects/flate2-rs/Dockerfile
new file mode 100644
index 0000000..1309ff0
--- /dev/null
+++ b/projects/flate2-rs/Dockerfile
@@ -0,0 +1,19 @@
+# Copyright 2021 Google LL
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+RUN git clone --depth 1 https://github.com/rust-lang/flate2-rs
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/flate2-rs/build.sh b/projects/flate2-rs/build.sh
new file mode 100644
index 0000000..c0ee06a
--- /dev/null
+++ b/projects/flate2-rs/build.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd $SRC/flate2-rs
+cargo fuzz build -O
+cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_gz_roundtrip $OUT/fuzz_gz_roundtrip
diff --git a/projects/flate2-rs/project.yaml b/projects/flate2-rs/project.yaml
new file mode 100644
index 0000000..05a29a9
--- /dev/null
+++ b/projects/flate2-rs/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/rust-lang/flate2-rs"
+main_repo: "https://github.com/rust-lang/flate2-rs"
+primary_contact: "david@adalogics.com"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "alex@alexcrichton.com"
diff --git a/projects/fluent-bit/build.sh b/projects/fluent-bit/build.sh
index e68e5b8..bf5aac3 100755
--- a/projects/fluent-bit/build.sh
+++ b/projects/fluent-bit/build.sh
@@ -14,7 +14,11 @@
 # limitations under the License.
 #
 ################################################################################
-cd fluent-bit/build
+cd fluent-bit
+sed -i 's/malloc(/fuzz_malloc(/g' ./lib/msgpack-c/src/zone.c
+sed -i 's/struct msgpack_zone_chunk {/void *fuzz_malloc(size_t size) {if (size > 0xa00000) return NULL;\nreturn malloc(size);}\nstruct msgpack_zone_chunk {/g' ./lib/msgpack-c/src/zone.c
+
+cd build
 
 export CFLAGS="$CFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON"
 export CXXFLAGS="$CXXFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON"
@@ -23,8 +27,14 @@
 INPUT_PLUGINS="-DFLB_IN_COLLECTD=OFF -DFLB_IN_CPU=OFF -DFLB_IN_DISK=OFF -DFLB_IN_DOCKER=OFF -DFLB_IN_EXEC=OFF -DFLB_IN_FORWARD=OFF -DFLB_IN_HEAD=OFF -DFLB_IN_HEALTH=OFF -DFLB_IN_KMSG=OFF -DFLB_IN_MEM=OFF -DFLB_IN_MQTT=OFF -DFLB_IN_NETIF=OFF -DFLB_IN_PROC=OFF -DFLB_IN_RANDOM=OFF -DFLB_IN_SERIAL=OFF -DFLB_IN_STDIN=OFF -DFLB_IN_SYSLOG=OFF -DFLB_IN_SYSTEMD=OFF -DFLB_IN_TAIL=OFF -DFLB_IN_TCP=OFF -DFLB_IN_THERMAL=OFF -DFLB_IN_WINLOG=OFF"
 OUTPUT_PLUGINS="-DFLB_STREAM_PROCESSOR=Off -DFLB_LUAJIT=OFF -DFLB_FILTER_GREP=OFF -DFLB_FILTER_REWRITE_TAG=OFF -DFLB_OUT_AZURE=OFF -DFLB_OUT_BIGQUERY=OFF -DFLB_OUT_COUNTER=OFF -DFLB_OUT_DATADOG=OFF -DFLB_OUT_ES=OFF -DFLB_OUT_FILE=OFF -DFLB_OUT_FLOWCOUNTER=OFF -DFLB_OUT_FORWARD=OFF -DFLB_OUT_GELF=OFF -DFLB_OUT_HTTP=OFF -DFLB_OUT_INFLUXDB=OFF -DFLB_OUT_KAFKA=OFF -DFLB_OUT_KAFKA_REST=OFF -DFLB_OUT_NATS=OFF -DFLB_OUT_NULL=OFF -DFLB_OUT_PGSQL=OFF -DFLB_OUT_PLOT=OFF -DFLB_OUT_SLACK=OFF -DFLB_OUT_SPLUNK=OFF -DFLB_OUT_STACKDRIVER=OFF -DFLB_OUT_STDOUT=OFF -DFLB_OUT_TCP=OFF -DFLB_OUT_SYSLOG=OFF -DFLB_OUT_NRLOGS=OFF  -DFLB_OUT_LOKI=OFF"
 FILTER_PLUGINS="-DFLB_FILTER_PARSER=ON  -DFLB_FILTER_RECORD_MODIFIER=OFF -DFLB_FILTER_MODIFY=OFF -DFLB_FILTER_THROTTLE=OFF -DFLB_FILTER_KUBERNETES=OFF -DFLB_FILTER_NEST=OFF -DFLB_FILTER_PARSER=OFF -DFLB_FILTER_AWS=OFF -DFLB_FILTER_ALTER_SIZE=OFF"
-
-cmake -DFLB_METRICS=ON -DFLB_DEBUG=On -DMBEDTLS_FATAL_WARNINGS=OFF -DFLB_TESTS_INTERNAL=ON -DFLB_TESTS_INTERNAL_FUZZ=ON -DFLB_TESTS_OSSFUZZ=ON ${INPUT_PLUGINS} ${FILTER_PLUGINS} ${OUTPUT_PLUGINS} ..
+EXTRA_FLAGS="-DFLB_BINARY=OFF -DFLB_EXAMPLES=OFF DFLB_METRICS=ON -DFLB_DEBUG=On -DMBEDTLS_FATAL_WARNINGS=OFF"
+cmake -DFLB_TESTS_INTERNAL=ON \
+      -DFLB_TESTS_INTERNAL_FUZZ=ON \
+      -DFLB_TESTS_OSSFUZZ=ON \
+      ${EXTRA_FLAGS} \
+      ${INPUT_PLUGINS} \
+      ${FILTER_PLUGINS} \
+      ${OUTPUT_PLUGINS} ..
 make
 
 # Create options files
diff --git a/projects/fluent-bit/project.yaml b/projects/fluent-bit/project.yaml
index aca7ccc..968e23a 100755
--- a/projects/fluent-bit/project.yaml
+++ b/projects/fluent-bit/project.yaml
@@ -4,4 +4,5 @@
 auto_ccs:
   - "david@adalogics.com"
   - "wppttt@amazon.com"
+  - "zh0512xx@gmail.com"
 main_repo: 'https://github.com/fluent/fluent-bit/'
diff --git a/projects/freeradius/Dockerfile b/projects/freeradius/Dockerfile
new file mode 100644
index 0000000..083532e
--- /dev/null
+++ b/projects/freeradius/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt install -y libtalloc-dev libkqueue-dev
+
+# OpenSSL 1.1
+ARG OPENSSL_VERSION=1.1.1g
+ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
+RUN set -ex \
+    && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
+    && echo "${OPENSSL_HASH}  openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
+    && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
+    && cd openssl-${OPENSSL_VERSION} \
+    && ./Configure linux-x86_64 no-shared --static "$CFLAGS" \
+    && make build_generated \
+    && make libcrypto.a \
+    && make install
+ENV OPENSSL_ROOT_DIR=/usr/local/openssl-${OPENSSL_VERSION}
+
+RUN git clone --depth 1 https://github.com/FreeRADIUS/freeradius-server.git
+COPY build.sh $SRC
+COPY patch.diff $SRC
+WORKDIR $SRC/freeradius-server
diff --git a/projects/freeradius/build.sh b/projects/freeradius/build.sh
new file mode 100755
index 0000000..17f2c0a
--- /dev/null
+++ b/projects/freeradius/build.sh
@@ -0,0 +1,45 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+function copy_lib
+    {
+    local fuzzer_path=$1
+    local lib=$2
+    cp $(ldd ${fuzzer_path} | grep "${lib}" | awk '{ print $3 }') ${OUT}/lib
+    }
+
+mkdir -p $OUT/lib
+
+git apply --ignore-whitespace $SRC/patch.diff
+# build project
+./configure --enable-fuzzer --enable-address-sanitizer
+# make tries to compile regular programs as fuzz targets
+# so -i flag ignores these errors
+make -i -j$(nproc)
+make -i install
+# use shared libraries
+ldconfig
+ls ./build/bin/local/fuzzer_* | while read i; do
+    patchelf --set-rpath '$ORIGIN/lib' ${i}
+    copy_lib ${i} libfreeradius
+    copy_lib ${i} talloc
+    copy_lib ${i} kqueue
+    cp ${i} $OUT/
+done
+cp -r /usr/local/share/freeradius/dictionary $OUT/dict
+# export FR_DICTIONARY_DIR=/out/dictionary/
+# export FR_LIBRARY_PATH=/out/lib/
diff --git a/projects/freeradius/patch.diff b/projects/freeradius/patch.diff
new file mode 100644
index 0000000..5436820
--- /dev/null
+++ b/projects/freeradius/patch.diff
@@ -0,0 +1,64 @@
+diff --git a/configure.ac b/configure.ac
+index 56e9600..ad488e8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -21,7 +21,7 @@ dnl #
+ dnl #############################################################
+ 
+ AC_PREREQ([2.59])
+-export CFLAGS LIBS LDFLAGS CPPFLAGS
++#export CFLAGS LIBS LDFLAGS CPPFLAGS
+ 
+ AC_INIT([freeradius],[$]Id[$],[http://bugs.freeradius.org],,[http://www.freeradius.org])
+ AC_CONFIG_SRCDIR([src/bin/radiusd.c])
+@@ -185,7 +185,7 @@ dnl #  -g3 so nice things like macro values are included. Other arguments are
+ dnl #  added later when we know what compiler were using.
+ dnl #
+ if test "x$developer" = "xyes"; then
+-  : ${CFLAGS=-g3}
++  : ${CFLAGS="$CFLAGS -g3"}
+ fi
+ 
+ dnl #
+
+diff --git a/src/bin/fuzzer.c b/src/bin/fuzzer.c
+index 9c2eb50..82d6fd6 100644
+--- a/src/bin/fuzzer.c
++++ b/src/bin/fuzzer.c
+@@ -125,7 +125,21 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
+                }
+        }
+ 
+-       if (!dict_dir) dict_dir = DICTDIR;
++       int free_dict = 0;
++       int free_lib = 0;
++       if (!dict_dir) {
++               dict_dir = malloc(strlen((*argv)[0]) + 1);
++               memcpy(dict_dir, (*argv)[0], strlen((*argv)[0]) + 1);
++               snprintf(strrchr(dict_dir, '/'), 6, "/dict");
++               free_dict = 1;
++       }
++       if (!lib_dir) {
++                lib_dir = malloc(strlen((*argv)[0]) + 1);
++                memcpy(lib_dir, (*argv)[0], strlen((*argv)[0]) + 1);
++                snprintf(strrchr(lib_dir, '/'), 5, "/lib");
++                setenv("FR_LIBRARY_PATH", lib_dir, 1);
++                free_lib = 1;
++       }
+ 
+        /*
+         *      When jobs=N is specified the fuzzer spawns worker processes via
+@@ -182,6 +196,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
+ 
+        init = true;
+ 
++        if (free_lib) {
++                free(lib_dir);
++        }
++        if (free_dict) {
++                free(dict_dir);
++        }
++
+        return 1;
+ }
+ 
diff --git a/projects/freeradius/project.yaml b/projects/freeradius/project.yaml
new file mode 100644
index 0000000..a04dae5
--- /dev/null
+++ b/projects/freeradius/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://freeradius.org"
+language: c++
+primary_contact: "a.cudbardb@gmail.com"
+auto_ccs:
+- "adekok@gmail.com"
+- "p.antoine@catenacyber.fr"
+main_repo: 'https://github.com/FreeRADIUS/freeradius-server.git'
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
diff --git a/projects/freetype2/project.yaml b/projects/freetype2/project.yaml
index 9649772..c747e1b 100644
--- a/projects/freetype2/project.yaml
+++ b/projects/freetype2/project.yaml
@@ -2,7 +2,6 @@
 language: c++
 primary_contact: "lemzwerg@gmail.com"
 auto_ccs:
-  - "darnold@adobe.com"
   - "lemzwerg@googlemail.com"
   - "HinTak.Leung@gmail.com"
   - "ewaldhew@gmail.com"
diff --git a/projects/fribidi/Dockerfile b/projects/fribidi/Dockerfile
new file mode 100644
index 0000000..b4d9ea7
--- /dev/null
+++ b/projects/fribidi/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y python3-pip pkg-config && \
+    pip3 install meson==0.53.0 ninja
+RUN git clone --depth 1 https://github.com/fribidi/fribidi.git
+WORKDIR fribidi
+COPY build.sh $SRC/
diff --git a/projects/fribidi/build.sh b/projects/fribidi/build.sh
new file mode 100755
index 0000000..aa8f60a
--- /dev/null
+++ b/projects/fribidi/build.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# setup
+build=$WORK/build
+
+# cleanup
+rm -rf $build
+mkdir -p $build
+
+# Build the library.
+meson --default-library=static --wrap-mode=nodownload -Ddocs=false \
+      -Dfuzzer_ldflags="$(echo $LIB_FUZZING_ENGINE)" \
+      $build \
+  || (cat build/meson-logs/meson-log.txt && false)
+
+# Build the fuzzers.
+ninja -v -j$(nproc) -C $build bin/fribidi-fuzzer
+mv $build/bin/fribidi-fuzzer $OUT/
+
+# Archive and copy to $OUT seed corpus if the build succeeded.
+zip $OUT/fribidi-fuzzer_seed_corpus.zip test/*.{input,reference} test/fuzzing/*
diff --git a/projects/fribidi/project.yaml b/projects/fribidi/project.yaml
new file mode 100644
index 0000000..7fbac3a
--- /dev/null
+++ b/projects/fribidi/project.yaml
@@ -0,0 +1,17 @@
+homepage: "https://github.com/fribidi/fribidi"
+language: c
+primary_contact: "dov.grobgeld@gmail.com"
+auto_ccs:
+  - "behdad.esfahbod@gmail.com"
+  - "behdad@gnu.org"
+  - "ebrahim@gnu.org"
+  - "dr.khaled.hosny@gmail.com"
+fuzzing_engines:
+  - libfuzzer
+  - afl
+  - honggfuzz
+sanitizers:
+  - address
+  - undefined
+  - memory
+main_repo: 'https://github.com/fribidi/fribidi.git'
diff --git a/projects/frr/Dockerfile b/projects/frr/Dockerfile
new file mode 100644
index 0000000..3286cc6
--- /dev/null
+++ b/projects/frr/Dockerfile
@@ -0,0 +1,30 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN apt-get update && apt-get install -y git autoconf automake libtool make \
+   libreadline-dev texinfo libjson-c-dev pkg-config bison flex python3-pip \
+   libc-ares-dev python3-dev python3-sphinx build-essential libsystemd-dev \
+   libsnmp-dev libcap-dev libelf-dev libpcre3-dev libpcre2-dev
+RUN pip3 install pytest
+RUN git clone https://github.com/CESNET/libyang.git
+
+RUN git clone --depth 1 --branch fuzz https://github.com/FRRouting/frr
+
+RUN git clone --depth 1 https://github.com/qlyoung/corpi
+COPY build.sh $SRC
+WORKDIR $SRC/frr
diff --git a/projects/frr/build.sh b/projects/frr/build.sh
new file mode 100755
index 0000000..ad1584e
--- /dev/null
+++ b/projects/frr/build.sh
@@ -0,0 +1,63 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+function copy_lib
+    {
+    local fuzzer_path=$1
+    local lib=$2
+    cp $(ldd ${fuzzer_path} | grep "${lib}" | awk '{ print $3 }') ${OUT}/lib/ || true
+    }
+
+mkdir -p $OUT/lib
+
+# build dependency
+(
+cd $SRC/libyang
+mkdir build; cd build
+cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+    -D CMAKE_BUILD_TYPE:String="Release" ..
+make -j$(nproc)
+make install
+)
+
+# build project
+export ASAN_OPTIONS=detect_leaks=0
+./bootstrap.sh
+./configure --enable-libfuzzer --enable-static --enable-static-bin --sbindir=$SRC/bin
+make -j$(nproc)
+make install
+cp ./lib/.libs/libfrr.so.0 $OUT/lib/
+cp $SRC/bin/bgpd $OUT/
+cp $SRC/bin/ospfd $OUT/
+cp $SRC/bin/pimd $OUT/
+cp $SRC/bin/zebra $OUT/
+
+# build corpus
+cd $SRC/corpi
+find . -type d -maxdepth 1 | while read i; do zip -j $OUT/"$i"_seed_corpus.zip "$i"/*; done
+
+find $OUT -maxdepth 1 -type f -executable | while read i; do
+    grep "LLVMFuzzerTestOneInput" ${i} > /dev/null 2>&1 || continue
+    patchelf --set-rpath '$ORIGIN/lib' ${i}
+    copy_lib ${i} libpcre2
+    copy_lib ${i} libyang
+    copy_lib ${i} libelf
+    copy_lib ${i} libjson-c
+done
+
+patchelf --remove-needed libpcre2-8.so.0 $OUT/lib/libyang.so.2
diff --git a/projects/frr/project.yaml b/projects/frr/project.yaml
new file mode 100644
index 0000000..8955c4f
--- /dev/null
+++ b/projects/frr/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://frrouting.org"
+language: c++
+primary_contact: "security@lists.frrouting.org"
+auto_ccs:
+- "qlyoung@qlyoung.net"
+- "equinox-ossfuzz@diac24.net"
+- "menotdonald@gmail.com"
+- "mjs.ietf@gmail.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: 'https://github.com/FRRouting/frr'
diff --git a/projects/gcloud-go/Dockerfile b/projects/gcloud-go/Dockerfile
index 1d2b38e..fe2f3b2 100644
--- a/projects/gcloud-go/Dockerfile
+++ b/projects/gcloud-go/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 LABEL maintainer="codyoss@google.com"
 RUN go get cloud.google.com/go/spanner
 COPY build.sh $SRC/
diff --git a/projects/gdal/project.yaml b/projects/gdal/project.yaml
index d0bbfe4..447fe10 100644
--- a/projects/gdal/project.yaml
+++ b/projects/gdal/project.yaml
@@ -9,6 +9,7 @@
   - "athomas@thinkspatial.com.au"
   - "ari.jolma@gmail.com"
   - "bjorn.harrtell@gmail.com"
+  - "nyall.dawson@gmail.com"
 architectures:
   - x86_64
   - i386
diff --git a/projects/gdbm/Dockerfile b/projects/gdbm/Dockerfile
new file mode 100644
index 0000000..69ade39
--- /dev/null
+++ b/projects/gdbm/Dockerfile
@@ -0,0 +1,32 @@
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get -qq update && \
+    apt-get install -qq \
+      build-essential\
+      git\
+      autopoint\
+      automake\
+      autoconf\
+      bison\
+      flex\
+      libtool\
+      texinfo\
+      gettext
+RUN git clone --depth 1 https://git.gnu.org.ua/gdbm.git
+WORKDIR gdbm
+COPY build.sh $SRC/
diff --git a/projects/gdbm/build.sh b/projects/gdbm/build.sh
new file mode 100644
index 0000000..9c21c8e
--- /dev/null
+++ b/projects/gdbm/build.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -eu
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Bootstrap and configure project
+./bootstrap --no-po
+./configure --disable-shared --enable-debug --disable-nls
+# Build project
+make -j$(nproc) all
+# Build fuzzer
+cd fuzz
+$CC $CFLAGS -c -I.. -I../src -ogdbm_fuzzer.o gdbm_fuzzer.c
+$CXX $CFLAGS -ogdbm_fuzzer gdbm_fuzzer.o ../src/libgdbmapp.a ../src/.libs/libgdbm.a $LIB_FUZZING_ENGINE
+
+cp gdbm_fuzzer $OUT
+cp gdbm_fuzzer.rc $OUT
+
+# Create seed
+PATH=$SRC/gdbm/src:$PATH sh ./build_seed.sh -C seed
+zip -rj "$OUT/gdbm_fuzzer_seed_corpus.zip" seed/
diff --git a/projects/gdbm/project.yaml b/projects/gdbm/project.yaml
new file mode 100644
index 0000000..2169eea
--- /dev/null
+++ b/projects/gdbm/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://www.gnu.org.ua/software/gdbm"
+language: c
+primary_contact: "sergey.poznyakoff@gmail.com"
+auto_ccs:
+  - "gray@gnu.org"
+main_repo: "https://git.gnu.org.ua/gdbm.git"
diff --git a/projects/geos/Dockerfile b/projects/geos/Dockerfile
new file mode 100644
index 0000000..a9db2a7
--- /dev/null
+++ b/projects/geos/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y cmake
+# fallback to github if main git server is not responding
+RUN git clone --depth 1 https://git.osgeo.org/gitea/geos/geos.git || git clone --depth 1 https://github.com/libgeos/geos.git
+COPY build.sh $SRC
+COPY patch.diff $SRC
+WORKDIR $SRC/geos
diff --git a/projects/geos/build.sh b/projects/geos/build.sh
new file mode 100755
index 0000000..5d5c59a
--- /dev/null
+++ b/projects/geos/build.sh
@@ -0,0 +1,24 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# build project
+git apply ../patch.diff
+mkdir build
+cd build
+cmake -DBUILD_SHARED_LIBS=OFF ..
+make -j$(nproc)
+cp bin/fuzz* $OUT/
diff --git a/projects/geos/patch.diff b/projects/geos/patch.diff
new file mode 100644
index 0000000..60c13f7
--- /dev/null
+++ b/projects/geos/patch.diff
@@ -0,0 +1,106 @@
+diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
+index 14506516..2e236476 100644
+--- a/tests/CMakeLists.txt
++++ b/tests/CMakeLists.txt
+@@ -11,4 +11,5 @@
+ add_subdirectory(unit)
+ add_subdirectory(xmltester)
+ add_subdirectory(bigtest)
++add_subdirectory(fuzz)
+ 
+diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
+new file mode 100644
+index 00000000..d0bd7a02
+--- /dev/null
++++ b/tests/fuzz/CMakeLists.txt
+@@ -0,0 +1,15 @@
++################################################################################
++# Part of CMake configuration for GEOS
++#
++# Copyright (C) 2018 Mateusz Loskot <mateusz@loskot.net>
++#
++# This is free software; you can redistribute and/or modify it under
++# the terms of the GNU Lesser General Public Licence as published
++# by the Free Software Foundation.
++# See the COPYING file for more information.
++################################################################################
++if(DEFINED ENV{LIB_FUZZING_ENGINE})
++  add_executable(fuzz_geo2 fuzz_geo2.c)
++  target_include_directories(fuzz_geo2 PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>)
++  target_link_libraries(fuzz_geo2 geos_c $ENV{LIB_FUZZING_ENGINE})
++endif()
+diff --git a/tests/fuzz/fuzz_geo2.c b/tests/fuzz/fuzz_geo2.c
+new file mode 100644
+index 00000000..ceee7ea6
+--- /dev/null
++++ b/tests/fuzz/fuzz_geo2.c
+@@ -0,0 +1,69 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdarg.h>
++#include <string.h>
++
++#include "geos_c.h"
++
++static int initialized = 0;
++FILE * flogOut;
++
++void
++notice(const char *fmt, ...) {
++    va_list ap;
++    fprintf( flogOut, "NOTICE: ");
++    va_start (ap, fmt);
++    vfprintf( flogOut, fmt, ap);
++    va_end(ap);
++    fprintf( flogOut, "\n" );
++}
++
++void
++log_and_exit(const char *fmt, ...) {
++    va_list ap;
++    fprintf( flogOut, "ERROR: ");
++    va_start (ap, fmt);
++    vfprintf( flogOut, fmt, ap);
++    va_end(ap);
++    fprintf( flogOut, "\n" );
++}
++
++int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
++    if (initialized == 0) {
++        flogOut = fopen("/dev/null", "wb");
++        initGEOS(notice, log_and_exit);
++        initialized = 1;
++    }
++    size_t sep;
++    for (sep = 0; sep < Size; sep ++) {
++        if (Data[sep] == 0) {
++            break;
++        }
++    }
++    if (sep == Size) {
++        return 0;
++    }
++    GEOSGeometry *g1 = GEOSGeomFromWKT(Data);
++
++    if (g1 != NULL) {
++        GEOSGeometry *g2 = GEOSGeomFromWKB_buf(Data+sep, Size-sep);
++        if (g2 != NULL) {
++            size_t usize;
++            GEOSGeometry *g3 = GEOSIntersection(g1, g2);
++            GEOSGeom_destroy(g3);
++            g3 = GEOSDifference(g1, g2);
++            GEOSGeom_destroy(g3);
++            g3 = GEOSUnion(g1, g2);
++            GEOSGeom_destroy(g3);
++            unsigned char* uptr = GEOSGeomToWKB_buf(g1, &usize);
++            free(uptr);
++            GEOSGeom_destroy(g2);
++        }
++        char * r = GEOSGeomToWKT(g1);
++        free(r);
++        GEOSGeom_destroy(g1);
++    }
++    return 0;
++}
++
diff --git a/projects/geos/project.yaml b/projects/geos/project.yaml
new file mode 100644
index 0000000..91a71eb
--- /dev/null
+++ b/projects/geos/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://geos.osgeo.org"
+language: c++
+primary_contact: "mtnclimb@gmail.com"
+auto_ccs :
+- "strk@kbt.io"
+- "lr@pcorp.us"
+- "p.antoine@catenacyber.fr"
+
+sanitizers:
+- address
+- undefined
+main_repo: 'https://git.osgeo.org/gitea/geos/geos.git'
diff --git a/projects/ghostscript/project.yaml b/projects/ghostscript/project.yaml
index d1f91d4..6a4a2db 100644
--- a/projects/ghostscript/project.yaml
+++ b/projects/ghostscript/project.yaml
@@ -10,5 +10,6 @@
   - "kdlee@chromium.org"
 sanitizers:
   - address
-  - memory
-main_repo: 'git://git.ghostscript.com/ghostpdl.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: 'git://git.ghostscript.com/ghostpdl.git'
\ No newline at end of file
diff --git a/projects/git/Dockerfile b/projects/git/Dockerfile
index 91c05e4..eb48743 100644
--- a/projects/git/Dockerfile
+++ b/projects/git/Dockerfile
@@ -20,7 +20,7 @@
         cvs cvsps gettext libcgi-pm-perl libcurl4-gnutls-dev \
         libdbd-sqlite3-perl liberror-perl libexpat1-dev libhttp-date-perl \
         libio-pty-perl libmailtools-perl libpcre2-dev libpcre3-dev libsvn-perl \
-        libtime-modules-perl libyaml-perl libz-dev python subversion tcl unzip \
+        perl-modules libyaml-perl libz-dev python subversion tcl unzip \
         asciidoc docbook-xsl xmlto libssl-dev zip
 RUN git clone https://github.com/git/git git
 WORKDIR git
diff --git a/projects/gitea/Dockerfile b/projects/gitea/Dockerfile
index 9403123..2defa81 100644
--- a/projects/gitea/Dockerfile
+++ b/projects/gitea/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone https://github.com/go-gitea/gitea
 COPY build.sh $SRC/
 WORKDIR $SRC/gitea
diff --git a/projects/glib/Dockerfile b/projects/glib/Dockerfile
index 72449d5..25b5204 100644
--- a/projects/glib/Dockerfile
+++ b/projects/glib/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y python3-pip
-RUN pip3 install -U meson ninja
+RUN unset CFLAGS CXXFLAGS && pip3 install -U meson ninja
 RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/glib
 WORKDIR glib
 COPY build.sh $SRC/
diff --git a/projects/glib/project.yaml b/projects/glib/project.yaml
index 64889c8..62cb330 100644
--- a/projects/glib/project.yaml
+++ b/projects/glib/project.yaml
@@ -8,6 +8,7 @@
 sanitizers:
 - address
 - undefined
-- memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 help_url: https://gitlab.gnome.org/GNOME/glib/tree/master/fuzzing#how-to-reproduce-oss-fuzz-bugs-locally
-main_repo: 'https://gitlab.gnome.org/GNOME/glib'
+main_repo: 'https://gitlab.gnome.org/GNOME/glib'
\ No newline at end of file
diff --git a/projects/gnupg/Dockerfile b/projects/gnupg/Dockerfile
index 57dc905..5392d97 100644
--- a/projects/gnupg/Dockerfile
+++ b/projects/gnupg/Dockerfile
@@ -16,6 +16,11 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y make autoconf automake libtool gettext bzip2 gnupg bison flex
+# Install automake 1.16.3 from future. See:
+# * https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=commit;h=6ca540715139899137e1f86c7e1dcbd0288f15b3
+# * https://packages.ubuntu.com/en/hirsute/automake
+RUN sed -i -e 's/focal/hirsute/g' /etc/apt/sources.list
+RUN apt-get update && apt-get install -y --reinstall automake
 
 RUN git clone --depth 1 git://git.gnupg.org/libgpg-error.git libgpg-error
 RUN git clone --depth 1 git://git.gnupg.org/libgcrypt.git libgcrypt
diff --git a/projects/gnupg/fuzzgnupg.diff b/projects/gnupg/fuzzgnupg.diff
index 226c86c..f736fae 100644
--- a/projects/gnupg/fuzzgnupg.diff
+++ b/projects/gnupg/fuzzgnupg.diff
@@ -1,10 +1,10 @@
 diff --git a/configure.ac b/configure.ac
-index 5bb366e76..ee9403149 100644
+index 7b398f3df..ee69b3063 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -991,6 +991,15 @@ AC_CHECK_LIB(util, openpty,
-              ])
- AC_SUBST(LIBUTIL_LIBS)
+@@ -991,6 +991,15 @@ if test x"$use_tofu" = xyes ; then
+   fi
+ fi
  
 +# TODO choose when to build fuzzing with option ?
 +AC_CHECK_LIB(FuzzingEngine, main,
@@ -15,19 +15,19 @@
 +AC_CHECK_PROG(HAVE_CLANGXX, clang++, 1)
 +AM_CONDITIONAL(HAVE_LIB_FUZZING_ENGINE, [test "$have_fuzz" = yes -a "$HAVE_CLANGXX" = 1])
 +
- # shred is used to clean temporary plain text files.
- AC_PATH_PROG(SHRED, shred, /usr/bin/shred)
- AC_DEFINE_UNQUOTED(SHRED,
-@@ -2094,6 +2103,7 @@ tests/migrations/Makefile
- tests/gpgsm/Makefile
+ AM_CONDITIONAL(SQLITE3, test "$have_sqlite" = "yes")
+ 
+ if test x"$use_tofu" = xyes ; then
+@@ -2149,6 +2158,7 @@ tests/migrations/Makefile
+ tests/tpm2dtests/Makefile
  tests/gpgme/Makefile
  tests/pkits/Makefile
 +tests/fuzz/Makefile
  g10/gpg.w32-manifest
- ])
- 
+ tools/gpg-connect-agent.w32-manifest
+ tools/gpgconf.w32-manifest
 diff --git a/g10/Makefile.am b/g10/Makefile.am
-index 2b92daf33..505d98f5e 100644
+index eb23573b7..785ac2b4b 100644
 --- a/g10/Makefile.am
 +++ b/g10/Makefile.am
 @@ -47,6 +47,7 @@ endif
@@ -38,14 +38,14 @@
  if !HAVE_W32CE_SYSTEM
  noinst_PROGRAMS += gpgv
  endif
-@@ -164,6 +165,9 @@ gpg_SOURCES  = gpg.c \
+@@ -164,6 +165,9 @@ gpg_sources = server.c          \
+ gpg_SOURCES  = gpg.c \
  	keyedit.c keyedit.h	\
  	$(gpg_sources)
- 
 +libgpg_a_SOURCES  = keyedit.c keyedit.h	\
 +	$(gpg_sources)
 +
- #gpgcompose_SOURCES  = gpgcompose.c  $(gpg_sources)
+ 
  gpgv_SOURCES = gpgv.c           \
  	      $(common_source)  \
 diff --git a/g10/armor.c b/g10/armor.c
@@ -63,7 +63,7 @@
  
  
 diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h
-index 285c4cb4d..7af328c2a 100644
+index c0f1e0cec..52652a0e0 100644
 --- a/g10/call-dirmngr.h
 +++ b/g10/call-dirmngr.h
 @@ -19,6 +19,8 @@
@@ -122,10 +122,10 @@
      } while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
               && !leave);
 diff --git a/g10/parse-packet.c b/g10/parse-packet.c
-index 2f92c1d2c..41e077a6a 100644
+index bb05eabb7..638d895d0 100644
 --- a/g10/parse-packet.c
 +++ b/g10/parse-packet.c
-@@ -738,7 +738,12 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
+@@ -806,7 +806,12 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
         * the uncompressing layer - in some error cases it just loops
         * and spits out 0xff bytes. */
        log_error ("%s: garbled packet detected\n", iobuf_where (inp));
@@ -139,10 +139,10 @@
  
    if (out && pkttype)
 diff --git a/g10/plaintext.c b/g10/plaintext.c
-index f9e0a4296..7b9709c08 100644
+index 3e169d93f..aa83ffbe0 100644
 --- a/g10/plaintext.c
 +++ b/g10/plaintext.c
-@@ -656,10 +656,16 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
+@@ -617,10 +617,16 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
  
    if (!fp)
      {
@@ -160,10 +160,10 @@
    do_hash (md, md2, fp, textmode);
    iobuf_close (fp);
 diff --git a/g10/sig-check.c b/g10/sig-check.c
-index 4c172d692..bd87f00ad 100644
+index 8dd18b2e2..9f5db89f9 100644
 --- a/g10/sig-check.c
 +++ b/g10/sig-check.c
-@@ -760,8 +760,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
+@@ -783,8 +783,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
  	    {
                gcry_md_hd_t md;
  
@@ -176,15 +176,15 @@
  	      /* Note: check_signature only checks that the signature
  		 is good.  It does not fail if the key is revoked.  */
 diff --git a/tests/Makefile.am b/tests/Makefile.am
-index b9be6aaa6..d6659eaf1 100644
+index f29b68a53..e788c9916 100644
 --- a/tests/Makefile.am
 +++ b/tests/Makefile.am
-@@ -18,7 +18,13 @@
+@@ -24,7 +24,13 @@ else
+ tpm2dtests =
+ endif
  
- ## Process this file with automake to produce Makefile.in
- 
--SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits .
-+SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits
+-SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests) .
++SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests)
 +
 +if MAINTAINER_MODE
 +SUBDIRS += fuzz
@@ -196,7 +196,7 @@
  
 diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
 new file mode 100644
-index 000000000..3bf039a54
+index 000000000..eb2216d3e
 --- /dev/null
 +++ b/tests/fuzz/Makefile.am
 @@ -0,0 +1,84 @@
diff --git a/projects/gnupg/project.yaml b/projects/gnupg/project.yaml
index c2c6ab2..516132e 100644
--- a/projects/gnupg/project.yaml
+++ b/projects/gnupg/project.yaml
@@ -2,3 +2,6 @@
 language: c++
 primary_contact: "p.antoine@catenacyber.fr"
 main_repo: 'git://git.gnupg.org/gnupg.git'
+fuzzing_engines:
+  - libfuzzer
+  - honggfuzz
diff --git a/projects/gnutls/Dockerfile b/projects/gnutls/Dockerfile
index 4630429..5d90227 100644
--- a/projects/gnutls/Dockerfile
+++ b/projects/gnutls/Dockerfile
@@ -38,7 +38,7 @@
 RUN git clone --depth=1 https://git.savannah.gnu.org/git/libunistring.git
 RUN git clone --depth=1 https://gitlab.com/libidn/libidn2.git
 RUN hg clone https://gmplib.org/repo/gmp/ gmp
-RUN git clone --depth=1 https://gitlab.com/gnutls/libtasn1.git
+RUN git clone https://gitlab.com/gnutls/libtasn1.git
 RUN git clone --depth=1 https://git.lysator.liu.se/nettle/nettle.git
 
 RUN git clone --depth=1 --recursive https://gitlab.com/gnutls/gnutls.git
diff --git a/projects/gnutls/build.sh b/projects/gnutls/build.sh
index a442827..730838c 100755
--- a/projects/gnutls/build.sh
+++ b/projects/gnutls/build.sh
@@ -16,9 +16,9 @@
 ################################################################################
 
 export DEPS_PATH=$SRC/deps
-export PKG_CONFIG_PATH=$DEPS_PATH/lib/pkgconfig
+export PKG_CONFIG_PATH=$DEPS_PATH/lib64/pkgconfig:$DEPS_PATH/lib/pkgconfig
 export CPPFLAGS="-I$DEPS_PATH/include"
-export LDFLAGS="-L$DEPS_PATH/lib"
+export LDFLAGS="-L$DEPS_PATH/lib -L$DEPS_PATH/lib64"
 export GNULIB_SRCDIR=$SRC/gnulib
 
 cd $SRC/libunistring
diff --git a/projects/go-attestation/Dockerfile b/projects/go-attestation/Dockerfile
index 4e1651c..33999be 100644
--- a/projects/go-attestation/Dockerfile
+++ b/projects/go-attestation/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 RUN go get -u -d github.com/google/go-attestation/...
 
diff --git a/projects/go-coredns/Dockerfile b/projects/go-coredns/Dockerfile
index 7991879..8dab305 100644
--- a/projects/go-coredns/Dockerfile
+++ b/projects/go-coredns/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 ENV GO111MODULE=on
 RUN git clone --depth 1  https://github.com/coredns/coredns $GOPATH/src/github.com/coredns/coredns
 
diff --git a/projects/go-dns/Dockerfile b/projects/go-dns/Dockerfile
index a5576e7..3819ff2 100644
--- a/projects/go-dns/Dockerfile
+++ b/projects/go-dns/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN go get -t github.com/miekg/dns
 
 COPY build.sh $SRC/
diff --git a/projects/go-ethereum/Dockerfile b/projects/go-ethereum/Dockerfile
index 8323922..3904fce 100644
--- a/projects/go-ethereum/Dockerfile
+++ b/projects/go-ethereum/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 RUN git clone --single-branch --depth=1 https://github.com/ethereum/go-ethereum $GOPATH/src/github.com/ethereum/go-ethereum 
 RUN (cd $GOPATH/src/github.com/ethereum/go-ethereum && go mod download)
diff --git a/projects/go-ethereum/project.yaml b/projects/go-ethereum/project.yaml
index a4c8532..062e5a1 100644
--- a/projects/go-ethereum/project.yaml
+++ b/projects/go-ethereum/project.yaml
@@ -4,6 +4,8 @@
   - "fjl@ethereum.org"
   - "martin.swende@ethereum.org"
   - "marius.vanderwijden@ethereum.org"
+  - "garyrong@ethereum.org"
+  - "zsfelfoldi@ethereum.org"
 language: go
 fuzzing_engines:
   - libfuzzer
diff --git a/projects/go-json-iterator/Dockerfile b/projects/go-json-iterator/Dockerfile
index 5d4cf02..fa3d930 100644
--- a/projects/go-json-iterator/Dockerfile
+++ b/projects/go-json-iterator/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone https://github.com/json-iterator/go json-iterator
 
 COPY fuzz_json.go $SRC/json-iterator/
diff --git a/projects/go-redis/Dockerfile b/projects/go-redis/Dockerfile
index b0ad177..0bcc651 100644
--- a/projects/go-redis/Dockerfile
+++ b/projects/go-redis/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone https://github.com/go-redis/redis redis
 COPY build.sh $SRC/
 WORKDIR $SRC/redis
diff --git a/projects/go-redis/build.sh b/projects/go-redis/build.sh
index e297cd3..38c2db6 100644
--- a/projects/go-redis/build.sh
+++ b/projects/go-redis/build.sh
@@ -13,5 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#github.com/go-redis/redis/fuzz is not a module, so needs local build
-compile_go_fuzzer ./fuzz Fuzz fuzz gofuzz
+compile_go_fuzzer github.com/go-redis/redis/v8/fuzz Fuzz fuzz gofuzz
diff --git a/projects/go-sftp/Dockerfile b/projects/go-sftp/Dockerfile
index 0269d8e..59c82b2 100644
--- a/projects/go-sftp/Dockerfile
+++ b/projects/go-sftp/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/pkg/sftp
 
 COPY build.sh $SRC/
diff --git a/projects/go-snappy/Dockerfile b/projects/go-snappy/Dockerfile
index d6d08af..59ff120 100644
--- a/projects/go-snappy/Dockerfile
+++ b/projects/go-snappy/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/golang/snappy
 
 COPY build.sh $SRC/
diff --git a/projects/go-snappy/project.yaml b/projects/go-snappy/project.yaml
index 8a732cc..42eca53 100644
--- a/projects/go-snappy/project.yaml
+++ b/projects/go-snappy/project.yaml
@@ -8,3 +8,4 @@
 sanitizers:
   - address
 main_repo: 'https://github.com/golang/snappy'
+disabled: true
diff --git a/projects/go-sqlite3/Dockerfile b/projects/go-sqlite3/Dockerfile
index f1b10e1..e2936b4 100644
--- a/projects/go-sqlite3/Dockerfile
+++ b/projects/go-sqlite3/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 http://github.com/mattn/go-sqlite3 $GOPATH/src/github.com/mattn/go-sqlite3
 
 COPY build.sh $SRC/
diff --git a/projects/golang-protobuf/Dockerfile b/projects/golang-protobuf/Dockerfile
index 1347a76..8c7272e 100644
--- a/projects/golang-protobuf/Dockerfile
+++ b/projects/golang-protobuf/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 ENV GO111MODULE="on"
 ENV GOFUZZ111MODULE="on"
diff --git a/projects/golang/Dockerfile b/projects/golang/Dockerfile
index 1118ce4..ff5cd2f 100644
--- a/projects/golang/Dockerfile
+++ b/projects/golang/Dockerfile
@@ -14,14 +14,9 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
-RUN mkdir -p $GOPATH/src/github.com/dvyukov/ && \
-    cd $GOPATH/src/github.com/dvyukov/ && \
-    git clone https://github.com/dvyukov/go-fuzz-corpus
-
-COPY build.sh $SRC/
-
-ENV GO111MODULE="off"
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus golang
+COPY build.sh text_fuzzer.go math_big_fuzzer.go $SRC/
 
 WORKDIR $SRC/golang
diff --git a/projects/golang/build.sh b/projects/golang/build.sh
index 064378a..99868c4 100755
--- a/projects/golang/build.sh
+++ b/projects/golang/build.sh
@@ -12,41 +12,37 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-function compile_fuzzer {
-  fuzzer=$(basename $1)
+# These two dependencies cause build issues and are not used by oss-fuzz:
+rm -r sqlparser
+rm -r parser
 
-  compile_go_fuzzer "github.com/dvyukov/go-fuzz-corpus/$fuzzer" Fuzz $fuzzer
+mkdir math && cp $SRC/math_big_fuzzer.go ./math/
 
-  # Pack the seed corpus
-  zip -r $OUT/fuzzer-${fuzzer}_seed_corpus.zip \
-      $GOPATH/src/github.com/dvyukov/go-fuzz-corpus/$fuzzer/corpus
-}
+go get -u golang.org/x/text
+mkdir text && cp $SRC/text_fuzzer.go ./text/
 
-export -f compile_fuzzer
-
-# Use this to attempt to compile all
-#find $SRC/go-fuzz-corpus -mindepth 1 -maxdepth 1 -type d -exec bash -c 'compile_fuzzer "$@"' bash {} \;
-
-compile_fuzzer asn1
-#compile_fuzzer bzip2
-compile_fuzzer csv
-compile_fuzzer elliptic
-compile_fuzzer flate
-compile_fuzzer fmt
-#compile_fuzzer gif
-compile_fuzzer gzip
-compile_fuzzer httpreq
-compile_fuzzer httpresp
-compile_fuzzer jpeg
-compile_fuzzer json
-compile_fuzzer lzw
-compile_fuzzer mime
-compile_fuzzer multipart
-compile_fuzzer png
-compile_fuzzer tar
-compile_fuzzer time
-#compile_fuzzer url
-compile_fuzzer xml
-compile_fuzzer zip
-compile_fuzzer zlib
-
+go mod init "github.com/dvyukov/go-fuzz-corpus"
+export FUZZ_ROOT="github.com/dvyukov/go-fuzz-corpus"
+compile_go_fuzzer $FUZZ_ROOT/text FuzzAcceptLanguage accept_language_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/text FuzzCurrency currency_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/math FuzzBigIntCmp1 big_cmp_fuzzer1
+compile_go_fuzzer $FUZZ_ROOT/math FuzzBigIntCmp2 big_cmp_fuzzer2
+compile_go_fuzzer $FUZZ_ROOT/math FuzzRatSetString big_rat_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/asn1 Fuzz asn_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/csv Fuzz csv_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/elliptic Fuzz elliptic_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/flate Fuzz flate_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/fmt Fuzz fmt_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/gzip Fuzz gzip_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/httpreq Fuzz httpreq_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/jpeg Fuzz jpeg_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/json Fuzz json_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/lzw Fuzz lzw_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/mime Fuzz mime_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/multipart Fuzz multipart_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/png Fuzz png_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/tar Fuzz tar_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/time Fuzz time_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/xml Fuzz xml_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/zip Fuzz zip_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/zlib Fuzz zlib_fuzzer
diff --git a/projects/golang/math_big_fuzzer.go b/projects/golang/math_big_fuzzer.go
new file mode 100644
index 0000000..60946bc
--- /dev/null
+++ b/projects/golang/math_big_fuzzer.go
@@ -0,0 +1,63 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+package mathfuzzer
+
+import "math/big"
+
+func FuzzBigIntCmp1(data []byte) int {
+    if !isDivisibleBy(len(data), 2) {
+        return -1
+    }
+    i1 := new(big.Int)
+    i2 := new(big.Int)
+
+    half := len(data) / 2
+
+    halfOne := data[:half]
+    halfTwo := data[half:]
+
+    i1.SetBytes(halfOne)
+    i2.SetBytes(halfTwo)
+
+    i1.Cmp(i2)
+    return 1
+}
+
+func FuzzBigIntCmp2(data []byte) int {
+    if !isDivisibleBy(len(data), 2) {
+        return -1
+    }
+    x, y := new(big.Int), new(big.Int)
+    half := len(data)/2
+    if err := x.UnmarshalText(data[:half]); err != nil {
+      return 0
+    }
+    if err := y.UnmarshalText(data[half:]); err != nil {
+      return 0
+    }
+    x.Cmp(y)
+    return 1
+}
+
+func FuzzRatSetString(data []byte) int {
+    _, _ = new(big.Rat).SetString(string(data))
+    return 1
+}
+
+func isDivisibleBy(n int, divisibleby int) bool {
+    return (n % divisibleby) == 0
+}
diff --git a/projects/golang/project.yaml b/projects/golang/project.yaml
index ed1e863..0fe496b 100644
--- a/projects/golang/project.yaml
+++ b/projects/golang/project.yaml
@@ -1,9 +1,11 @@
 homepage: "https://golang.org/"
+main_repo: "https://github.com/golang/go"
 primary_contact: "golang-fuzz@googlegroups.com"
 auto_ccs:
- - "mmoroz@chromium.org"
  - "josharian@gmail.com"
  - "emmanuel@orijtech.com"
+ - "Adam@adalogics.com"
+ - "cuong.manhle.vn@gmail.com"
 language: go
 sanitizers:
  - address
diff --git a/projects/golang/text_fuzzer.go b/projects/golang/text_fuzzer.go
new file mode 100644
index 0000000..d7686ae
--- /dev/null
+++ b/projects/golang/text_fuzzer.go
@@ -0,0 +1,36 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package fuzztext
+
+import (
+	"golang.org/x/text/currency"
+	"golang.org/x/text/language"
+)
+
+func FuzzAcceptLanguage(data []byte) int {
+	_, _, _ = language.ParseAcceptLanguage(string(data))
+	return 1
+}
+
+func FuzzCurrency(data []byte) int {
+	// Create tag
+	t, err := language.Parse(string(data))
+	if err != nil {
+		return 0
+	}
+	_, _ = currency.FromTag(t)
+	return 1
+}
diff --git a/projects/gonids/Dockerfile b/projects/gonids/Dockerfile
index 66e9a89..13175c9 100644
--- a/projects/gonids/Dockerfile
+++ b/projects/gonids/Dockerfile
@@ -14,10 +14,10 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN go get -t github.com/google/gonids
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/google/gonids
 
 ADD https://rules.emergingthreats.net/open/suricata/emerging.rules.zip emerging.rules.zip
 
 COPY build.sh $SRC/
-WORKDIR $SRC/
+WORKDIR $SRC/gonids
diff --git a/projects/gonids/build.sh b/projects/gonids/build.sh
index 590045f..7397c50 100755
--- a/projects/gonids/build.sh
+++ b/projects/gonids/build.sh
@@ -17,6 +17,7 @@
 
 compile_go_fuzzer github.com/google/gonids FuzzParseRule fuzz_parserule
 
+cd $SRC
 unzip emerging.rules.zip
 cd rules
 i=0
diff --git a/projects/gopacket/Dockerfile b/projects/gopacket/Dockerfile
index f8816e5..7f6c09a 100644
--- a/projects/gopacket/Dockerfile
+++ b/projects/gopacket/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN go get github.com/google/gopacket
 
 COPY build.sh $SRC/
diff --git a/projects/gpac/Dockerfile b/projects/gpac/Dockerfile
index cf7fc80..0784e48 100755
--- a/projects/gpac/Dockerfile
+++ b/projects/gpac/Dockerfile
@@ -16,8 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y build-essential pkg-config libz-dev
-RUN git clone https://github.com/gpac/gpac
+RUN git clone https://github.com/gpac/gpac && git clone https://github.com/gpac/testsuite
 
 WORKDIR $SRC
 COPY build.sh $SRC/
-COPY fuzz_parse.c $SRC/
diff --git a/projects/gpac/build.sh b/projects/gpac/build.sh
index 904f5f2..3bce724 100755
--- a/projects/gpac/build.sh
+++ b/projects/gpac/build.sh
@@ -18,8 +18,8 @@
 cd gpac
 ./configure --static-build --extra-cflags="${CFLAGS}" --extra-ldflags="${CFLAGS}"
 make
-cp $SRC/fuzz_parse.c . 
 
+cp $SRC/testsuite/oss-fuzzers/fuzz_parse.c .
 $CC $CFLAGS $LIB_FUZZING_ENGINE fuzz_parse.c -o $OUT/fuzz_parse \
     -I./include -I./ ./bin/gcc/libgpac_static.a \
     -lm -lz -lpthread -DGPAC_HAVE_CONFIG_H 
diff --git a/projects/gpac/fuzz_parse.c b/projects/gpac/fuzz_parse.c
deleted file mode 100644
index b7c9ac9..0000000
--- a/projects/gpac/fuzz_parse.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright 2021 Google LLC
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-      http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-#include <stdio.h>
-#include <unistd.h>
-
-#include <gpac/internal/isomedia_dev.h>
-#include <gpac/constants.h>
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-    char filename[256];
-    sprintf(filename, "/tmp/libfuzzer.%d", getpid());
-
-    FILE *fp = fopen(filename, "wb");
-    if (!fp) {
-        return 0;
-    }
-    fwrite(data, size, 1, fp);
-    fclose(fp);
-
-    GF_ISOFile *movie = NULL;
-    movie = gf_isom_open_file(filename, GF_ISOM_OPEN_READ_DUMP, NULL);
-    if (movie != NULL) {
-        gf_isom_close(movie);
-    }
-    unlink(filename);
-    return 0;
-}
diff --git a/projects/graphicsmagick/Dockerfile b/projects/graphicsmagick/Dockerfile
index 97f3a56..7596b61 100644
--- a/projects/graphicsmagick/Dockerfile
+++ b/projects/graphicsmagick/Dockerfile
@@ -29,7 +29,7 @@
 RUN git clone https://git.savannah.nongnu.org/r/freetype/freetype2.git/
 RUN git clone --depth 1 https://github.com/pnggroup/libpng
 RUN git clone --depth 1 https://github.com/mm2/Little-CMS
-RUN git clone https://git.ghostscript.com/ghostpdl.git
+RUN git clone http://git.ghostscript.com/ghostpdl.git
 RUN git clone --depth 1 https://gitlab.com/federicomenaquintero/bzip2.git
 RUN git clone --depth 1 https://github.com/jasper-software/jasper
 RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
diff --git a/projects/graphicsmagick/project.yaml b/projects/graphicsmagick/project.yaml
index 7b16f6c..319db44 100644
--- a/projects/graphicsmagick/project.yaml
+++ b/projects/graphicsmagick/project.yaml
@@ -8,7 +8,8 @@
 sanitizers:
     - address
     - memory
-    - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
 architectures:
     - x86_64
     - i386
diff --git a/projects/grpc-gateway/Dockerfile b/projects/grpc-gateway/Dockerfile
index 9a7cad2..e6ef61c 100644
--- a/projects/grpc-gateway/Dockerfile
+++ b/projects/grpc-gateway/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 ENV GO111MODULE on
 RUN git clone https://github.com/grpc-ecosystem/grpc-gateway
 COPY build.sh $SRC/
diff --git a/projects/grpc-go/Dockerfile b/projects/grpc-go/Dockerfile
index dc00af5..fa10f6d 100644
--- a/projects/grpc-go/Dockerfile
+++ b/projects/grpc-go/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 ENV GO111MODULE=on
 RUN go get google.golang.org/protobuf/cmd/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
 RUN git clone --depth 1 https://github.com/grpc/grpc-go $GOPATH/src/google.golang.org/grpc
diff --git a/projects/grpc-httpjson-transcoding/Dockerfile b/projects/grpc-httpjson-transcoding/Dockerfile
new file mode 100644
index 0000000..1746a42
--- /dev/null
+++ b/projects/grpc-httpjson-transcoding/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+MAINTAINER nareddyt@google.com
+
+RUN apt-get update && apt-get install python -y
+RUN git clone https://github.com/grpc-ecosystem/grpc-httpjson-transcoding.git
+WORKDIR $SRC/grpc-httpjson-transcoding/
+COPY build.sh $SRC/
diff --git a/projects/grpc-httpjson-transcoding/build.sh b/projects/grpc-httpjson-transcoding/build.sh
new file mode 100755
index 0000000..85e8e0b
--- /dev/null
+++ b/projects/grpc-httpjson-transcoding/build.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eu
+#
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# This project uses bazel rules_fuzzing.
+
+bazel_build_fuzz_tests
diff --git a/projects/grpc-httpjson-transcoding/project.yaml b/projects/grpc-httpjson-transcoding/project.yaml
new file mode 100644
index 0000000..07997d2
--- /dev/null
+++ b/projects/grpc-httpjson-transcoding/project.yaml
@@ -0,0 +1,20 @@
+homepage: "https://github.com/grpc-ecosystem/grpc-httpjson-transcoding"
+main_repo: "https://github.com/grpc-ecosystem/grpc-httpjson-transcoding.git"
+language: c++
+primary_contact: "nareddyt@google.com"
+auto_ccs:
+- "yangshuo@google.com"
+- "taoxuy@google.com"
+- "qiwzhang@google.com"
+- "justinmp@google.com"
+
+fuzzing_engines:
+- libfuzzer
+- afl
+- honggfuzz
+
+sanitizers:
+- address
+- undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
\ No newline at end of file
diff --git a/projects/grpc-swift/Dockerfile b/projects/grpc-swift/Dockerfile
new file mode 100644
index 0000000..981ebe9
--- /dev/null
+++ b/projects/grpc-swift/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-swift
+
+# specific to project
+RUN apt-get update && apt-get install -y zlib1g-dev
+RUN git clone --depth 1 https://github.com/grpc/grpc-swift
+COPY build.sh $SRC
+WORKDIR $SRC/grpc-swift
diff --git a/projects/grpc-swift/build.sh b/projects/grpc-swift/build.sh
new file mode 100755
index 0000000..a27f371
--- /dev/null
+++ b/projects/grpc-swift/build.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+. precompile_swift
+# build project
+cd FuzzTesting
+swift build -c debug $SWIFTFLAGS
+
+(
+cd .build/debug/
+find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-debug; done
+)
+swift build -c release $SWIFTFLAGS
+(
+cd .build/release/
+find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-release; done
+)
diff --git a/projects/grpc-swift/project.yaml b/projects/grpc-swift/project.yaml
new file mode 100644
index 0000000..2b5c230
--- /dev/null
+++ b/projects/grpc-swift/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/grpc/grpc-swift"
+language: swift
+primary_contact: "gbarnett@apple.com"
+auto_ccs :
+- "lukasa@apple.com"
+- "pp_adams@apple.com"
+- "p.antoine@catenacyber.fr"
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
+- thread
+main_repo: 'https://github.com/grpc/grpc-swift'
diff --git a/projects/grpc/Dockerfile b/projects/grpc/Dockerfile
index 6d2a310..5999a2c 100644
--- a/projects/grpc/Dockerfile
+++ b/projects/grpc/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 
-RUN apt-get update && apt-get install -y software-properties-common python-software-properties
+RUN apt-get update && apt-get install -y software-properties-common
 RUN add-apt-repository ppa:webupd8team/java
 RUN apt-get update && apt-get -y install  \
 	vim             \
@@ -38,6 +38,7 @@
 # Install Python packages from PyPI
 RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
+RUN pip install incremental==16.10.1
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #========================
diff --git a/projects/gstreamer/Dockerfile b/projects/gstreamer/Dockerfile
index 46318a5..1a88348 100644
--- a/projects/gstreamer/Dockerfile
+++ b/projects/gstreamer/Dockerfile
@@ -13,18 +13,23 @@
 # limitations under the License.
 #
 ################################################################################
-
 FROM gcr.io/oss-fuzz-base/base-builder
-# Install the build dependencies
 
-# install the minimum
+RUN apt-get update && \
+   apt-get install -y make autoconf automake libtool build-essential pkg-config bison flex gettext \
+    libffi-dev liblzma-dev libtheora-dev libogg-dev zlib1g-dev libcairo2-dev \
+    python3-pip ninja-build && \
+   pip3 install meson==0.55.1
 
-RUN sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" && \
-   apt-get update && \
-   apt-get install -y build-essential pkg-config bison flex gettext \
-    libffi-dev liblzma-dev libvorbis-dev libtheora-dev libogg-dev zlib1g-dev \
-    python3-pip && \
-   pip3 install meson==0.55.1 ninja==1.10.0.post2
+# We must install libvorbis from scratch as otherwise we will run into
+# undefined functions in Ubuntu 20.04
+RUN git clone --depth 1 https://gitlab.xiph.org/xiph/vorbis.git && \
+    cd $SRC/vorbis && \
+    ./autogen.sh && \
+    ./configure --enable-static && \
+    make clean && \
+    make -j$(nproc) && \
+    make install
 
 ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.64/glib-2.64.2.tar.xz $SRC
 
@@ -35,6 +40,8 @@
   git clone --depth 1 --recursive https://gitlab.freedesktop.org/gstreamer/gst-plugins-base.git gst-plugins-base && \
   git clone --depth 1 --recursive https://gitlab.freedesktop.org/gstreamer/gst-ci.git gst-ci
 
+RUN sed -i 's/theoraenc theoradec theora/theoraenc theoradec theora cairo/g' $SRC/gst-ci/fuzzing/build-oss-fuzz.sh
+
 ADD https://people.freedesktop.org/~bilboed/gst-discoverer_seed_corpus.zip $SRC
 
 WORKDIR gstreamer
diff --git a/projects/gvisor/Dockerfile b/projects/gvisor/Dockerfile
new file mode 100644
index 0000000..598664e
--- /dev/null
+++ b/projects/gvisor/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 --branch go https://github.com/google/gvisor
+COPY build.sh state_fuzzer.go $SRC/
+ENV GVISOR_ROOT $SRC/gvisor
+WORKDIR $GVISOR_ROOT
diff --git a/projects/gvisor/build.sh b/projects/gvisor/build.sh
new file mode 100644
index 0000000..7a1ee27
--- /dev/null
+++ b/projects/gvisor/build.sh
@@ -0,0 +1,19 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mv $SRC/state_fuzzer.go $GVISOR_ROOT/
+compile_go_fuzzer gvisor.dev/gvisor FuzzStateLoad state_load_fuzz
diff --git a/projects/gvisor/project.yaml b/projects/gvisor/project.yaml
new file mode 100644
index 0000000..b44a8ad
--- /dev/null
+++ b/projects/gvisor/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/google/gvisor"
+main_repo: "https://github.com/google/gvisor"
+primary_contact: "krakauer@google.com"
+auto_ccs :
+  - "gvisor-dev@googlegroups.com"
+  - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/gvisor/state_fuzzer.go b/projects/gvisor/state_fuzzer.go
new file mode 100644
index 0000000..b44f07a
--- /dev/null
+++ b/projects/gvisor/state_fuzzer.go
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package fuzzing
+
+import (
+	"bytes"
+	"context"
+	"gvisor.dev/gvisor/pkg/buffer"
+	"gvisor.dev/gvisor/pkg/state"
+)
+
+func FuzzStateLoad(data []byte) int {
+	ctx := context.Background()
+	var toLoad *buffer.View
+	_, _ = state.Load(ctx, bytes.NewReader(data), toLoad)
+	return 1
+}
diff --git a/projects/h2o/build.sh b/projects/h2o/build.sh
index 96c10de..22b655d 100755
--- a/projects/h2o/build.sh
+++ b/projects/h2o/build.sh
@@ -22,6 +22,7 @@
 
 zip -jr $OUT/h2o-fuzzer-http1_seed_corpus.zip $SRC/h2o/fuzz/http1-corpus
 zip -jr $OUT/h2o-fuzzer-http2_seed_corpus.zip $SRC/h2o/fuzz/http2-corpus
+zip -jr $OUT/h2o-fuzzer-http3_seed_corpus.zip $SRC/h2o/fuzz/http3-corpus
 zip -jr $OUT/h2o-fuzzer-url_seed_corpus.zip $SRC/h2o/fuzz/url-corpus
 
 cp $SRC/*.options $SRC/h2o/fuzz/*.dict $OUT/
diff --git a/projects/h2o/h2o-fuzzer-http3.options b/projects/h2o/h2o-fuzzer-http3.options
new file mode 100644
index 0000000..97ff13b
--- /dev/null
+++ b/projects/h2o/h2o-fuzzer-http3.options
@@ -0,0 +1,4 @@
+[libfuzzer]
+close_fd_mask = 3
+max_len = 16384
+dict = http.dict
diff --git a/projects/h2o/project.yaml b/projects/h2o/project.yaml
index 3c32e81..bc96502 100644
--- a/projects/h2o/project.yaml
+++ b/projects/h2o/project.yaml
@@ -8,5 +8,10 @@
   - "frederik.deweerdt@gmail.com"
   - "kazuhooku@gmail.com"
   - "i.nagata110@gmail.com"
+  - "hfujita@fastly.com"
   - "security@fastly.com"
+  - "mtakayama@fastly.com"
+  - "gfuji@fastly.com"
+  - "nalramli@fastly.com"
+
 main_repo: 'https://github.com/h2o/h2o'
diff --git a/projects/h3/Dockerfile b/projects/h3/Dockerfile
new file mode 100644
index 0000000..98f6e6c
--- /dev/null
+++ b/projects/h3/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool \
+  pkg-config
+RUN git clone --depth 1 https://github.com/uber/h3
+WORKDIR h3
+COPY build.sh h3_fuzzer.c $SRC/
diff --git a/projects/h3/build.sh b/projects/h3/build.sh
new file mode 100755
index 0000000..126327e
--- /dev/null
+++ b/projects/h3/build.sh
@@ -0,0 +1,34 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir build
+cd build
+sed -i '21d' $SRC/h3/CMakeLists.txt
+cmake ..
+make -j$(nproc)
+$CC $CFLAGS -DH3_PREFIX="" \
+    -I/src/h3/src/apps/applib/include \
+    -I/src/h3/src/h3lib/include \
+    -I/src/h3/build/src/h3lib/include \
+    -o h3_fuzzer.o \
+    -c $SRC/h3_fuzzer.c
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE -rdynamic \
+    h3_fuzzer.o \
+    -o $OUT/h3_fuzzer \
+    lib/libh3.a
+
diff --git a/projects/h3/h3_fuzzer.c b/projects/h3/h3_fuzzer.c
new file mode 100644
index 0000000..5d60733
--- /dev/null
+++ b/projects/h3/h3_fuzzer.c
@@ -0,0 +1,71 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "h3api.h"
+#include "utility.h"
+
+static const Direction DIGITS[7] = {CENTER_DIGIT,  K_AXES_DIGIT, J_AXES_DIGIT,
+                                    JK_AXES_DIGIT, I_AXES_DIGIT, IK_AXES_DIGIT,
+                                    IJ_AXES_DIGIT};
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < sizeof(H3Index)) {
+    return 0;
+  }
+  H3Index h3;
+  memcpy(&h3, data, sizeof(H3Index));
+
+  H3Index input[] = {h3, h3};
+  int inputSize = sizeof(input) / sizeof(H3Index);
+
+  // fuzz compactCells
+  H3Index *compacted = calloc(inputSize, sizeof(H3Index));
+  H3Error errCompact = compactCells(input, compacted, inputSize);
+
+  // fuzz uncompactCells
+  int compactedCount = 0;
+  for (int i = 0; i < inputSize; i++) {
+    if (compacted[i] != 0) {
+      compactedCount++;
+    }
+  }
+  if (compactedCount < 2) {
+    int uncompactRes = 10;
+    int64_t uncompactedSize;
+    H3Error err2 =
+        uncompactCellsSize(compacted, inputSize, uncompactRes, &uncompactedSize);
+
+    H3Index *uncompacted = calloc(uncompactedSize, sizeof(H3Index));
+    H3Error err3 = uncompactCells(compacted, compactedCount, uncompacted,
+                                  uncompactedSize, uncompactRes);
+    free(uncompacted);
+  }
+
+  // fuzz h3NeighborRotations
+  int rotations = 0;
+  for (int i = 0; i < 7; i++) {
+    h3NeighborRotations(h3, DIGITS[i], &rotations);
+  }
+  free(compacted);
+  return 0;
+}
diff --git a/projects/h3/project.yaml b/projects/h3/project.yaml
new file mode 100644
index 0000000..fdfbbfb
--- /dev/null
+++ b/projects/h3/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/uber/h3"
+language: c
+primary_contact: "isaacnf0x@gmail.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+  - "h3-dev@googlegroups.com"
+  - "isv.damocles@gmail.com"
+  - "ajfriend@gmail.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+main_repo: 'https://github.com/uber/h3'
diff --git a/projects/harfbuzz/build.sh b/projects/harfbuzz/build.sh
index 3509a67..c43b253 100755
--- a/projects/harfbuzz/build.sh
+++ b/projects/harfbuzz/build.sh
@@ -41,9 +41,9 @@
 # Archive and copy to $OUT seed corpus if the build succeeded.
 mkdir all-fonts
 for d in \
-	test/shaping/data/in-house/fonts \
-	test/shaping/data/aots/fonts \
-	test/shaping/data/text-rendering-tests/fonts \
+	test/shape/data/in-house/fonts \
+	test/shape/data/aots/fonts \
+	test/shape/data/text-rendering-tests/fonts \
 	test/api/fonts \
 	test/fuzzing/fonts \
 	perf/fonts \
diff --git a/projects/hcl/Dockerfile b/projects/hcl/Dockerfile
new file mode 100644
index 0000000..122beca
--- /dev/null
+++ b/projects/hcl/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/hashicorp/hcl
+COPY build.sh $SRC
+WORKDIR $SRC/hcl
\ No newline at end of file
diff --git a/projects/hcl/build.sh b/projects/hcl/build.sh
new file mode 100644
index 0000000..986e100
--- /dev/null
+++ b/projects/hcl/build.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -eu
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FUZZERS_BASE=$SRC/hcl/hclsyntax/fuzz
+FUZZERS_PACKAGE=github.com/hashicorp/hcl/v2/hclsyntax/fuzz
+FUZZER_CLASS=Fuzz
+
+for THE_FUZZER in config expr template traversal
+do
+    THE_FUZZER_NAME="fuzz_"$THE_FUZZER
+    compile_go_fuzzer $FUZZERS_PACKAGE/$THE_FUZZER $FUZZER_CLASS $THE_FUZZER_NAME
+
+    OUTDIR=$OUT/$THE_FUZZER_NAME"_seed_corpus"
+    mkdir $OUTDIR
+    find $FUZZERS_BASE/$THE_FUZZER/corpus -type f | while read FNAME
+    do
+        SHASUM_NAME=$(shasum "$FNAME" | awk '{print $1}')
+        cp "$FNAME" $OUTDIR
+    done
+    zip -r $OUTDIR".zip" $OUTDIR
+    rm -rf $OUTDIR
+done
\ No newline at end of file
diff --git a/projects/hcl/project.yaml b/projects/hcl/project.yaml
new file mode 100644
index 0000000..4abeeb5
--- /dev/null
+++ b/projects/hcl/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/hashicorp/hcl"
+language: go
+auto_ccs:
+  - federico.maggi@gmail.com
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+primary_contact: "security@hashicorp.com"
+main_repo: 'https://github.com/hashicorp/hcl'
\ No newline at end of file
diff --git a/projects/hermes/Dockerfile b/projects/hermes/Dockerfile
index eb59a38..70f4293 100644
--- a/projects/hermes/Dockerfile
+++ b/projects/hermes/Dockerfile
@@ -16,9 +16,16 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && \
-    apt-get install -y make autoconf automake libtool wget libicu-dev \
-    ninja-build python zip libreadline-dev libatomic-ops-dev
+    apt-get install -y make autoconf automake libtool wget \
+    python zip libreadline-dev libatomic-ops-dev
+
+RUN pip3 install meson ninja
+RUN ln -s /usr/local/bin/ninja /usr/bin/ninja
+
+RUN wget https://github.com/unicode-org/icu/archive/refs/tags/cldr/2021-08-25.tar.gz && \
+    tar xzvf ./2021-08-25.tar.gz && \
+    mv ./icu-cldr-2021-08-25/icu4c $SRC/icu
 
 RUN git clone https://github.com/facebook/hermes.git
-WORKDIR hermes
+WORKDIR $SRC
 COPY build.sh $SRC/
diff --git a/projects/hermes/build.sh b/projects/hermes/build.sh
index 01c11f3..7bf7a9b 100755
--- a/projects/hermes/build.sh
+++ b/projects/hermes/build.sh
@@ -15,6 +15,23 @@
 #
 ################################################################################
 
+# build ICU for linking statically.
+cd $SRC/icu/source
+./configure --disable-shared --enable-static --disable-layoutex \
+  --disable-tests --disable-samples --with-data-packaging=static
+make install -j$(nproc)
+
+# Ugly ugly hack to get static linking to work for icu.
+cd lib
+ls *.a | xargs -n1 ar x
+rm *.a
+ar r libicu.a *.{ao,o}
+ln -s $PWD/libicu.a /usr/lib/x86_64-linux-gnu/libicudata.a
+ln -s $PWD/libicu.a /usr/lib/x86_64-linux-gnu/libicuuc.a
+ln -s $PWD/libicu.a /usr/lib/x86_64-linux-gnu/libicui18n.a
+
+cd $SRC/hermes
+
 if [ "${SANITIZER}" = address ]
 then
     CONFIGURE_FLAGS="--enable-asan"
diff --git a/projects/hermes/project.yaml b/projects/hermes/project.yaml
index 0e614fe..baeedb6 100644
--- a/projects/hermes/project.yaml
+++ b/projects/hermes/project.yaml
@@ -2,8 +2,9 @@
 language: c++
 primary_contact: "neildhar@fb.com"
 auto_ccs:
-  - "dulinr@fb.com"
   - "mhl@fb.com"
+  - "avp@fb.com"
+  - "jsx@fb.com"
 vendor_ccs:
   - "oss-fuzz@fb.com"
 fuzzing_engines:
diff --git a/projects/hostap/project.yaml b/projects/hostap/project.yaml
index db978e1..9d95c6e 100644
--- a/projects/hostap/project.yaml
+++ b/projects/hostap/project.yaml
@@ -11,9 +11,10 @@
 sanitizers:
   - address
   - undefined
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - dataflow
 architectures:
   - x86_64
   - i386
-main_repo: 'git://w1.fi/srv/git/hostap.git'
+main_repo: 'git://w1.fi/srv/git/hostap.git'
\ No newline at end of file
diff --git a/projects/http-pattern-matcher/Dockerfile b/projects/http-pattern-matcher/Dockerfile
new file mode 100644
index 0000000..ab029cc
--- /dev/null
+++ b/projects/http-pattern-matcher/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+MAINTAINER nareddyt@google.com
+
+RUN apt-get update && apt-get install python -y
+RUN git clone https://github.com/google/http_pattern_matcher.git
+WORKDIR $SRC/http_pattern_matcher/
+COPY build.sh $SRC/
diff --git a/projects/http-pattern-matcher/build.sh b/projects/http-pattern-matcher/build.sh
new file mode 100755
index 0000000..85e8e0b
--- /dev/null
+++ b/projects/http-pattern-matcher/build.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eu
+#
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# This project uses bazel rules_fuzzing.
+
+bazel_build_fuzz_tests
diff --git a/projects/http-pattern-matcher/project.yaml b/projects/http-pattern-matcher/project.yaml
new file mode 100644
index 0000000..40a541e
--- /dev/null
+++ b/projects/http-pattern-matcher/project.yaml
@@ -0,0 +1,20 @@
+homepage: "https://github.com/google/http_pattern_matcher"
+main_repo: "https://github.com/google/http_pattern_matcher.git"
+language: c++
+primary_contact: "nareddyt@google.com"
+auto_ccs:
+- "yangshuo@google.com"
+- "taoxuy@google.com"
+- "qiwzhang@google.com"
+- "justinmp@google.com"
+
+fuzzing_engines:
+- libfuzzer
+- afl
+- honggfuzz
+
+sanitizers:
+- address
+- undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
diff --git a/projects/httparse/Dockerfile b/projects/httparse/Dockerfile
index cffcc9f..9b7b320 100644
--- a/projects/httparse/Dockerfile
+++ b/projects/httparse/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN git clone https://github.com/seanmonstar/httparse
 WORKDIR $SRC
diff --git a/projects/httplib2/Dockerfile b/projects/httplib2/Dockerfile
index f7dcaf2..55a17f9 100644
--- a/projects/httplib2/Dockerfile
+++ b/projects/httplib2/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 RUN git clone --depth 1 https://github.com/httplib2/httplib2
 
 COPY build.sh $SRC/
diff --git a/projects/httplib2/build.sh b/projects/httplib2/build.sh
index 3a3d0ea..ba9410d 100644
--- a/projects/httplib2/build.sh
+++ b/projects/httplib2/build.sh
@@ -15,7 +15,7 @@
 #
 ################################################################################
 
-pip3 install six 
+pip3 install six pytest
 python3 setup.py install
 
 # Build fuzzers in $OUT.
@@ -31,5 +31,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/hugo/Dockerfile b/projects/hugo/Dockerfile
index bfba1a2..351c194 100644
--- a/projects/hugo/Dockerfile
+++ b/projects/hugo/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 RUN git clone https://github.com/gohugoio/hugo
 COPY build.sh fuzz.go $SRC/
diff --git a/projects/hugo/fuzz.go b/projects/hugo/fuzz.go
index 7a22e6d..bfb23cf 100644
--- a/projects/hugo/fuzz.go
+++ b/projects/hugo/fuzz.go
@@ -24,7 +24,6 @@
 	"github.com/gohugoio/hugo/hugofs"
 	"github.com/gohugoio/hugo/langs"
 	"github.com/spf13/afero"
-	"github.com/spf13/viper"
 )
 
 func newFuzzDeps(cfg config.Provider) *deps.Deps {
@@ -43,7 +42,7 @@
 }
 
 func FuzzMarkdownify(data []byte) int {
-	v := viper.New()
+	v := config.New()
 	v.Set("contentDir", "content")
 	ns := New(newFuzzDeps(v))
 
diff --git a/projects/hunspell/project.yaml b/projects/hunspell/project.yaml
index 48c3f88..248ffa2 100644
--- a/projects/hunspell/project.yaml
+++ b/projects/hunspell/project.yaml
@@ -8,9 +8,10 @@
   - "twsmith@mozilla.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 architectures:
  - i386
  - x86_64
-main_repo: 'https://github.com/hunspell/hunspell.git'
+main_repo: 'https://github.com/hunspell/hunspell.git'
\ No newline at end of file
diff --git a/projects/hyperium/Dockerfile b/projects/hyperium/Dockerfile
new file mode 100644
index 0000000..4193023
--- /dev/null
+++ b/projects/hyperium/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+
+RUN git clone https://github.com/hyperium/http
+RUN git clone https://github.com/hyperium/h2
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/hyperium/build.sh b/projects/hyperium/build.sh
new file mode 100755
index 0000000..72c29e5
--- /dev/null
+++ b/projects/hyperium/build.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd $SRC/http
+cargo fuzz build -O
+cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_http $OUT/
+
+cd $SRC/h2
+cargo fuzz build -O
+cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_client $OUT/
+cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_e2e $OUT/
+cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_hpack $OUT/
+
+for fuzz_name in fuzz_e2e fuzz_client; do
+	echo "[libfuzzer]" > $OUT/${fuzz_name}.options
+	echo "detect_leaks=0" >> $OUT/${fuzz_name}.options
+done
diff --git a/projects/hyperium/project.yaml b/projects/hyperium/project.yaml
new file mode 100644
index 0000000..c3d3d9f
--- /dev/null
+++ b/projects/hyperium/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://github.com/hyperium/"
+main_repo: "https://github.com/hyperium/"
+primary_contact: "sean.monstar@gmail.com"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "ver@buoyant.io"
+  - "eliza@buoyant.io"
+  - "david@adalogics.com"
diff --git a/projects/ibmswtpm2/project.yaml b/projects/ibmswtpm2/project.yaml
index c1c6a96..9af192d 100644
--- a/projects/ibmswtpm2/project.yaml
+++ b/projects/ibmswtpm2/project.yaml
@@ -7,5 +7,6 @@
   - "david.wooten@ieee.org"
 sanitizers:
   - address
-  - memory
-  - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+  - undefined
\ No newline at end of file
diff --git a/projects/icu/project.yaml b/projects/icu/project.yaml
index d38b523..4ad93fd 100644
--- a/projects/icu/project.yaml
+++ b/projects/icu/project.yaml
@@ -11,6 +11,7 @@
  - ftang@google.com
 sanitizers:
  - address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 
-main_repo: 'https://github.com/unicode-org/icu.git'
+main_repo: 'https://github.com/unicode-org/icu.git'
\ No newline at end of file
diff --git a/projects/image-png/Dockerfile b/projects/image-png/Dockerfile
index cb953de..48be676 100644
--- a/projects/image-png/Dockerfile
+++ b/projects/image-png/Dockerfile
@@ -13,11 +13,10 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 RUN apt-get update && apt-get install -y make autoconf automake libtool curl cmake python llvm-dev libclang-dev clang
 
 RUN git clone https://github.com/image-rs/image-png
 WORKDIR $SRC
 
 COPY build.sh $SRC/
-COPY buf_independent.rs $SRC/image-png/fuzz/fuzz_targets/buf_independent.rs
diff --git a/projects/image-png/buf_independent.rs b/projects/image-png/buf_independent.rs
deleted file mode 100644
index f4a1f31..0000000
--- a/projects/image-png/buf_independent.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-#![no_main]
-extern crate libfuzzer_sys;
-use libfuzzer_sys::fuzz_target;
-extern crate png;
-
-use std::io::{BufRead, Read, Result};
-
-/// A reader that reads at most `n` bytes.
-struct SmalBuf<R: BufRead> {
-    inner: R,
-    cap: usize,
-}
-
-impl<R: BufRead> SmalBuf<R> {
-    fn new(inner: R, cap: usize) -> Self {
-        SmalBuf { inner, cap }
-    }
-}
-
-impl<R: BufRead> Read for SmalBuf<R> {
-    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
-        let len = buf.len().min(self.cap);
-        self.inner.read(&mut buf[..len])
-    }
-}
-
-impl<R: BufRead> BufRead for SmalBuf<R> {
-    fn fill_buf(&mut self) -> Result<&[u8]> {
-        let buf = self.inner.fill_buf()?;
-        let len = buf.len().min(self.cap);
-        Ok(&buf[..len])
-    }
-
-    fn consume(&mut self, amt: usize) {
-        assert!(amt <= self.cap);
-        self.inner.consume(amt)
-    }
-}
-
-fuzz_target!(|data: &[u8]| {
-    // Small limits, we don't need them hopefully.
-    let limits = png::Limits { bytes: 1 << 16 };
-
-    let reference = png::Decoder::new_with_limits(data, limits);
-    let smal = png::Decoder::new_with_limits(SmalBuf::new(data, 1), limits);
-
-    let _ = png_compare(reference, smal);
-});
-
-#[inline(always)]
-fn png_compare<R: BufRead, S: BufRead>(reference: png::Decoder<R>, smal: png::Decoder<S>)
-    -> std::result::Result<png::OutputInfo, ()>
-{
-    let mut smal = Some(smal);
-    let (info, mut reference) = reference.read_info().map_err(|_| {
-        assert!(smal.take().unwrap().read_info().is_err());
-    })?;
-
-    let (sinfo, mut smal) = smal.take().unwrap().read_info().expect("Deviation");
-    assert_eq!(info, sinfo);
-
-    if info.buffer_size() > 5_000_000 {
-        return Err(());
-    }
-
-    let mut ref_data = vec![0; info.buffer_size()];
-    let mut smal_data = vec![0; info.buffer_size()];
-
-    let _rref = reference.next_frame(&mut ref_data);
-    let _rsmal = smal.next_frame(&mut smal_data);
-
-    assert_eq!(smal_data, ref_data);
-    return Ok(info);
-}
diff --git a/projects/image-rs/Dockerfile b/projects/image-rs/Dockerfile
new file mode 100644
index 0000000..636bc2b
--- /dev/null
+++ b/projects/image-rs/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+
+RUN git clone https://github.com/image-rs/image
+WORKDIR $SRC/image
+
+COPY build.sh $SRC/
diff --git a/projects/image-rs/build.sh b/projects/image-rs/build.sh
new file mode 100755
index 0000000..c33f11c
--- /dev/null
+++ b/projects/image-rs/build.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cargo fuzz build -O
+cargo fuzz list | while read i; do
+    cp fuzz/target/x86_64-unknown-linux-gnu/release/$i $OUT/
+done
diff --git a/projects/image-rs/project.yaml b/projects/image-rs/project.yaml
new file mode 100644
index 0000000..62ae580
--- /dev/null
+++ b/projects/image-rs/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://docs.rs/image/0.23.14/image"
+main_repo: "https://github.com/image-rs/image"
+primary_contact: "andreas.molzer@gmx.de"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "fintelia@gmail.com"
+  - "p.antoine@catenacyber.fr"
diff --git a/projects/imageio/Dockerfile b/projects/imageio/Dockerfile
index 87c1811..eeef914 100644
--- a/projects/imageio/Dockerfile
+++ b/projects/imageio/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 RUN git clone https://github.com/imageio/imageio
 
 COPY build.sh $SRC/
diff --git a/projects/imageio/build.sh b/projects/imageio/build.sh
index aeef84e..8bf0fe5 100644
--- a/projects/imageio/build.sh
+++ b/projects/imageio/build.sh
@@ -29,5 +29,5 @@
 this_dir=\$(dirname \"\$0\")
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/imagemagick/project.yaml b/projects/imagemagick/project.yaml
index 509c8c1..ed95c7d 100644
--- a/projects/imagemagick/project.yaml
+++ b/projects/imagemagick/project.yaml
@@ -7,7 +7,8 @@
   - urban.warrior.fuzz@gmail.com
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
   - undefined
 architectures:
   - x86_64
diff --git a/projects/influxdb/Dockerfile b/projects/influxdb/Dockerfile
index e00af14..d108fe8 100644
--- a/projects/influxdb/Dockerfile
+++ b/projects/influxdb/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 MAINTAINER william@influxdata.com
 RUN go get github.com/influxdata/influxdb
 RUN go get github.com/dgrijalva/jwt-go
diff --git a/projects/ipfs/Dockerfile b/projects/ipfs/Dockerfile
index aee4c4c..1deea86 100644
--- a/projects/ipfs/Dockerfile
+++ b/projects/ipfs/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/ipfs/go-datastore
 
 COPY build.sh $SRC/
diff --git a/projects/istio/Dockerfile b/projects/istio/Dockerfile
index 4ba44e2..8962688 100644
--- a/projects/istio/Dockerfile
+++ b/projects/istio/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone https://github.com/istio/istio
 COPY build.sh $SRC/
 WORKDIR $SRC/istio
diff --git a/projects/istio/build.sh b/projects/istio/build.sh
index cb148e8..2ec9723 100644
--- a/projects/istio/build.sh
+++ b/projects/istio/build.sh
@@ -15,6 +15,5 @@
 #
 ################################################################################
 
+$SRC/istio/tests/fuzz/oss_fuzz_build.sh
 
-compile_go_fuzzer ./tests/fuzz FuzzParseInputs fuzz_parse_inputs
-compile_go_fuzzer ./tests/fuzz FuzzParseAndBuildSchema fuzz_parse_and_build_schema
diff --git a/projects/jackson-core/Dockerfile b/projects/jackson-core/Dockerfile
index 1ff7850..73e630b 100644
--- a/projects/jackson-core/Dockerfile
+++ b/projects/jackson-core/Dockerfile
@@ -15,7 +15,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
 RUN apt-get update && apt-get install -y maven
 
 RUN git clone --depth 1 https://github.com/google/fuzzing
diff --git a/projects/jackson-core/build.sh b/projects/jackson-core/build.sh
index 5cbf19c..4023cf9 100644
--- a/projects/jackson-core/build.sh
+++ b/projects/jackson-core/build.sh
@@ -53,5 +53,5 @@
 --target_class=$fuzzer_basename \
 --jvm_args=\"-Xmx2048m\" \
 \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/jackson-dataformat-xml/Dockerfile b/projects/jackson-dataformat-xml/Dockerfile
new file mode 100644
index 0000000..65f1195
--- /dev/null
+++ b/projects/jackson-dataformat-xml/Dockerfile
@@ -0,0 +1,39 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+    unzip maven.zip -d $SRC/maven && \
+    rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+RUN git clone --depth 1 https://github.com/google/fuzzing && \
+    mv fuzzing/dictionaries/xml.dict $SRC/XmlFuzzer.dict && \
+    rm -rf fuzzing
+
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \
+    zip -j $SRC/XmlFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \
+    rm -rf go-fuzz-corpus
+
+ENV JACKSON_BRANCH=2.13
+
+RUN git clone --depth 1 --branch=$JACKSON_BRANCH https://github.com/FasterXML/jackson-dataformat-xml
+
+COPY build.sh $SRC/
+COPY XmlFuzzer.java $SRC/
+WORKDIR $SRC/jackson-dataformat-xml
diff --git a/projects/jackson-dataformat-xml/XmlFuzzer.java b/projects/jackson-dataformat-xml/XmlFuzzer.java
new file mode 100644
index 0000000..aeb2e8e
--- /dev/null
+++ b/projects/jackson-dataformat-xml/XmlFuzzer.java
@@ -0,0 +1,29 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import java.io.IOException;
+
+public class XmlFuzzer {
+  public static void fuzzerTestOneInput(byte[] input) {
+    ObjectMapper mapper = new XmlMapper();
+    try {
+      mapper.readTree(input);
+    } catch (IOException ignored) {
+    }
+  }
+}
diff --git a/projects/jackson-dataformat-xml/build.sh b/projects/jackson-dataformat-xml/build.sh
new file mode 100644
index 0000000..9be88a9
--- /dev/null
+++ b/projects/jackson-dataformat-xml/build.sh
@@ -0,0 +1,52 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Move seed corpus and dictionary.
+mv $SRC/{*.zip,*.dict} $OUT
+
+MAVEN_ARGS="-P!java14+ -Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15"
+$MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS
+CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+ -Dexpression=project.version -q -DforceStdout)
+cp "target/jackson-dataformat-xml-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-xml.jar
+
+ALL_JARS="jackson-dataformat-xml.jar"
+
+# The classpath at build-time includes the project jars in $OUT as well as the
+# Jazzer API.
+BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
+
+# All .jar and .class files lie in the same directory as the fuzzer at runtime.
+RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
+
+for fuzzer in $(find $SRC -name '*Fuzzer.java'); do
+  fuzzer_basename=$(basename -s .java $fuzzer)
+  javac -cp $BUILD_CLASSPATH $fuzzer
+  cp $SRC/$fuzzer_basename.class $OUT/
+
+  # Create an execution wrapper that executes Jazzer with the correct arguments.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
+done
diff --git a/projects/jackson-dataformat-xml/project.yaml b/projects/jackson-dataformat-xml/project.yaml
new file mode 100644
index 0000000..7109fd0
--- /dev/null
+++ b/projects/jackson-dataformat-xml/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/FasterXML/jackson-dataformat-xml"
+language: jvm
+primary_contact: "tatu@fasterxml.com"
+auto_ccs:
+  - "meumertzheim@code-intelligence.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://github.com/FasterXML/jackson-dataformat-xml"
+sanitizers:
+  - address
diff --git a/projects/jackson-dataformats-binary/Dockerfile b/projects/jackson-dataformats-binary/Dockerfile
index 0e4ea82..700e3ea 100644
--- a/projects/jackson-dataformats-binary/Dockerfile
+++ b/projects/jackson-dataformats-binary/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
 RUN apt-get update && apt-get install -y maven
 
 ENV JACKSON_BRANCH=2.13
diff --git a/projects/jackson-dataformats-binary/build.sh b/projects/jackson-dataformats-binary/build.sh
index 3c3c0af..7cfdbb1 100644
--- a/projects/jackson-dataformats-binary/build.sh
+++ b/projects/jackson-dataformats-binary/build.sh
@@ -62,5 +62,5 @@
 --target_class=$fuzzer_basename \
 --jvm_args=\"-Xmx2048m\" \
 \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/janet/build.sh b/projects/janet/build.sh
index 0627307..2279e80 100755
--- a/projects/janet/build.sh
+++ b/projects/janet/build.sh
@@ -18,5 +18,5 @@
 cd janet
 make
 
-clang $CFLAGS -std=c99 -Isrc/include -Isrc/conf -fPIC  -o fuzz_dostring.o -c ./test/fuzzers/fuzz_dostring.c
-clang++ $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_dostring.o build/libjanet.a -o $OUT/fuzz_dostring
+$CC $CFLAGS -std=c99 -Isrc/include -Isrc/conf -fPIC  -o fuzz_dostring.o -c ./test/fuzzers/fuzz_dostring.c
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_dostring.o build/libjanet.a -o $OUT/fuzz_dostring
diff --git a/projects/janus-gateway/Dockerfile b/projects/janus-gateway/Dockerfile
index f0c56cd..6cf0e14 100644
--- a/projects/janus-gateway/Dockerfile
+++ b/projects/janus-gateway/Dockerfile
@@ -22,7 +22,7 @@
 	gtk-doc-tools \
 	libconfig-dev \
 	libglib2.0-dev \
-	libgnutls-dev \
+	libgnutls28-dev \
 	libini-config-dev \
 	libjansson-dev \
 	libnice-dev \
diff --git a/projects/janus-gateway/project.yaml b/projects/janus-gateway/project.yaml
index f2a640a..db1b178 100644
--- a/projects/janus-gateway/project.yaml
+++ b/projects/janus-gateway/project.yaml
@@ -5,7 +5,8 @@
   - "lminiero@gmail.com"
 sanitizers:
   - address
-  - memory
   - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 coverage_extra_args: -ignore-filename-regex=.*glib.* -ignore-filename-regex=.*log.c
 main_repo: 'https://github.com/meetecho/janus-gateway.git'
diff --git a/projects/java-example/Dockerfile b/projects/java-example/Dockerfile
index 316e9a8..18ed9e1 100644
--- a/projects/java-example/Dockerfile
+++ b/projects/java-example/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
 
 COPY build.sh $SRC/
 
diff --git a/projects/java-example/ExampleFuzzerNative.cpp b/projects/java-example/ExampleFuzzerNative.cpp
index 7ae0de8..565f75c 100644
--- a/projects/java-example/ExampleFuzzerNative.cpp
+++ b/projects/java-example/ExampleFuzzerNative.cpp
@@ -16,15 +16,21 @@
 
 #include "ExampleFuzzerNative.h"
 
+#include <limits>
 #include <string>
 
 // simple function containing a crash that requires coverage and string compare
 // instrumentation for the fuzzer to find
-void parseInternal(const std::string &input) {
+__attribute__((optnone)) void parseInternal(const std::string &input) {
+  constexpr int bar = std::numeric_limits<int>::max() - 5;
+  // Crashes with UBSan.
+  if (bar + input[0] == 300) {
+    return;
+  }
   if (input[0] == 'a' && input[1] == 'b' && input[5] == 'c') {
     if (input.find("secret_in_native_library") != std::string::npos) {
-      // BOOM
-      *(char *)1 = 2;
+      // Crashes with ASan.
+      [[maybe_unused]] char foo = input[input.size() + 2];
     }
   }
 }
diff --git a/projects/java-example/build.sh b/projects/java-example/build.sh
index 63f4c95..c2fcd44 100755
--- a/projects/java-example/build.sh
+++ b/projects/java-example/build.sh
@@ -17,8 +17,9 @@
 
 # Build native library.
 JVM_INCLUDES="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
+mkdir $OUT/native
 $CXX $CXXFLAGS $JVM_INCLUDES -fPIC -shared \
-    ExampleFuzzerNative.cpp -o $OUT/libnative.so
+    ExampleFuzzerNative.cpp -o $OUT/native/libnative.so
 
 BUILD_CLASSPATH=$JAZZER_API_PATH
 
@@ -31,7 +32,7 @@
   cp $SRC/$fuzzer_basename.class $OUT/
 
   if [[ $fuzzer_basename == *FuzzerNative ]]; then
-    driver=jazzer_driver_asan
+    driver=jazzer_driver_with_sanitizer
   else
     driver=jazzer_driver
   fi
@@ -41,12 +42,12 @@
   echo "#!/bin/sh
 # LLVMFuzzerTestOneInput for fuzzer detection.
 this_dir=\$(dirname \"\$0\")
-LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir/native \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
 --cp=$RUNTIME_CLASSPATH \
 --target_class=$fuzzer_basename \
 --jvm_args=\"-Xmx2048m\" \
 \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/java-example/default.options b/projects/java-example/default.options
index 5931803..8cda4b2 100644
--- a/projects/java-example/default.options
+++ b/projects/java-example/default.options
@@ -1,3 +1,6 @@
 [asan]
 handle_segv=1
 allow_user_segv_handler=1
+
+[ubsan]
+handle_segv=1
diff --git a/projects/java-example/project.yaml b/projects/java-example/project.yaml
index e71c405..6401e22 100644
--- a/projects/java-example/project.yaml
+++ b/projects/java-example/project.yaml
@@ -1,4 +1,5 @@
 homepage: "https://github.com/CodeIntelligenceTesting/jazzer"
+disabled: true
 language: jvm
 primary_contact: "meumertzheim@code-intelligence.com"
 fuzzing_engines:
@@ -6,3 +7,4 @@
 main_repo: "https://github.com/CodeIntelligenceTesting/jazzer"
 sanitizers:
   - address
+  - undefined
diff --git a/projects/javaparser/Dockerfile b/projects/javaparser/Dockerfile
new file mode 100644
index 0000000..d0b8a74
--- /dev/null
+++ b/projects/javaparser/Dockerfile
@@ -0,0 +1,26 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN apt-get update && apt-get install -y maven
+
+RUN git clone --depth 1 https://github.com/javaparser/javaparser
+COPY build.sh $SRC/
+
+COPY *.java $SRC/
+
+WORKDIR $SRC/javaparser
diff --git a/projects/javaparser/build.sh b/projects/javaparser/build.sh
new file mode 100755
index 0000000..a931350
--- /dev/null
+++ b/projects/javaparser/build.sh
@@ -0,0 +1,49 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Build the jar.
+CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+-Dexpression=project.version -q -DforceStdout)
+mvn package -Dmaven.test.skip=true
+cp "javaparser-core/target/javaparser-core-$CURRENT_VERSION.jar" $OUT/javaparser.jar
+
+# The jar files containing the project (separated by spaces).
+PROJECT_JARS=javaparser.jar
+
+# Build fuzzers in $OUT.
+BUILD_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
+
+# All jars and class files lie in the same directory as the fuzzer at runtime.
+RUNTIME_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir
+
+for fuzzer in $(find $SRC -name '*Fuzzer.java'); do
+  fuzzer_basename=$(basename -s .java $fuzzer)
+  javac -cp $BUILD_CLASSPATH $fuzzer
+  cp $SRC/$fuzzer_basename.class $OUT/
+
+  # Create execution wrapper.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
+done
diff --git a/projects/javaparser/parseFuzzer.java b/projects/javaparser/parseFuzzer.java
new file mode 100644
index 0000000..662f3fb
--- /dev/null
+++ b/projects/javaparser/parseFuzzer.java
@@ -0,0 +1,41 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ParserConfiguration;
+import static com.github.javaparser.Providers.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+public class parseFuzzer {
+  public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+    String datastring = data.consumeRemainingAsString();
+    InputStream datastream = new ByteArrayInputStream(datastring.getBytes());
+    try {
+        ParserConfiguration configuration = new ParserConfiguration();
+        final ParseResult<CompilationUnit> result = new JavaParser(configuration)
+        .parse(COMPILATION_UNIT, provider(datastream, configuration.getCharacterEncoding()));
+    } catch (Exception e) {
+      return;
+    }
+  }
+}
diff --git a/projects/javaparser/project.yaml b/projects/javaparser/project.yaml
new file mode 100644
index 0000000..f62cb77
--- /dev/null
+++ b/projects/javaparser/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://javaparser.org"
+language: jvm
+primary_contact: "MysterAitch@users.noreply.github.com"
+auto_ccs:
+  - "p.antoine@catenacyber.fr"
+  - "jean-pierre.lerbscher@jperf.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://github.com/javaparser/javaparser"
+sanitizers:
+  - address
diff --git a/projects/jbig2dec/jbig2_fuzzer.cc b/projects/jbig2dec/jbig2_fuzzer.cc
index 4b94f2c..c10b871 100644
--- a/projects/jbig2dec/jbig2_fuzzer.cc
+++ b/projects/jbig2dec/jbig2_fuzzer.cc
@@ -27,7 +27,7 @@
 #define KBYTE ((size_t) 1024)
 #define MBYTE (1024 * KBYTE)
 #define GBYTE (1024 * MBYTE)
-#define MAX_ALLOCATION (1 * GBYTE)
+#define MAX_ALLOCATION (32 * MBYTE)
 
 static size_t used;
 
diff --git a/projects/json-patch/Dockerfile b/projects/json-patch/Dockerfile
new file mode 100644
index 0000000..81eabb4
--- /dev/null
+++ b/projects/json-patch/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/evanphx/json-patch
+
+COPY fuzz_*.go $SRC/json-patch/
+
+COPY build.sh $SRC/
+WORKDIR $SRC/json-patch
diff --git a/projects/json-patch/build.sh b/projects/json-patch/build.sh
new file mode 100755
index 0000000..d13e7ab
--- /dev/null
+++ b/projects/json-patch/build.sh
@@ -0,0 +1,19 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+compile_go_fuzzer github.com/evanphx/json-patch FuzzCreateMerge fuzz_create_merge
+compile_go_fuzzer github.com/evanphx/json-patch FuzzDecodeApply fuzz_decode_apply
diff --git a/projects/json-patch/fuzz_create_merge.go b/projects/json-patch/fuzz_create_merge.go
new file mode 100644
index 0000000..b7cb330
--- /dev/null
+++ b/projects/json-patch/fuzz_create_merge.go
@@ -0,0 +1,26 @@
+package jsonpatch
+
+import (
+	"bytes"
+)
+
+func FuzzCreateMerge(data []byte) int {
+	s := bytes.Split(data, []byte{0})
+	if len(s) != 3 {
+		return 0
+	}
+	original := s[0]
+	target := s[1]
+	alternative := s[2]
+
+	patch, err := CreateMergePatch(original, target)
+	if err != nil {
+		return 0
+	}
+	_, err = MergePatch(alternative, patch)
+	if err != nil {
+		return 0
+	}
+
+	return 1
+}
diff --git a/projects/json-patch/fuzz_decode_apply.go b/projects/json-patch/fuzz_decode_apply.go
new file mode 100644
index 0000000..3159558
--- /dev/null
+++ b/projects/json-patch/fuzz_decode_apply.go
@@ -0,0 +1,25 @@
+package jsonpatch
+
+import (
+	"bytes"
+)
+
+func FuzzDecodeApply(data []byte) int {
+	s := bytes.Split(data, []byte{0})
+	if len(s) != 2 {
+		return 0
+	}
+	patchJSON := s[0]
+	original := s[1]
+
+	patch, err := DecodePatch(patchJSON)
+	if err != nil {
+		return 0
+	}
+
+	_, err = patch.Apply(original)
+	if err != nil {
+		return 0
+	}
+	return 1
+}
diff --git a/projects/json-patch/project.yaml b/projects/json-patch/project.yaml
new file mode 100644
index 0000000..a66ada9
--- /dev/null
+++ b/projects/json-patch/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/evanphx/json-patch"
+primary_contact: "evan@phx.io"
+auto_ccs:
+  - "p.antoine@catenacyber.fr"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: 'https://github.com/evanphx/json-patch'
diff --git a/projects/json-sanitizer/Dockerfile b/projects/json-sanitizer/Dockerfile
index f36a136..9d1052a 100644
--- a/projects/json-sanitizer/Dockerfile
+++ b/projects/json-sanitizer/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
 
 RUN apt-get update && apt-get install -y maven
 
diff --git a/projects/json-sanitizer/build.sh b/projects/json-sanitizer/build.sh
index 64df5e5..dd4063b 100755
--- a/projects/json-sanitizer/build.sh
+++ b/projects/json-sanitizer/build.sh
@@ -56,5 +56,5 @@
 --target_class=$fuzzer_basename \
 --jvm_args=\"-Xmx2048m\" \
 \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/json/project.yaml b/projects/json/project.yaml
index 83f48e2..927bfc5 100644
--- a/projects/json/project.yaml
+++ b/projects/json/project.yaml
@@ -6,5 +6,6 @@
 sanitizers:
  - address
  - undefined
- - memory
-main_repo: 'https://github.com/nlohmann/json.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: 'https://github.com/nlohmann/json.git'
\ No newline at end of file
diff --git a/projects/json5format/Dockerfile b/projects/json5format/Dockerfile
index c0117a5..64c8793 100644
--- a/projects/json5format/Dockerfile
+++ b/projects/json5format/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN git clone --depth 1 https://github.com/google/json5format
 WORKDIR $SRC
diff --git a/projects/jsoncpp/project.yaml b/projects/jsoncpp/project.yaml
index 8dc8f02..51795d4 100644
--- a/projects/jsoncpp/project.yaml
+++ b/projects/jsoncpp/project.yaml
@@ -6,5 +6,6 @@
 sanitizers:
   - address
   - undefined
-  - memory
-main_repo: 'https://github.com/open-source-parsers/jsoncpp'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: 'https://github.com/open-source-parsers/jsoncpp'
\ No newline at end of file
diff --git a/projects/jsonnet/build.sh b/projects/jsonnet/build.sh
index 5386efb..d51c704 100644
--- a/projects/jsonnet/build.sh
+++ b/projects/jsonnet/build.sh
@@ -28,4 +28,5 @@
 $CXX $CXXFLAGS -I${INSTALL_DIR}/include $LIB_FUZZING_ENGINE \
   $fuzzer.cc -o $OUT/$fuzzer \
   ${INSTALL_DIR}/build/libjsonnet.a \
-  ${INSTALL_DIR}/build/libmd5.a
+  ${INSTALL_DIR}/build/libmd5.a \
+  ${INSTALL_DIR}/build/libryml.a
diff --git a/projects/jsonnet/project.yaml b/projects/jsonnet/project.yaml
index 4b33850..feec146 100644
--- a/projects/jsonnet/project.yaml
+++ b/projects/jsonnet/project.yaml
@@ -2,12 +2,12 @@
 language: c++
 primary_contact: "dcunnin@google.com"
 auto_ccs:
-  - "wwweiwang@google.com"
   - "sparkprime@gmail.com"
 
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
   - undefined
 
 labels:
diff --git a/projects/jsonparser/Dockerfile b/projects/jsonparser/Dockerfile
index a5d91fa..38f310f 100644
--- a/projects/jsonparser/Dockerfile
+++ b/projects/jsonparser/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/buger/jsonparser
 
 COPY build.sh $SRC/
diff --git a/projects/jsonschema/Dockerfile b/projects/jsonschema/Dockerfile
index ffec717..007e01c 100644
--- a/projects/jsonschema/Dockerfile
+++ b/projects/jsonschema/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 RUN pip3 install hypothesis
 
 RUN git clone --depth=1 https://github.com/Julian/jsonschema
diff --git a/projects/jsonschema/build.sh b/projects/jsonschema/build.sh
index 71d4ad6..3ba97ab 100644
--- a/projects/jsonschema/build.sh
+++ b/projects/jsonschema/build.sh
@@ -30,5 +30,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/jsoup/Dockerfile b/projects/jsoup/Dockerfile
new file mode 100644
index 0000000..d83f7b5
--- /dev/null
+++ b/projects/jsoup/Dockerfile
@@ -0,0 +1,38 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+    unzip maven.zip -d $SRC/maven && \
+    rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+RUN git clone --depth 1 https://github.com/google/fuzzing && \
+    mv fuzzing/dictionaries/html.dict $SRC/HtmlFuzzer.dict && \
+    mv fuzzing/dictionaries/xml.dict $SRC/XmlFuzzer.dict && \
+    rm -rf fuzzing
+
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \
+    zip -j $SRC/XmlFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \
+    rm -rf go-fuzz-corpus
+
+RUN git clone --depth 1 https://github.com/jhy/jsoup/
+
+COPY build.sh $SRC/
+COPY HtmlFuzzer.java XmlFuzzer.java $SRC/
+WORKDIR $SRC/jsoup
diff --git a/projects/jsoup/HtmlFuzzer.java b/projects/jsoup/HtmlFuzzer.java
new file mode 100644
index 0000000..5f2090e
--- /dev/null
+++ b/projects/jsoup/HtmlFuzzer.java
@@ -0,0 +1,25 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+import org.jsoup.Jsoup;
+
+public class HtmlFuzzer {
+  public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+    Jsoup.parse(data.consumeRemainingAsString());
+  }
+}
diff --git a/projects/jsoup/XmlFuzzer.java b/projects/jsoup/XmlFuzzer.java
new file mode 100644
index 0000000..ddce20b
--- /dev/null
+++ b/projects/jsoup/XmlFuzzer.java
@@ -0,0 +1,26 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+import org.jsoup.Jsoup;
+import org.jsoup.parser.Parser;
+
+public class XmlFuzzer {
+  public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+    Jsoup.parse(data.consumeRemainingAsString(), "", Parser.xmlParser());
+  }
+}
diff --git a/projects/jsoup/build.sh b/projects/jsoup/build.sh
new file mode 100755
index 0000000..4bbe473
--- /dev/null
+++ b/projects/jsoup/build.sh
@@ -0,0 +1,52 @@
+#!/bin/bash -eu
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Move seed corpus and dictionary.
+mv $SRC/{*.zip,*.dict} $OUT
+
+MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15"
+$MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS
+CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+ -Dexpression=project.version -q -DforceStdout)
+cp "target/jsoup-$CURRENT_VERSION.jar" $OUT/jsoup.jar
+
+ALL_JARS="jsoup.jar"
+
+# The classpath at build-time includes the project jars in $OUT as well as the
+# Jazzer API.
+BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
+
+# All .jar and .class files lie in the same directory as the fuzzer at runtime.
+RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
+
+for fuzzer in $(find $SRC -name '*Fuzzer.java'); do
+  fuzzer_basename=$(basename -s .java $fuzzer)
+  javac -cp $BUILD_CLASSPATH $fuzzer
+  cp $SRC/$fuzzer_basename.class $OUT/
+
+  # Create an execution wrapper that executes Jazzer with the correct arguments.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+  chmod u+x $OUT/$fuzzer_basename
+done
diff --git a/projects/jsoup/project.yaml b/projects/jsoup/project.yaml
new file mode 100644
index 0000000..6f47c29
--- /dev/null
+++ b/projects/jsoup/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/jhy/jsoup/"
+language: jvm
+primary_contact: "jonathan@hedley.net"
+auto_ccs:
+  - "wagner@code-intelligence.com"
+  - "ffrr33aakk@gmail.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://github.com/jhy/jsoup/"
+sanitizers:
+  - address
diff --git a/projects/juju/Dockerfile b/projects/juju/Dockerfile
new file mode 100644
index 0000000..e4c15cb
--- /dev/null
+++ b/projects/juju/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/juju/juju
+COPY build.sh storage_fuzzer.go $SRC/
+WORKDIR $SRC/juju
diff --git a/projects/juju/build.sh b/projects/juju/build.sh
new file mode 100644
index 0000000..7dc892c
--- /dev/null
+++ b/projects/juju/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mv $SRC/storage_fuzzer.go $SRC/juju/storage/
+
+if [[ $SANITIZER = *coverage* ]]; then
+	compile_go_fuzzer github.com/juju/juju/storage Fuzz storage_fuzzer
+	exit 0
+fi
+
+compile_go_fuzzer ./storage Fuzz storage_fuzzer
diff --git a/projects/juju/project.yaml b/projects/juju/project.yaml
new file mode 100644
index 0000000..709249f
--- /dev/null
+++ b/projects/juju/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://juju.is"
+main_repo: "https://github.com/juju/juju"
+primary_contact: "stickupkid@gmail.com"
+auto_ccs :
+  - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/juju/storage_fuzzer.go b/projects/juju/storage_fuzzer.go
new file mode 100644
index 0000000..17e2a0e
--- /dev/null
+++ b/projects/juju/storage_fuzzer.go
@@ -0,0 +1,24 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package storage
+
+func Fuzz(data []byte) int {
+	_, err := ParseConstraints(string(data))
+	if err != nil {
+		return 0
+	}
+	return 1
+}
diff --git a/projects/kamailio/build.sh b/projects/kamailio/build.sh
index 2b7c373..5d94cec 100755
--- a/projects/kamailio/build.sh
+++ b/projects/kamailio/build.sh
@@ -22,7 +22,8 @@
 
 sed -i 's/int main(/int main2(/g' ./src/main.c
 
-make || true
+export MEMPKG=sys
+make Q=verbose || true
 cd src
 mkdir objects && find . -name "*.o" -exec cp {} ./objects/ \;
 ar -r libkamilio.a ./objects/*.o
@@ -30,3 +31,7 @@
 $CC $CFLAGS $LIB_FUZZING_ENGINE ./misc/fuzz/fuzz_uri.c -o $OUT/fuzz_uri \
     -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \
     -I./src/ -I./src/core/parser -ldl -lresolv -lm
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./misc/fuzz/fuzz_parse_msg.c -o $OUT/fuzz_parse_msg \
+    -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \
+    -I./src/ -I./src/core/parser -ldl -lresolv -lm
diff --git a/projects/kamailio/project.yaml b/projects/kamailio/project.yaml
index 46020a0..ae2ce66 100755
--- a/projects/kamailio/project.yaml
+++ b/projects/kamailio/project.yaml
@@ -5,3 +5,5 @@
 auto_ccs:
   - "miconda@gmail.com"
   - "david@adalogics.com"
+  - "mail@gilawa.com"
+  - "qxork.droid@gmail.com"
diff --git a/projects/karchive/project.yaml b/projects/karchive/project.yaml
index 0e023cd..2318ce5 100644
--- a/projects/karchive/project.yaml
+++ b/projects/karchive/project.yaml
@@ -3,6 +3,7 @@
 primary_contact: tsdgeos@gmail.com
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://invent.kde.org/frameworks/karchive.git'
+main_repo: 'https://invent.kde.org/frameworks/karchive.git'
\ No newline at end of file
diff --git a/projects/kcodecs/Dockerfile b/projects/kcodecs/Dockerfile
index 3d70e83..1c563cf 100644
--- a/projects/kcodecs/Dockerfile
+++ b/projects/kcodecs/Dockerfile
@@ -15,7 +15,8 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get install --yes cmake gperf
+RUN apt-get install --yes cmake
+RUN curl -L http://ftp.gnu.org/pub/gnu/gperf/gperf-3.1.tar.gz -O
 RUN git clone --depth 1 --branch=5.15 git://code.qt.io/qt/qtbase.git
 RUN git clone --depth 1 https://invent.kde.org/frameworks/kcodecs.git
 RUN git clone --depth 1 https://invent.kde.org/frameworks/extra-cmake-modules.git
diff --git a/projects/kcodecs/build.sh b/projects/kcodecs/build.sh
index 2f8c857..85f5be3 100644
--- a/projects/kcodecs/build.sh
+++ b/projects/kcodecs/build.sh
@@ -16,6 +16,20 @@
 ################################################################################
 
 cd $SRC
+tar xzf gperf*.tar.gz && rm -f gperf*.tar.gz
+cd gperf*
+FUZZ_CFLAGS="${CFLAGS}"
+FUZZ_CXXFLAGS="${CXXFLAGS}"
+unset CFLAGS
+unset CXXFLAGS
+# gperf is a code generator, so no need to sanitize it
+./configure --prefix=/usr
+make -j$(nproc) install
+export CFLAGS="${FUZZ_CFLAGS}"
+export CXXFLAGS="${FUZZ_CXXFLAGS}"
+
+
+cd $SRC
 cd extra-cmake-modules
 cmake .
 make install
diff --git a/projects/kcodecs/project.yaml b/projects/kcodecs/project.yaml
index 1b731e3..b698f63 100644
--- a/projects/kcodecs/project.yaml
+++ b/projects/kcodecs/project.yaml
@@ -3,6 +3,7 @@
 primary_contact: tsdgeos@gmail.com
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://invent.kde.org/frameworks/kcodecs.git'
+main_repo: 'https://invent.kde.org/frameworks/kcodecs.git'
\ No newline at end of file
diff --git a/projects/keystone/project.yaml b/projects/keystone/project.yaml
index 860313b..4bb1e0b 100644
--- a/projects/keystone/project.yaml
+++ b/projects/keystone/project.yaml
@@ -6,6 +6,7 @@
   - "stalkr@stalkr.net"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/keystone-engine/keystone.git'
+main_repo: 'https://github.com/keystone-engine/keystone.git'
\ No newline at end of file
diff --git a/projects/kimageformats/Dockerfile b/projects/kimageformats/Dockerfile
index 4acc31c..060709f 100644
--- a/projects/kimageformats/Dockerfile
+++ b/projects/kimageformats/Dockerfile
@@ -22,8 +22,8 @@
 RUN git clone --depth 1 --branch=5.15 git://code.qt.io/qt/qtbase.git
 RUN git clone --depth 1 https://invent.kde.org/frameworks/karchive.git
 RUN git clone --depth 1 https://invent.kde.org/frameworks/kimageformats.git
-RUN git clone --depth 1 -b v2.0.2 https://aomedia.googlesource.com/aom
-RUN git clone --depth 1 -b v0.9.0 https://github.com/AOMediaCodec/libavif.git
+RUN git clone --depth 1 -b v3.1.0 https://aomedia.googlesource.com/aom
+RUN git clone --depth 1 -b v0.9.1 https://github.com/AOMediaCodec/libavif.git
 RUN git clone --depth 1 https://github.com/strukturag/libde265.git
 RUN git clone --depth 1 https://github.com/strukturag/libheif.git
 COPY build.sh $SRC
diff --git a/projects/kimageformats/build.sh b/projects/kimageformats/build.sh
index 0ffa60b..537056e 100644
--- a/projects/kimageformats/build.sh
+++ b/projects/kimageformats/build.sh
@@ -103,7 +103,7 @@
   fuzz_target_name=kimgio_${format}_fuzzer
 
   $SRC/qtbase/bin/moc $SRC/kimageformats/src/imageformats/$format.cpp -o $format.moc
-  $CXX $CXXFLAGS -fPIC -DHANDLER=$class -std=c++14 $SRC/kimgio_fuzzer.cc $SRC/kimageformats/src/imageformats/$format.cpp -o $OUT/$fuzz_target_name -I $SRC/qtbase/include/QtCore/ -I $SRC/qtbase/include/ -I $SRC/qtbase/include//QtGui -I $SRC/kimageformats/src/imageformats/ -I $SRC/karchive/src/ -I $SRC/qtbase/mkspecs/linux-clang-libc++/ -I $SRC/libavif/include/ -I . -L $SRC/qtbase/lib $SRC/libavif/build/libavif.a /usr/local/lib/libheif.a /usr/local/lib/liblibde265.a $SRC/aom/build.libavif/libaom.a -lQt5Gui -lQt5Core -lqtlibpng -lqtharfbuzz -lm -lqtpcre2 -ldl -lpthread $LIB_FUZZING_ENGINE /usr/local/lib/libzip.a /usr/local/lib/libz.a -lKF5Archive /usr/local/lib/libz.a
+  $CXX $CXXFLAGS -fPIC -DHANDLER=$class -std=c++17 $SRC/kimgio_fuzzer.cc $SRC/kimageformats/src/imageformats/$format.cpp -o $OUT/$fuzz_target_name -I $SRC/qtbase/include/QtCore/ -I $SRC/qtbase/include/ -I $SRC/qtbase/include//QtGui -I $SRC/kimageformats/src/imageformats/ -I $SRC/karchive/src/ -I $SRC/qtbase/mkspecs/linux-clang-libc++/ -I $SRC/libavif/include/ -I . -L $SRC/qtbase/lib $SRC/libavif/build/libavif.a /usr/local/lib/libheif.a /usr/local/lib/liblibde265.a $SRC/aom/build.libavif/libaom.a -lQt5Gui -lQt5Core -lqtlibpng -lqtharfbuzz -lm -lqtpcre2 -ldl -lpthread $LIB_FUZZING_ENGINE /usr/local/lib/libzip.a /usr/local/lib/libz.a -lKF5Archive /usr/local/lib/libz.a
 
   find . -name "*.${format}" | zip -q $OUT/${fuzz_target_name}_seed_corpus.zip -@
 )
diff --git a/projects/kimageformats/project.yaml b/projects/kimageformats/project.yaml
index d2551a8..a36df36 100644
--- a/projects/kimageformats/project.yaml
+++ b/projects/kimageformats/project.yaml
@@ -3,6 +3,7 @@
 primary_contact: tsdgeos@gmail.com
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
   - undefined
 main_repo: 'https://invent.kde.org/frameworks/kimageformats.git'
diff --git a/projects/knot-dns/build.sh b/projects/knot-dns/build.sh
index e451813..b49aa69 100755
--- a/projects/knot-dns/build.sh
+++ b/projects/knot-dns/build.sh
@@ -20,7 +20,7 @@
 # Cribbed from projects/wget2, thanks rockdaboot@gmail.com
 
 export DEPS_PATH=$SRC/knot_deps
-export PKG_CONFIG_PATH=$DEPS_PATH/lib/pkgconfig
+export PKG_CONFIG_PATH=$DEPS_PATH/lib64/pkgconfig:$DEPS_PATH/lib/pkgconfig
 export CPPFLAGS="-I$DEPS_PATH/include"
 export LDFLAGS="-L$DEPS_PATH/lib"
 export GNULIB_SRCDIR=$SRC/gnulib
@@ -75,6 +75,9 @@
 # Set up fuzzing seeds
 
 git submodule update --init -- ./fuzz_packet.in
-find ./fuzz_packet.in/ -type f -exec zip -u $OUT/fuzz_packet_seed_corpus.zip {} \;
 git submodule update --init -- ./fuzz_zscanner.in
-find ./fuzz_zscanner.in/ -type f -exec zip -u $OUT/fuzz_zscanner_seed_corpus.zip {} \;
+# ./fuzz_dname_to_str.in/ and ./fuzz_dname_from_str.in/ are stored in the base repository
+find ./fuzz_packet.in/         -type f -exec zip -u $OUT/fuzz_packet_seed_corpus.zip {} \;
+find ./fuzz_zscanner.in/       -type f -exec zip -u $OUT/fuzz_zscanner_seed_corpus.zip {} \;
+find ./fuzz_dname_to_str.in/   -type f -exec zip -u $OUT/fuzz_dname_to_str_seed_corpus.zip {} \;
+find ./fuzz_dname_from_str.in/ -type f -exec zip -u $OUT/fuzz_dname_from_str_seed_corpus.zip {} \;
diff --git a/projects/kryo/DeserializeCollectionsFuzzer.java b/projects/kryo/DeserializeCollectionsFuzzer.java
new file mode 100644
index 0000000..f28e378
--- /dev/null
+++ b/projects/kryo/DeserializeCollectionsFuzzer.java
@@ -0,0 +1,69 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer;
+
+import java.util.*;
+
+public class DeserializeCollectionsFuzzer {
+    public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+        Kryo kryo = new Kryo();
+        kryo.register(SomeClass.class);
+
+        kryo.setReferences(data.consumeBoolean());
+        if (data.consumeBoolean())
+            kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
+
+        Input in = new Input(data.consumeRemainingAsBytes());
+        try {
+            kryo.readObject(in, SomeClass.class);
+        } catch (KryoException e) {
+        } finally {
+            in.close();
+        }
+    }
+
+    public static final class SomeClass {
+        List<String> _emptyList = Collections.emptyList();
+        Set<String> _emptySet = Collections.emptySet();
+        Map<String, String> _emptyMap = Collections.emptyMap();
+        List<String> _singletonList = Collections.singletonList("foo");
+        Set<String> _singletonSet = Collections.emptySet();
+        Map<String, String> _singletonMap;
+        TreeSet<String> _treeSet;
+        TreeMap<String, Integer> _treeMap;
+        List<String> _arrayList;
+        Set<String> _hashSet;
+        Map<String, Integer> _hashMap;
+        List<Integer> _asList = Arrays.asList(1, 2, 3);
+        int[] _intArray;
+        long[] _longArray;
+        short[] _shortArray;
+        float[] _floatArray;
+        double[] _doubleArray;
+        byte[] _byteArray;
+        char[] _charArray;
+        String[] _stringArray;
+        Integer[] _integerArray;
+        BitSet _bitSet;
+    }
+
+}
diff --git a/projects/kryo/DeserializeNumbersFuzzer.java b/projects/kryo/DeserializeNumbersFuzzer.java
new file mode 100644
index 0000000..80137c7
--- /dev/null
+++ b/projects/kryo/DeserializeNumbersFuzzer.java
@@ -0,0 +1,76 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class DeserializeNumbersFuzzer {
+    public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+        Kryo kryo = new Kryo();
+        kryo.register(SomeClass.class);
+
+        kryo.setReferences(data.consumeBoolean());
+        if (data.consumeBoolean())
+            kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
+
+        Input in = new Input(data.consumeRemainingAsBytes());
+        try {
+            kryo.readObject(in, SomeClass.class);
+        } catch (KryoException e) {
+        } finally {
+            in.close();
+        }
+    }
+
+    public static final class SomeClass {
+        Date _date;
+        TimeZone _timeZone;
+        Calendar _calendar;
+        Locale _locale;
+        Integer[] _integerArray;
+        boolean _boolean;
+        char _char;
+        byte _byte;
+        short _short;
+        int _int1;
+        int _int2;
+        long _long;
+        float _float;
+        double _double;
+        Boolean _Boolean;
+        Character _Character;
+        Byte _Byte;
+        Short _Short;
+        Integer _Integer;
+        Long _Long;
+        Float _Float;
+        Double _Double;
+        BigInteger _bigInteger;
+        BigDecimal _bigDecimal;
+        AtomicInteger _atomicInteger;
+        AtomicLong _atomicLong;
+    }
+}
diff --git a/projects/kryo/DeserializeStringFuzzer.java b/projects/kryo/DeserializeStringFuzzer.java
new file mode 100644
index 0000000..9fe77ec
--- /dev/null
+++ b/projects/kryo/DeserializeStringFuzzer.java
@@ -0,0 +1,45 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer;
+
+public class DeserializeStringFuzzer {
+    public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+        Kryo kryo = new Kryo();
+        kryo.register(SomeClass.class);
+
+        kryo.setReferences(data.consumeBoolean());
+        if (data.consumeBoolean())
+            kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
+
+        Input in = new Input(data.consumeRemainingAsBytes());
+        try {
+            kryo.readObject(in, SomeClass.class);
+        } catch (KryoException e) {
+        } finally {
+            in.close();
+        }
+    }
+
+    public static final class SomeClass {
+        String value;
+    }
+}
diff --git a/projects/kryo/Dockerfile b/projects/kryo/Dockerfile
new file mode 100644
index 0000000..bf512f0
--- /dev/null
+++ b/projects/kryo/Dockerfile
@@ -0,0 +1,29 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+    unzip maven.zip -d $SRC/maven && \
+    rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+RUN git clone --depth 1 https://github.com/EsotericSoftware/kryo
+
+COPY build.sh $SRC/
+COPY DeserializeCollectionsFuzzer.java DeserializeNumbersFuzzer.java DeserializeStringFuzzer.java $SRC/
+WORKDIR $SRC/kryo
diff --git a/projects/kryo/build.sh b/projects/kryo/build.sh
new file mode 100644
index 0000000..9d53d39
--- /dev/null
+++ b/projects/kryo/build.sh
@@ -0,0 +1,51 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15"
+
+$MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS
+current_version=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+-Dexpression=project.version -q -DforceStdout)
+cp "target/kryo-$current_version.jar" $OUT/kryo.jar
+
+ALL_JARS="kryo.jar"
+
+# The classpath at build-time includes the project jars in $OUT as well as the
+# Jazzer API.
+BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
+
+# All .jar and .class files lie in the same directory as the fuzzer at runtime.
+RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
+
+for fuzzer in $(find $SRC -name '*Fuzzer.java'); do
+  fuzzer_basename=$(basename -s .java $fuzzer)
+  javac --enable-preview --release 15 -cp $BUILD_CLASSPATH $fuzzer
+  cp $SRC/$fuzzer_basename.class $OUT/
+  cp $SRC/${fuzzer_basename}\$SomeClass.class $OUT/
+
+  # Create an execution wrapper that executes Jazzer with the correct arguments.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m;--enable-preview\" \
+\$@" > $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
+done
diff --git a/projects/kryo/project.yaml b/projects/kryo/project.yaml
new file mode 100644
index 0000000..8b747ac
--- /dev/null
+++ b/projects/kryo/project.yaml
@@ -0,0 +1,12 @@
+homepage: "http://esotericsoftware.com/"
+language: jvm
+primary_contact: "thomas@umschalt.com"
+auto_ccs:
+  - "meumertzheim@code-intelligence.com"
+  - "wagner@code-intelligence.com"
+  - "meumertzheim@code-intelligence.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://github.com/EsotericSoftware/kryo"
+sanitizers:
+  - address
diff --git a/projects/kubernetes/Dockerfile b/projects/kubernetes/Dockerfile
index e4ebed8..e6391ad 100644
--- a/projects/kubernetes/Dockerfile
+++ b/projects/kubernetes/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 RUN go get github.com/ianlancetaylor/demangle
 RUN git clone --depth 1 https://github.com/kubernetes/kubernetes.git
diff --git a/projects/lame/project.yaml b/projects/lame/project.yaml
index b6bd382..630fd76 100644
--- a/projects/lame/project.yaml
+++ b/projects/lame/project.yaml
@@ -5,7 +5,8 @@
     - "bouvigne@gmail.com"
 sanitizers:
  - address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 architectures:
  - x86_64
- - i386
+ - i386
\ No newline at end of file
diff --git a/projects/leveldb/project.yaml b/projects/leveldb/project.yaml
index 7eecedc..710887f 100644
--- a/projects/leveldb/project.yaml
+++ b/projects/leveldb/project.yaml
@@ -6,5 +6,6 @@
   - "david@adalogics.com"
 sanitizers:
   - address
-  - memory
-main_repo: 'https://github.com/google/leveldb.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: 'https://github.com/google/leveldb.git'
\ No newline at end of file
diff --git a/projects/libaom/Dockerfile b/projects/libaom/Dockerfile
index a911f33..2bfa6aa 100644
--- a/projects/libaom/Dockerfile
+++ b/projects/libaom/Dockerfile
@@ -18,5 +18,5 @@
 RUN apt-get update && apt-get install -y cmake yasm wget
 RUN git clone https://aomedia.googlesource.com/aom
 ADD https://storage.googleapis.com/aom-test-data/fuzzer/dec_fuzzer_seed_corpus.zip $SRC/
-COPY build.sh av1_dec_fuzzer.dict $SRC/
+COPY build.sh $SRC/
 WORKDIR aom
diff --git a/projects/libaom/av1_dec_fuzzer.dict b/projects/libaom/av1_dec_fuzzer.dict
deleted file mode 100644
index fb16388..0000000
--- a/projects/libaom/av1_dec_fuzzer.dict
+++ /dev/null
@@ -1,5 +0,0 @@
-# IVF Signature + version (bytes 0-5)
-kw1="DKIF\x00\x00"
-
-# AV1 codec fourCC (bytes 8-11)
-kw2="AV01"
diff --git a/projects/libaom/build.sh b/projects/libaom/build.sh
index fc25bbf..590b45a 100755
--- a/projects/libaom/build.sh
+++ b/projects/libaom/build.sh
@@ -65,5 +65,5 @@
 
 # copy seed corpus.
 cp $SRC/dec_fuzzer_seed_corpus.zip $OUT/${fuzzer_name}_seed_corpus.zip
-cp $SRC/av1_dec_fuzzer.dict $OUT/${fuzzer_name}.dict
+cp $SRC/aom/examples/av1_dec_fuzzer.dict $OUT/${fuzzer_name}.dict
 
diff --git a/projects/libaom/project.yaml b/projects/libaom/project.yaml
index dedc304..02fe387 100644
--- a/projects/libaom/project.yaml
+++ b/projects/libaom/project.yaml
@@ -6,10 +6,10 @@
 - memory
 - undefined
 auto_ccs:
-- huisu@google.com
 - jaikk@google.com
 - jzern@google.com
 - wtc@google.com
+- yunqingwang@google.com
 vendor_ccs:
 - twsmith@mozilla.com
 main_repo: 'https://aomedia.googlesource.com/aom'
diff --git a/projects/libarchive/Dockerfile b/projects/libarchive/Dockerfile
index bd07669..c41e51c 100644
--- a/projects/libarchive/Dockerfile
+++ b/projects/libarchive/Dockerfile
@@ -16,12 +16,12 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 
-# Installing optional libraries can utilize more code path and/or improve
-# performance (avoid calling external programs).
 RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config \
         libbz2-dev liblzo2-dev liblzma-dev liblz4-dev libz-dev \
-        libxml2-dev libssl-dev libacl1-dev libattr1-dev lrzip \
-	liblz4-tool lzop zstd lcab genisoimage jlha-utils rar default-jdk
+        libssl-dev libacl1-dev libattr1-dev lrzip \
+	      liblz4-tool lzop zstd lcab genisoimage jlha-utils rar default-jdk
 RUN git clone --depth 1 https://github.com/libarchive/libarchive.git
-WORKDIR libarchive
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
+
 COPY build.sh libarchive_fuzzer.cc $SRC/
+WORKDIR $SRC
diff --git a/projects/libarchive/build.sh b/projects/libarchive/build.sh
index 87587a5..a46a44d 100755
--- a/projects/libarchive/build.sh
+++ b/projects/libarchive/build.sh
@@ -15,18 +15,35 @@
 #
 ################################################################################
 
-# build the project
-./build/autogen.sh
-./configure
-make -j$(nproc) all
+# compile libxml2 from source so we can statically link
+DEPS=/deps
+mkdir ${DEPS}
+cd $SRC/libxml2
+./autogen.sh \
+    --without-debug \
+    --without-ftp \
+    --without-http \
+    --without-legacy \
+    --without-python
+make -j$(nproc)
+make install
+cp .libs/libxml2.a ${DEPS}/
+cd $SRC/libarchive
+
+sed -i 's/-Wall//g' ./CMakeLists.txt
+sed -i 's/-Werror//g' ./CMakeLists.txt
+
+mkdir build2
+cd build2
+cmake ../
+make
 
 # build seed
 cp $SRC/libarchive/contrib/oss-fuzz/corpus.zip\
-       	$OUT/libarchive_fuzzer_seed_corpus.zip
+        $OUT/libarchive_fuzzer_seed_corpus.zip
 
 # build fuzzer(s)
-$CXX $CXXFLAGS -Ilibarchive \
+$CXX $CXXFLAGS -I../libarchive \
     $SRC/libarchive_fuzzer.cc -o $OUT/libarchive_fuzzer \
-    $LIB_FUZZING_ENGINE .libs/libarchive.a \
-    -Wl,-Bstatic -lbz2 -llzo2  -lxml2 -llzma -lz -lcrypto -llz4 -licuuc \
-    -licudata -Wl,-Bdynamic
+    $LIB_FUZZING_ENGINE ./libarchive/libarchive.a \
+    -lcrypto -lacl -llzma -llz4 -lbz2 -lz ${DEPS}/libxml2.a
diff --git a/projects/libass/Dockerfile b/projects/libass/Dockerfile
index b0758ce..88801cc 100644
--- a/projects/libass/Dockerfile
+++ b/projects/libass/Dockerfile
@@ -15,11 +15,10 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libfreetype6-dev libfontconfig1-dev python3-pip && \
+RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libfontconfig1-dev libfreetype-dev libfribidi-dev python3-pip && \
     pip3 install meson==0.53.0 ninja
 
 RUN git clone --depth 1 https://github.com/libass/libass.git
-RUN git clone --depth 1 https://github.com/behdad/fribidi.git
 RUN git clone --depth 1 https://github.com/harfbuzz/harfbuzz.git
 
 COPY build.sh libass_fuzzer.cc *.dict *.options $SRC/
diff --git a/projects/libass/build.sh b/projects/libass/build.sh
index 44006e3..8e313fd 100755
--- a/projects/libass/build.sh
+++ b/projects/libass/build.sh
@@ -15,10 +15,6 @@
 #
 ################################################################################
 
-cd $SRC/fribidi
-./autogen.sh --disable-docs --enable-static=yes --enable-shared=no --with-pic=yes --prefix=/work/
-make install
-
 cd $SRC/harfbuzz
 
 # setup
@@ -33,6 +29,7 @@
 CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" \
 meson --default-library=static --wrap-mode=nodownload \
       -Dfuzzer_ldflags="$(echo $LIB_FUZZING_ENGINE)" \
+      -Dtests=disabled \
       --prefix=/work/ --libdir=lib $build \
   || (cat build/meson-logs/meson-log.txt && false)
 meson install -C $build
@@ -44,10 +41,11 @@
 ./configure --disable-asm
 make -j$(nproc)
 
-$CXX $CXXFLAGS -std=c++11 -I$SRC/libass -L/work/lib \
+$CXX $CXXFLAGS -std=c++11 -I$SRC/libass \
     $SRC/libass_fuzzer.cc -o $OUT/libass_fuzzer \
     $LIB_FUZZING_ENGINE libass/.libs/libass.a \
-    -Wl,-Bstatic -lfontconfig  -lfribidi -lfreetype -lharfbuzz -lz -lpng12 \
-    -lexpat -Wl,-Bdynamic
+    -Wl,-Bstatic \
+    $(pkg-config --static --libs fontconfig freetype2 fribidi harfbuzz | sed 's/-lm //g') \
+    -Wl,-Bdynamic
 
 cp $SRC/*.dict $SRC/*.options $OUT/
diff --git a/projects/libass/libass_fuzzer.cc b/projects/libass/libass_fuzzer.cc
index 5254faf..8cb11a6 100644
--- a/projects/libass/libass_fuzzer.cc
+++ b/projects/libass/libass_fuzzer.cc
@@ -1,3 +1,21 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -12,29 +30,35 @@
 static const int kFrameWidth = 1280;
 static const int kFrameHeight = 720;
 
-static bool init(int frame_w, int frame_h) {
-  ass_library = ass_library_init();
-  if (!ass_library) {
-    printf("ass_library_init failed!\n");
-    exit(1);
+struct init {
+  init(int frame_w, int frame_h) {
+    ass_library = ass_library_init();
+    if (!ass_library) {
+      printf("ass_library_init failed!\n");
+      exit(1);
+    }
+
+    ass_set_message_cb(ass_library, msg_callback, NULL);
+
+    ass_renderer = ass_renderer_init(ass_library);
+    if (!ass_renderer) {
+      printf("ass_renderer_init failed!\n");
+      exit(1);
+    }
+
+    ass_set_frame_size(ass_renderer, frame_w, frame_h);
+    ass_set_fonts(ass_renderer, nullptr, "sans-serif",
+                  ASS_FONTPROVIDER_AUTODETECT, nullptr, 1);
   }
 
-  ass_set_message_cb(ass_library, msg_callback, NULL);
-
-  ass_renderer = ass_renderer_init(ass_library);
-  if (!ass_renderer) {
-    printf("ass_renderer_init failed!\n");
-    exit(1);
+  ~init() {
+    ass_renderer_done(ass_renderer);
+    ass_library_done(ass_library);
   }
-
-  ass_set_frame_size(ass_renderer, frame_w, frame_h);
-  ass_set_fonts(ass_renderer, nullptr, "sans-serif",
-                ASS_FONTPROVIDER_AUTODETECT, nullptr, 1);
-  return true;
-}
+};
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  static bool initialized = init(kFrameWidth, kFrameHeight);
+  static init initialized(kFrameWidth, kFrameHeight);
 
   ASS_Track *track = ass_read_memory(ass_library, (char *)data, size, nullptr);
   if (!track) return 0;
diff --git a/projects/libass/project.yaml b/projects/libass/project.yaml
index bfcb93e..9fdaf42 100644
--- a/projects/libass/project.yaml
+++ b/projects/libass/project.yaml
@@ -1,10 +1,9 @@
 homepage: "https://github.com/libass/libass"
 language: c++
-primary_contact: "greg@kinoho.net"
+primary_contact: "chortos@inbox.lv"
 auto_ccs:
+  - "greg@kinoho.net"
   - "rodger.combs@gmail.com"
-  - "nfxjfg@gmail.com"
-  - "chortos@inbox.lv"
   - "vabnick@gmail.com"
 sanitizers:
   - address
diff --git a/projects/libavc/project.yaml b/projects/libavc/project.yaml
index 1f5422f..845e523 100644
--- a/projects/libavc/project.yaml
+++ b/projects/libavc/project.yaml
@@ -12,10 +12,12 @@
   - bcreasey@google.com
   - hamzeh@google.com
   - geuteneier@google.com
-  - hollyhall@google.com
-  - mikelogan@google.com
   - maverickm@google.com
   - warrenwright@google.com
+  - ailport@google.com
+  - kimtony@google.com
+  - faerber@google.com
+  - greendonald@google.com
 architectures:
   - x86_64
   - i386
diff --git a/projects/libavif/Dockerfile b/projects/libavif/Dockerfile
index a1f030e..c1d918b 100644
--- a/projects/libavif/Dockerfile
+++ b/projects/libavif/Dockerfile
@@ -15,19 +15,11 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-
-ADD bionic.list /etc/apt/sources.list.d/bionic.list
-ADD nasm_apt.pin /etc/apt/preferences
-
 RUN apt-get update && \
-    apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel cmake git && \
+    apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel cmake git nasm && \
     pip3 install meson ninja
 
 RUN git clone --depth 1 https://github.com/AOMediaCodec/libavif.git libavif
 WORKDIR libavif
 
-RUN curl -L https://download.videolan.org/contrib/nasm/nasm-2.14.tar.gz | tar xvz
-RUN cd nasm-2.14 && ./configure && make -j2 && ln -s `pwd`/nasm /usr/bin/nasm && cd ..
-RUN nasm --version
-
 COPY build.sh avif_decode_seed_corpus.zip $SRC/
diff --git a/projects/libavif/bionic.list b/projects/libavif/bionic.list
deleted file mode 100644
index 8621803..0000000
--- a/projects/libavif/bionic.list
+++ /dev/null
@@ -1,2 +0,0 @@
-# use nasm 2.13.02 from bionic
-deb http://archive.ubuntu.com/ubuntu/ bionic universe
diff --git a/projects/libavif/build.sh b/projects/libavif/build.sh
index 130709f..fe7eba0 100755
--- a/projects/libavif/build.sh
+++ b/projects/libavif/build.sh
@@ -16,7 +16,7 @@
 ################################################################################
 
 # build dav1d
-cd ext && bash dav1d.cmd && cd ..
+cd ext && bash dav1d_oss_fuzz.sh && cd ..
 
 # build libavif
 mkdir build
diff --git a/projects/libavif/nasm_apt.pin b/projects/libavif/nasm_apt.pin
deleted file mode 100644
index 6909902..0000000
--- a/projects/libavif/nasm_apt.pin
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: *
-Pin: release n=bionic
-Pin-Priority: 1
-
-Package: nasm
-Pin: release n=bionic
-Pin-Priority: 555
diff --git a/projects/libcacard/Dockerfile b/projects/libcacard/Dockerfile
index 5e280b9..7d7a0ab 100644
--- a/projects/libcacard/Dockerfile
+++ b/projects/libcacard/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y pkg-config libglib2.0-dev gyp libsqlite3-dev mercurial python3-pip
+RUN apt-get update && apt-get install -y pkg-config libglib2.0-dev gyp libsqlite3-dev mercurial python3-pip python
 # Because Ubuntu has really ancient meson out there
 RUN pip3 install meson ninja
 
diff --git a/projects/libcacard/build.sh b/projects/libcacard/build.sh
index 719502e..f12cb41 100755
--- a/projects/libcacard/build.sh
+++ b/projects/libcacard/build.sh
@@ -33,7 +33,11 @@
 sed -i "s/\/lib/\/lib\/Debug/g" dist/Debug/lib/pkgconfig/nss.pc
 sed -i "s/include\/nspr/public\/nss/g" dist/Debug/lib/pkgconfig/nss.pc
 sed -i "s/NSPR/NSS/g" dist/Debug/lib/pkgconfig/nss.pc
-sed -i "s/Libs:.*/Libs: -L\${libdir} -lssl -lsmime -lnssdev -lnss_static -lpk11wrap_static -lcryptohi -lcerthi -lcertdb -lnssb -lnssutil -lnsspki -ldl -lm -lsqlite -lsoftokn_static -lfreebl_static -lgcm-aes-x86_c_lib -lhw-acc-crypto-avx -lhw-acc-crypto-avx2 /g" dist/Debug/lib/pkgconfig/nss.pc
+LIBS="-lssl -lsmime -lnssdev -lnss_static -lpk11wrap_static -lcryptohi"
+LIBS="$LIBS -lcerthi -lcertdb -lnssb -lnssutil -lnsspki -ldl -lm -lsqlite"
+LIBS="$LIBS -lsoftokn_static -lsha-x86_c_lib -lfreebl_static"
+LIBS="$LIBS -lgcm-aes-x86_c_lib -lhw-acc-crypto-avx -lhw-acc-crypto-avx2"
+sed -i "s/Libs:.*/Libs: -L\${libdir} $LIBS/g" dist/Debug/lib/pkgconfig/nss.pc
 echo "Requires: nspr" >> dist/Debug/lib/pkgconfig/nss.pc
 
 export NSS_NSPR_PATH=$(realpath $SRC/nss-nspr/)
diff --git a/projects/libchewing/Dockerfile b/projects/libchewing/Dockerfile
deleted file mode 100644
index 4a77e24..0000000
--- a/projects/libchewing/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2016 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool texinfo
-
-RUN git clone --depth 1 https://github.com/chewing/libchewing.git
-WORKDIR libchewing
-COPY build.sh chewing_fuzzer_common.[ch] chewing_*_fuzzer.c $SRC/
diff --git a/projects/libchewing/build.sh b/projects/libchewing/build.sh
deleted file mode 100755
index e721a0b..0000000
--- a/projects/libchewing/build.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash -eu
-# Copyright 2016 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-# build the library.
-./autogen.sh
-./configure --disable-shared --enable-static --without-sqlite3
-make clean
-make -j$(nproc) all
-
-# build your fuzzer(s)
-make -C test CFLAGS="$CFLAGS -Dmain=stress_main -Drand=get_fuzz_input" stress.o
-
-$CC $CFLAGS -c $SRC/chewing_fuzzer_common.c -o $WORK/chewing_fuzzer_common.o
-
-for variant in default random_init dynamic_config; do
-    $CC $CFLAGS -c $SRC/chewing_${variant}_fuzzer.c -o $WORK/chewing_${variant}_fuzzer.o
-    $CXX $CXXFLAGS \
-      -o $OUT/chewing_${variant}_fuzzer \
-      $WORK/chewing_${variant}_fuzzer.o $WORK/chewing_fuzzer_common.o \
-      test/stress.o test/.libs/libtesthelper.a src/.libs/libchewing.a \
-      $LIB_FUZZING_ENGINE
-done
-
-# install data files
-make -j$(nproc) -C data pkgdatadir=$OUT install
diff --git a/projects/libchewing/chewing_default_fuzzer.c b/projects/libchewing/chewing_default_fuzzer.c
deleted file mode 100644
index dd6fc7a..0000000
--- a/projects/libchewing/chewing_default_fuzzer.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-#include "chewing_fuzzer_common.h"
-
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  fuzz_input = fuzz_ptr = data;
-  fuzz_size = size;
-
-  const char* stress_argv[] = {
-      "./chewing_fuzzer", "-loop", "1", NULL,
-  };
-  stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1,
-              (char**)stress_argv);
-  return 0;
-}
diff --git a/projects/libchewing/chewing_dynamic_config_fuzzer.c b/projects/libchewing/chewing_dynamic_config_fuzzer.c
deleted file mode 100644
index 5479c1e..0000000
--- a/projects/libchewing/chewing_dynamic_config_fuzzer.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-#include "chewing_fuzzer_common.h"
-
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  fuzz_input = fuzz_ptr = data;
-  fuzz_size = size;
-
-  const char* stress_argv[] = {
-      "./chewing_fuzzer", "-loop", "1", "-extra", NULL,
-  };
-  stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1,
-              (char**)stress_argv);
-  return 0;
-}
diff --git a/projects/libchewing/chewing_fuzzer_common.c b/projects/libchewing/chewing_fuzzer_common.c
deleted file mode 100644
index 34426ea..0000000
--- a/projects/libchewing/chewing_fuzzer_common.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "chewing_fuzzer_common.h"
-
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static char userphrase_path[] = "/tmp/chewing_userphrase.db.XXXXXX";
-
-int LLVMFuzzerInitialize(int* argc, char*** argv) {
-  char* exe_path = (*argv)[0];
-
-  // dirname() can modify its argument.
-  char* exe_path_copy = strdup(exe_path);
-  char* dir = dirname(exe_path_copy);
-
-  // Assume data files are at the same location as executable.
-  setenv("CHEWING_PATH", dir, 0);
-  free(exe_path_copy);
-
-  // Specify user db of this process. So we can run multiple fuzzers at the
-  // same time.
-  mktemp(userphrase_path);
-  setenv("TEST_USERPHRASE_PATH", userphrase_path, 0);
-  return 0;
-}
-
-int get_fuzz_input() {
-  if (fuzz_ptr - fuzz_input >= fuzz_size)
-    return EOF;
-  return *fuzz_ptr++;
-}
diff --git a/projects/libchewing/chewing_fuzzer_common.h b/projects/libchewing/chewing_fuzzer_common.h
deleted file mode 100644
index 5032d65..0000000
--- a/projects/libchewing/chewing_fuzzer_common.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef CHEWING_FUZZER_COMMON_H
-#define CHEWING_FUZZER_COMMON_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-const uint8_t* fuzz_ptr;
-const uint8_t* fuzz_input;
-size_t fuzz_size;
-
-int stress_main(int argc, char** argv);
-
-#endif
diff --git a/projects/libchewing/chewing_random_init_fuzzer.c b/projects/libchewing/chewing_random_init_fuzzer.c
deleted file mode 100644
index e0d755f..0000000
--- a/projects/libchewing/chewing_random_init_fuzzer.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-#include "chewing_fuzzer_common.h"
-
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  fuzz_input = fuzz_ptr = data;
-  fuzz_size = size;
-
-  const char* stress_argv[] = {
-      "./chewing_fuzzer", "-loop", "1", "-init", NULL,
-  };
-  stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1,
-              (char**)stress_argv);
-  return 0;
-}
diff --git a/projects/libchewing/project.yaml b/projects/libchewing/project.yaml
deleted file mode 100644
index 1dd3e6e..0000000
--- a/projects/libchewing/project.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-homepage: "http://chewing.im/"
-language: c++
-disabled: true
-view_restrictions: none
-main_repo: 'https://github.com/chewing/libchewing.git'
diff --git a/projects/libecc/Dockerfile b/projects/libecc/Dockerfile
new file mode 100644
index 0000000..aaeed8e
--- /dev/null
+++ b/projects/libecc/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool wget python
+RUN git clone https://github.com/ANSSI-FR/libecc.git
+RUN git clone --depth 1 https://github.com/randombit/botan.git
+RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+COPY build.sh $SRC/
diff --git a/projects/libecc/build.sh b/projects/libecc/build.sh
new file mode 100755
index 0000000..558b852
--- /dev/null
+++ b/projects/libecc/build.sh
@@ -0,0 +1,69 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL"
+export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE"
+
+# Install Boost headers
+cd $SRC/
+tar jxf boost_1_74_0.tar.bz2
+cd boost_1_74_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+cp -R boost/ /usr/include/
+
+# Build libecc
+cd $SRC/libecc
+git checkout cryptofuzz
+export CFLAGS="$CFLAGS -DUSE_CRYPTOFUZZ"
+make -j$(nproc) build/libsign.a
+export LIBECC_PATH=$(realpath .)
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_LIBECC"
+
+# Build Botan
+cd $SRC/botan
+if [[ $CFLAGS != *-m32* ]]
+then
+    ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator,x509,tls --build-targets=static --without-documentation
+else
+    ./configure.py --cpu=x86_32 --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator,x509,tls --build-targets=static --without-documentation
+fi
+make -j$(nproc)
+
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
+export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a"
+export BOTAN_INCLUDE_PATH="$SRC/botan/build/include"
+
+# Build Cryptofuzz
+cd $SRC/cryptofuzz
+python gen_repository.py
+rm extra_options.h
+echo -n '"' >>extra_options.h
+echo -n '--force-module=libecc ' >>extra_options.h
+echo -n '--operations=Digest,ECC_PrivateToPublic,ECDSA_Sign,ECDSA_Verify,ECGDSA_Sign,ECGDSA_Verify,ECRDSA_Sign,ECRDSA_Verify,ECC_Point_Add,ECC_Point_Mul,BignumCalc ' >>extra_options.h
+echo -n '--curves=brainpool224r1,brainpool256r1,brainpool384r1,brainpool512r1,secp192r1,secp224r1,secp256r1,secp384r1,secp521r1,secp256k1 ' >>extra_options.h
+echo -n '--digests=NULL,SHA224,SHA256,SHA3-224,SHA3-256,SHA3-384,SHA3-512,SHA384,SHA512,SHA512-224,SHA512-256,SM3,SHAKE256_114,STREEBOG-256,STREEBOG-512 ' >>extra_options.h
+echo -n '--calcops=Add,AddMod,And,Bit,GCD,InvMod,IsOdd,IsOne,IsZero,LShift1,Mod,Mul,MulMod,NumBits,Or,RShift,Sqr,Sub,SubMod,Xor ' >>extra_options.h
+echo -n '"' >>extra_options.h
+cd modules/libecc/
+make -B -j$(nproc)
+cd ../botan/
+make -B -j$(nproc)
+cd ../../
+make -B -j$(nproc)
+
+cp cryptofuzz $OUT/cryptofuzz-libecc
diff --git a/projects/libecc/project.yaml b/projects/libecc/project.yaml
new file mode 100644
index 0000000..2fe474f
--- /dev/null
+++ b/projects/libecc/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://github.com/ANSSI-FR/libecc"
+language: c++
+primary_contact: "guidovranken@gmail.com"
+main_repo: "https://github.com/ANSSI-FR/libecc.git"
+auto_ccs:
+    - "dev.libecc@gmail.com"
+sanitizers:
+ - address
+ - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+architectures:
+ - x86_64
+ - i386
diff --git a/projects/libevent/Dockerfile b/projects/libevent/Dockerfile
index 04fdc04..0c34bd7 100644
--- a/projects/libevent/Dockerfile
+++ b/projects/libevent/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool cmake
+RUN apt-get update && apt-get install -y make autoconf automake libtool cmake pkg-config
 RUN git clone --depth 1 https://github.com/libevent/libevent.git libevent
 WORKDIR libevent
 COPY build.sh *.cc $SRC/
diff --git a/projects/libevent/project.yaml b/projects/libevent/project.yaml
index feb600c..be4d8bd 100644
--- a/projects/libevent/project.yaml
+++ b/projects/libevent/project.yaml
@@ -3,9 +3,10 @@
 primary_contact: "a3at.mail@gmail.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 architectures:
   - x86_64
   - i386
-main_repo: 'https://github.com/libevent/libevent.git'
+main_repo: 'https://github.com/libevent/libevent.git'
\ No newline at end of file
diff --git a/projects/libfdk-aac/project.yaml b/projects/libfdk-aac/project.yaml
index 0613f72..922606a 100644
--- a/projects/libfdk-aac/project.yaml
+++ b/projects/libfdk-aac/project.yaml
@@ -1,4 +1,5 @@
 homepage: https://android.googlesource.com/platform/external/aac/
+main_repo: 'https://android.googlesource.com/platform/external/aac/'
 language: c++
 primary_contact: audio-fdk@iis.fraunhofer.de
 auto_ccs:
@@ -7,10 +8,12 @@
   - bcreasey@google.com
   - hamzeh@google.com
   - geuteneier@google.com
-  - hollyhall@google.com
-  - mikelogan@google.com
   - maverickm@google.com
   - warrenwright@google.com
+  - ailport@google.com
+  - kimtony@google.com
+  - faerber@google.com
+  - greendonald@google.com
 fuzzing_engines:
   - libfuzzer
   - afl
diff --git a/projects/libfido2/project.yaml b/projects/libfido2/project.yaml
index 5a351a0..d335eea 100644
--- a/projects/libfido2/project.yaml
+++ b/projects/libfido2/project.yaml
@@ -9,7 +9,8 @@
 sanitizers:
     - address
     - undefined
-    - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 fuzzing_engines:
     - libfuzzer
-main_repo: 'https://github.com/Yubico/libfido2'
+main_repo: 'https://github.com/Yubico/libfido2'
\ No newline at end of file
diff --git a/projects/libheif/build.sh b/projects/libheif/build.sh
index 70618a2..7c303ea 100755
--- a/projects/libheif/build.sh
+++ b/projects/libheif/build.sh
@@ -74,7 +74,8 @@
     --enable-static \
     --disable-examples \
     --disable-go \
-    --enable-libfuzzer="$LIB_FUZZING_ENGINE"
+    --enable-libfuzzer="$LIB_FUZZING_ENGINE" \
+    CPPFLAGS="-I$DEPS_PATH/include"
 make clean
 make -j$(nproc)
 
diff --git a/projects/libhevc/project.yaml b/projects/libhevc/project.yaml
index 5d84b08..4af0cab 100644
--- a/projects/libhevc/project.yaml
+++ b/projects/libhevc/project.yaml
@@ -12,10 +12,12 @@
   - bcreasey@google.com
   - hamzeh@google.com
   - geuteneier@google.com
-  - hollyhall@google.com
-  - mikelogan@google.com
   - maverickm@google.com
   - warrenwright@google.com
+  - ailport@google.com
+  - kimtony@google.com
+  - faerber@google.com
+  - greendonald@google.com
 architectures:
   - x86_64
   - i386
diff --git a/projects/libhtp/project.yaml b/projects/libhtp/project.yaml
index 3b861d5..753887a 100644
--- a/projects/libhtp/project.yaml
+++ b/projects/libhtp/project.yaml
@@ -7,6 +7,7 @@
 
 sanitizers:
 - address
-- memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 - undefined
-main_repo: 'https://github.com/OISF/libhtp.git'
+main_repo: 'https://github.com/OISF/libhtp.git'
\ No newline at end of file
diff --git a/projects/libidn/Dockerfile b/projects/libidn/Dockerfile
index 3bb5413..e6aebff 100644
--- a/projects/libidn/Dockerfile
+++ b/projects/libidn/Dockerfile
@@ -22,7 +22,7 @@
  autoconf-archive \
  automake \
  libtool \
- gettext gengetopt curl gperf
+ gettext gengetopt curl gperf wget
 
 RUN git clone --depth=1 https://git.savannah.gnu.org/git/libidn.git
 
diff --git a/projects/libidn/build.sh b/projects/libidn/build.sh
index b66d8b9..5aa0ea3 100755
--- a/projects/libidn/build.sh
+++ b/projects/libidn/build.sh
@@ -18,10 +18,10 @@
 # avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite)
 export ASAN_OPTIONS=detect_leaks=0
 
-make CFGFLAGS="--enable-static --disable-doc"
-make clean
-make -j1
-make -j$(nproc) check
+./bootstrap
+./configure --enable-static --disable-doc
+make -j
+make -j check
 
 cd fuzz
 make oss-fuzz
diff --git a/projects/libigl/Dockerfile b/projects/libigl/Dockerfile
new file mode 100644
index 0000000..2fba95a
--- /dev/null
+++ b/projects/libigl/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make
+RUN git clone --depth 1 https://github.com/libigl/libigl
+WORKDIR $SRC/libigl
+COPY igl_fuzzer.cpp \
+     build.sh \
+     $SRC/
+
diff --git a/projects/libigl/build.sh b/projects/libigl/build.sh
new file mode 100755
index 0000000..d2a39f1
--- /dev/null
+++ b/projects/libigl/build.sh
@@ -0,0 +1,39 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir build-dir && cd build-dir
+cmake -DLIBIGL_WITH_OPENGL=OFF \
+      -DLIBIGL_WITH_OPENGL_GLFW=OFF \
+      -DLIBIGL_WITH_OPENGL_GLFW_IMGUI=OFF \
+      -DLIBIGL_WITH_COMISO=OFF \
+      -DLIBIGL_WITH_EMBREE=OFF \
+      -DLIBIGL_WITH_PNG=OFF \
+      -DLIBIGL_WITH_TETGEN=OFF \
+      -DLIBIGL_WITH_TRIANGLE=OFF \
+      -DLIBIGL_WITH_PREDICATES=OFF \
+      -DLIBIGL_WITH_XML=OFF \
+      -DLIBIGL_BUILD_TESTS=OFF \
+      ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DIGL_STATIC_LIBRARY \
+     -I/src/libigl/include \
+     -isystem /src/libigl/cmake/../include \
+     -isystem /src/libigl/cmake/../external/eigen \
+     -c $SRC/igl_fuzzer.cpp -o fuzzer.o
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzzer.o   \
+     -o $OUT/igl_fuzzer $SRC/libigl/build-dir/libigl.a
diff --git a/projects/libigl/igl_fuzzer.cpp b/projects/libigl/igl_fuzzer.cpp
new file mode 100644
index 0000000..34e4dfe
--- /dev/null
+++ b/projects/libigl/igl_fuzzer.cpp
@@ -0,0 +1,37 @@
+/*  Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <igl/MshLoader.h>
+#include <iostream>
+
+extern "C"
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+    char *nullt_string = (char *)malloc(size+1);
+    if (nullt_string == NULL){
+            return 0;
+    }
+    memcpy(nullt_string, data, size);
+    nullt_string[size] = '\0';
+    std::ofstream fuzz_file;
+    fuzz_file.open ("fuzz_file.msh");
+    fuzz_file << nullt_string;
+    fuzz_file.close();
+    try {
+    	igl::MshLoader msh_loader("fuzz_file.msh");
+    } catch (...) {}
+    free(nullt_string);
+    return 0;
+}
+
diff --git a/projects/libigl/project.yaml b/projects/libigl/project.yaml
new file mode 100644
index 0000000..411d0da
--- /dev/null
+++ b/projects/libigl/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://libigl.github.io"
+language: c++
+primary_contact: "github@jdumas.org"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+main_repo: "https://github.com/libigl/libigl"
diff --git a/projects/libjpeg-turbo/Dockerfile b/projects/libjpeg-turbo/Dockerfile
index 40c8f49..74f1249 100644
--- a/projects/libjpeg-turbo/Dockerfile
+++ b/projects/libjpeg-turbo/Dockerfile
@@ -15,12 +15,13 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool yasm curl cmake
+RUN apt-get update && apt-get install -y make yasm cmake
 RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo
 
-RUN mkdir afl-testcases
-RUN cd afl-testcases/ && curl https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz | tar -xz
-RUN zip libjpeg_turbo_fuzzer_seed_corpus.zip afl-testcases/jpeg/full/images/* afl-testcases/jpeg_turbo/full/images/* $SRC/libjpeg-turbo/testimages/*
+RUN git clone --depth 1 https://github.com/libjpeg-turbo/seed-corpora
+RUN cd seed-corpora && zip -r ../decompress_fuzzer_seed_corpus.zip afl-testcases/jpeg* bugs/decompress* $SRC/libjpeg-turbo/testimages/*.jpg
+RUN cd seed-corpora && zip -r ../compress_fuzzer_seed_corpus.zip afl-testcases/bmp afl-testcases/gif* bugs/compress* $SRC/libjpeg-turbo/testimages/*.bmp $SRC/libjpeg-turbo/testimages/*.ppm
+RUN rm -rf seed-corpora
 
 WORKDIR libjpeg-turbo
-COPY build.sh libjpeg_turbo_fuzzer.cc $SRC/
+RUN cp fuzz/build.sh $SRC/
diff --git a/projects/libjpeg-turbo/build.sh b/projects/libjpeg-turbo/build.sh
deleted file mode 100755
index e500e20..0000000
--- a/projects/libjpeg-turbo/build.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash -eu
-# Copyright 2016 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-
-cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DENABLE_STATIC:bool=on
-make "-j$(nproc)"
-make install
-
-$CXX $CXXFLAGS -std=c++11 -I. \
-    $SRC/libjpeg_turbo_fuzzer.cc -o $OUT/libjpeg_turbo_fuzzer \
-    $LIB_FUZZING_ENGINE "$WORK/lib/libturbojpeg.a"
-
-cp $SRC/libjpeg_turbo_fuzzer_seed_corpus.zip $OUT/
diff --git a/projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc b/projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc
deleted file mode 100644
index 1b9ffd6..0000000
--- a/projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-# Copyright 2016 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-*/
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <memory>
-
-#include <turbojpeg.h>
-
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-    tjhandle jpegDecompressor = tjInitDecompress();
-
-    int width, height, subsamp, colorspace;
-    int res = tjDecompressHeader3(
-        jpegDecompressor, data, size, &width, &height, &subsamp, &colorspace);
-
-    // Bail out if decompressing the headers failed, the width or height is 0,
-    // or the image is too large (avoids slowing down too much). Cast to size_t to
-    // avoid overflows on the multiplication
-    if (res != 0 || width == 0 || height == 0 || ((size_t)width * height > (1024 * 1024))) {
-        tjDestroy(jpegDecompressor);
-        return 0;
-    }
-
-    const int buffer_size = width * height * 3;
-    std::unique_ptr<unsigned char[]> buf(new unsigned char[buffer_size]);
-    tjDecompress2(
-        jpegDecompressor, data, size, buf.get(), width, 0, height, TJPF_RGB, 0);
-
-    // For memory sanitizer, test each output byte
-    const unsigned char* raw_buf = buf.get();
-    int count = 0;
-    for( int i = 0; i < buffer_size; i++ )
-    {
-        if (raw_buf[i])
-        {
-            count ++;
-        }
-    }
-    if (count == buffer_size)
-    {
-        // Do something with side effect, so that all the above tests don't
-        // get removed by the optimizer.
-        free(malloc(1));
-    }
-
-    tjDestroy(jpegDecompressor);
-
-    return 0;
-}
diff --git a/projects/libjpeg-turbo/project.yaml b/projects/libjpeg-turbo/project.yaml
index 4ed2d55..88d56ec 100644
--- a/projects/libjpeg-turbo/project.yaml
+++ b/projects/libjpeg-turbo/project.yaml
@@ -1,5 +1,5 @@
-homepage: "https://github.com/libjpeg-turbo/libjpeg-turbo"
-language: c++
+homepage: "https://libjpeg-turbo.org"
+language: c
 primary_contact: "drc@virtualgl.org"
 vendor_ccs:
   - "aosmond@mozilla.com"
diff --git a/projects/libjxl/Dockerfile b/projects/libjxl/Dockerfile
new file mode 100644
index 0000000..0d52e88
--- /dev/null
+++ b/projects/libjxl/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y cmake ninja-build pkg-config
+RUN git clone --depth 1 https://github.com/libjxl/libjxl.git
+# We only need these sub-projects for the fuzzers.
+RUN git -C libjxl submodule update --init --recommend-shallow \
+  third_party/highway third_party/lodepng third_party/skcms third_party/brotli
+
+WORKDIR libjxl
+COPY build.sh $SRC/
diff --git a/projects/libjxl/build.sh b/projects/libjxl/build.sh
new file mode 100755
index 0000000..091c55a
--- /dev/null
+++ b/projects/libjxl/build.sh
@@ -0,0 +1,73 @@
+#!/bin/bash -eu
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+build_args=(
+  -G Ninja
+  -DBUILD_TESTING=OFF
+  -DJPEGXL_ENABLE_BENCHMARK=OFF
+  -DJPEGXL_ENABLE_DEVTOOLS=ON
+  -DJPEGXL_ENABLE_EXAMPLES=OFF
+  -DJPEGXL_ENABLE_FUZZERS=ON
+  -DJPEGXL_ENABLE_MANPAGES=OFF
+  -DJPEGXL_ENABLE_SJPEG=OFF
+  -DJPEGXL_ENABLE_VIEWERS=OFF
+  -DCMAKE_BUILD_TYPE=Release
+)
+
+# Build and generate a fuzzer corpus in release mode without instrumentation.
+# This is done in a subshell since we change the environment.
+(
+  unset CFLAGS
+  unset CXXFLAGS
+  export AFL_NOOPT=1
+
+  mkdir -p ${WORK}/libjxl-corpus
+  cd ${WORK}/libjxl-corpus
+  cmake "${build_args[@]}" "${SRC}/libjxl"
+  ninja clean
+  ninja fuzzer_corpus
+
+  # Generate a fuzzer corpus.
+  mkdir -p djxl_fuzzer_corpus
+  tools/fuzzer_corpus -q -r djxl_fuzzer_corpus
+  zip -q -j "${OUT}/djxl_fuzzer_seed_corpus.zip" djxl_fuzzer_corpus/*
+)
+
+# Build the fuzzers in release mode but force the inclusion of JXL_DASSERT()
+# checks.
+export CXXFLAGS="${CXXFLAGS} -DJXL_IS_DEBUG_BUILD=1"
+
+mkdir -p ${WORK}/libjxl-fuzzer
+cd ${WORK}/libjxl-fuzzer
+cmake \
+  "${build_args[@]}" \
+  -DJPEGXL_FUZZER_LINK_FLAGS="${LIB_FUZZING_ENGINE}" \
+  "${SRC}/libjxl"
+
+fuzzers=(
+  color_encoding_fuzzer
+  djxl_fuzzer
+  fields_fuzzer
+  icc_codec_fuzzer
+  rans_fuzzer
+)
+
+ninja clean
+ninja "${fuzzers[@]}"
+for fuzzer in "${fuzzers[@]}"; do
+  cp tools/${fuzzer} "${OUT}/"
+done
diff --git a/projects/libjxl/project.yaml b/projects/libjxl/project.yaml
new file mode 100644
index 0000000..d3707f0
--- /dev/null
+++ b/projects/libjxl/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://github.com/libjxl/libjxl"
+language: c++
+primary_contact: "libjxl-security@google.com"
+auto_ccs:
+  - "deymo@google.com"
+  - "veluca@google.com"
+sanitizers:
+  - address
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+  - undefined
+main_repo: 'https://github.com/libjxl/libjxl.git'
\ No newline at end of file
diff --git a/projects/libldac/project.yaml b/projects/libldac/project.yaml
index 189adf0..c850deb 100644
--- a/projects/libldac/project.yaml
+++ b/projects/libldac/project.yaml
@@ -7,10 +7,12 @@
   - bcreasey@google.com
   - hamzeh@google.com
   - geuteneier@google.com
-  - hollyhall@google.com
-  - mikelogan@google.com
   - maverickm@google.com
   - warrenwright@google.com
+  - ailport@google.com
+  - kimtony@google.com
+  - faerber@google.com
+  - greendonald@google.com
 fuzzing_engines:
   - libfuzzer
   - afl
diff --git a/projects/liblouis/Dockerfile b/projects/liblouis/Dockerfile
index 40a17c0..2d6649e 100644
--- a/projects/liblouis/Dockerfile
+++ b/projects/liblouis/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y make autoconf automake libtool \
-  pkg-config zlib1g-dev pciutils-dev libpci-dev
+  pkg-config zlib1g-dev libpci-dev
 RUN git clone --depth 1 https://github.com/liblouis/liblouis
 WORKDIR liblouis
 COPY build.sh $SRC/
diff --git a/projects/libmpeg2/project.yaml b/projects/libmpeg2/project.yaml
index a3ec5d4..e88f915 100644
--- a/projects/libmpeg2/project.yaml
+++ b/projects/libmpeg2/project.yaml
@@ -12,10 +12,12 @@
   - bcreasey@google.com
   - hamzeh@google.com
   - geuteneier@google.com
-  - hollyhall@google.com
-  - mikelogan@google.com
   - maverickm@google.com
   - warrenwright@google.com
+  - ailport@google.com
+  - kimtony@google.com
+  - faerber@google.com
+  - greendonald@google.com
 architectures:
   - x86_64
   - i386
diff --git a/projects/libpg_query/Dockerfile b/projects/libpg_query/Dockerfile
new file mode 100644
index 0000000..90f173b
--- /dev/null
+++ b/projects/libpg_query/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN git clone --depth 1 https://github.com/pganalyze/libpg_query libpg_query
+WORKDIR libpg_query
+COPY build.sh $SRC/
diff --git a/projects/libpg_query/build.sh b/projects/libpg_query/build.sh
new file mode 100755
index 0000000..0b5aa9f
--- /dev/null
+++ b/projects/libpg_query/build.sh
@@ -0,0 +1,19 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+make build
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./test/fuzz/fuzz_parser.c ./libpg_query.a -I./ -o $OUT/fuzz_parser
diff --git a/projects/libpg_query/project.yaml b/projects/libpg_query/project.yaml
new file mode 100644
index 0000000..11d7e74
--- /dev/null
+++ b/projects/libpg_query/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://pganalyze.com/"
+language: c
+primary_contact: "team@pganalyze.com"
+main_repo: "https://github.com/pganalyze/pg_query"
+auto_ccs: 
+  - "lukas@pganalyze.com"
+  - "david@adalogics.com"
diff --git a/projects/libphonenumber/Dockerfile b/projects/libphonenumber/Dockerfile
index c75d78c..85f278f 100644
--- a/projects/libphonenumber/Dockerfile
+++ b/projects/libphonenumber/Dockerfile
@@ -15,12 +15,27 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y autoconf automake libtool g++ cmake-curses-gui libgtest-dev libre2-dev libicu-dev libboost-dev libboost-thread-dev libboost-system-dev binutils ninja-build liblzma-dev libz-dev pkg-config wget openjdk-8-jdk
 
-WORKDIR $SRC/
+RUN apt-get update && apt-get install -y autoconf automake \
+      cmake cmake-curses-gui libre2-dev \
+      libicu-dev libboost-dev libboost-thread-dev libboost-system-dev \
+      libgflags-dev libgoogle-glog-dev libssl-dev \
+      protobuf-compiler libtool wget default-jre icu-devtools
+RUN apt-get install -y libgtest-dev && \
+    cd /usr/src/googletest/googletest && \
+		mkdir build && \
+		cd build && \
+		cmake .. && \
+		make && \
+		mkdir /usr/local/lib/googletest && \
+		ln -sn /usr/local/lib/googletest/libgtest.a /usr/lib/libgtest.a && \
+		ln -sn /usr/local/lib/googletest/libgtest_main.a /usr/lib/libgtest_main.a && \
+    rm /lib/x86_64-linux-gnu/libgtest.a && \
+    ln -sn /usr/local/lib/googletest/libgtest.a /lib/x86_64-linux-gnu/libgtest.a
+RUN wget https://github.com/unicode-org/icu/releases/download/release-66-rc/icu4c-66rc-src.tgz && \
+    tar xzvf icu4c-66rc-src.tgz
 RUN git clone https://github.com/google/libphonenumber
 
-RUN wget https://github.com/unicode-org/icu/releases/download/release-55-2/icu4c-55_2-src.tgz && tar xzvf icu4c-55_2-src.tgz
-
 COPY build.sh $SRC/
 COPY phonefuzz.cc $SRC/
+WORKDIR $SRC/
diff --git a/projects/libphonenumber/build.sh b/projects/libphonenumber/build.sh
index ec67ec6..768275e 100755
--- a/projects/libphonenumber/build.sh
+++ b/projects/libphonenumber/build.sh
@@ -68,20 +68,18 @@
 sed -i 's/list (APPEND CMAKE_C_FLAGS "-pthread")/string (APPEND CMAKE_C_FLAGS " -pthread")/g' CMakeLists.txt
 
 mkdir build && cd build
-cmake -DUSE_BOOST=OFF -DBUILD_GEOCODER=OFF -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
+cmake -DUSE_BOOST=OFF -DBUILD_GEOCODER=OFF \
+      -DPROTOBUF_LIB="/src/protobuf/src/.libs/libprotobuf.a" \
+      -DBUILD_STATIC_LIB=ON \
       -DICU_UC_INCLUDE_DIR=$SRC/icu/source/comon \
       -DICU_UC_LIB=$DEPS_PATH/lib/libicuuc.a \
       -DICU_I18N_INCLUDE_DIR=$SRC/icu/source/i18n/ \
-      -DICU_I18N_LIB=$DEPS_PATH/lib/libicui18n.a  ../
+      -DICU_I18N_LIB=$DEPS_PATH/lib/libicui18n.a  \
+      ../
 make
-cd ../
 
 # Build our fuzzer
-cp $SRC/*fuzz.cc .
-$CXX -I/src/libphonenumber/cpp/src $CXXFLAGS -o phonefuzz.o -c phonefuzz.cc
-
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE phonefuzz.o -o phonefuzz \
-     build/libphonenumber.a $SRC/protobuf/src/.libs/libprotobuf.a \
+$CXX -I$SRC/libphonenumber/cpp/src $CXXFLAGS -o phonefuzz.o -c $SRC/phonefuzz.cc
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE phonefuzz.o -o $OUT/phonefuzz \
+     ./libphonenumber.a $SRC/protobuf/src/.libs/libprotobuf.a \
      $DEPS_PATH/lib/libicu.a -lpthread
-
-cp phonefuzz $OUT/
diff --git a/projects/libpng/project.yaml b/projects/libpng/project.yaml
index 66b280b..1e9d786 100644
--- a/projects/libpng/project.yaml
+++ b/projects/libpng/project.yaml
@@ -7,6 +7,7 @@
   - "twsmith@mozilla.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/glennrp/libpng.git'
+main_repo: 'https://github.com/glennrp/libpng.git'
\ No newline at end of file
diff --git a/projects/libpsl/Dockerfile b/projects/libpsl/Dockerfile
index 303c5bb..89dd365 100644
--- a/projects/libpsl/Dockerfile
+++ b/projects/libpsl/Dockerfile
@@ -34,12 +34,8 @@
  python
 
 RUN git clone git://git.savannah.gnu.org/gnulib.git
-ENV GNULIB_TOOL=$SRC/gnulib/gnulib-tool
-ENV GNULIB_SRCDIR=$SRC/gnulib
-
 RUN git clone --depth=1 https://git.savannah.gnu.org/git/libunistring.git
-RUN git clone --depth=1 https://gitlab.com/libidn/libidn2.git && \
-    rmdir libidn2/gnulib && ln -s $SRC/gnulib libidn2/gnulib
+RUN git clone --depth=1 https://gitlab.com/libidn/libidn2.git
 RUN git clone --depth=1 https://git.savannah.gnu.org/git/libidn.git
 RUN wget https://github.com/unicode-org/icu/releases/download/release-59-2/icu4c-59_2-src.tgz && tar xvfz icu4c-59_2-src.tgz
 
diff --git a/projects/libpsl/build.sh b/projects/libpsl/build.sh
index 0dd93b5..8aba395 100755
--- a/projects/libpsl/build.sh
+++ b/projects/libpsl/build.sh
@@ -20,6 +20,9 @@
 export CPPFLAGS="-I$DEPS_PATH/include"
 export LDFLAGS="-L$DEPS_PATH/lib"
 export CONFIG_SITE=$SRC/config.site
+export GNULIB_SRCDIR=$SRC/gnulib
+export GNULIB_TOOL=$GNULIB_SRCDIR/gnulib-tool
+
 
 cd $SRC/icu/source
 UBSAN_OPTIONS=detect_leaks=0 \
@@ -30,29 +33,32 @@
   --disable-tests --disable-samples --with-data-packaging=static --prefix=$DEPS_PATH
 # ugly hack to avoid build error
 echo '#include <locale.h>' >>i18n/digitlst.h
-make -j$(nproc)
+
+# Hack so that upgrade to Ubuntu 20.04 works.
+ln -s /usr/include/locale.h /usr/include/xlocale.h
+
+make -j
 make install
 
 cd $SRC/libunistring
 ./autogen.sh
 ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \
   ./configure --enable-static --disable-shared --prefix=$DEPS_PATH
-make -j$(nproc)
+make -j
 make install
 
 cd $SRC/libidn
+./bootstrap
 ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \
-  make CFGFLAGS="--enable-static --disable-shared --disable-doc --prefix=$DEPS_PATH"
-make clean
-make -j1
-make -j$(nproc) check
+  ./configure --enable-static --disable-shared --disable-doc --prefix=$DEPS_PATH
+make -j
 make install
 
 cd $SRC/libidn2
 ./bootstrap
 ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \
   ./configure --enable-static --disable-shared --disable-doc --disable-gcc-warnings --prefix=$DEPS_PATH
-make -j$(nproc)
+make -j
 make install
 
 
@@ -82,8 +88,8 @@
   ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \
     ./configure --enable-static --disable-shared --disable-gtk-doc $BUILD_FLAGS --prefix=$DEPS_PATH
   make clean
-  make -j$(nproc)
-  make -j$(nproc) check
+  make -j
+  make -j check
   make -C fuzz oss-fuzz
   find fuzz -name '*_fuzzer' -exec cp -v '{}' $OUT ';'
 done
diff --git a/projects/libra/Dockerfile b/projects/libra/Dockerfile
index 426e547..cc541e3 100644
--- a/projects/libra/Dockerfile
+++ b/projects/libra/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 # google oss-fuzz stuff
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 # install other tools we might need
 RUN apt-get update && apt-get install -y cmake curl
diff --git a/projects/librawspeed/Dockerfile b/projects/librawspeed/Dockerfile
index 54bb66d..a480f15 100644
--- a/projects/librawspeed/Dockerfile
+++ b/projects/librawspeed/Dockerfile
@@ -18,7 +18,7 @@
 RUN apt-get update && \
     apt-get install -y apt-transport-https ca-certificates gnupg software-properties-common wget && \
     wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add - && \
-    apt-add-repository 'deb https://apt.kitware.com/ubuntu/ xenial main' && \
+    apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' && \
     apt-get update && apt-get install -y cmake make
 RUN git clone --depth 1 https://github.com/darktable-org/rawspeed.git librawspeed
 WORKDIR librawspeed
diff --git a/projects/libreoffice/Dockerfile b/projects/libreoffice/Dockerfile
index 6e8d211..e6eeb4c 100644
--- a/projects/libreoffice/Dockerfile
+++ b/projects/libreoffice/Dockerfile
@@ -20,156 +20,9 @@
 #build requirements
 RUN apt-get update && apt-get build-dep -y libreoffice
 RUN apt-get install -y wget yasm locales && locale-gen en_US.UTF-8
-#xenial gperf too old
-RUN sed -i -e 's/xenial/bionic/g' /etc/apt/sources.list
-RUN apt-get update && apt-get install gperf
 
-#cache build dependencies
-ADD https://dev-www.libreoffice.org/src/c74b7223abe75949b4af367942d96c7a-crosextrafonts-carlito-20130920.tar.gz \
-    https://dev-www.libreoffice.org/src/e7a384790b13c29113e22e596ade9687-LinLibertineG-20120116.zip \
-    https://dev-www.libreoffice.org/src/Amiri-0.111.zip \
-    https://dev-www.libreoffice.org/src/ReemKufi-0.7.zip \
-    https://dev-www.libreoffice.org/src/edc4d741888bc0d38e32dbaa17149596-source-sans-pro-2.010R-ro-1.065R-it.tar.gz \
-    https://dev-www.libreoffice.org/src/907d6e99f241876695c19ff3db0b8923-source-code-pro-2.030R-ro-1.050R-it.tar.gz \
-    https://dev-www.libreoffice.org/src/134d8262145fc793c6af494dcace3e71-liberation-fonts-ttf-1.07.4.tar.gz \
-    https://dev-www.libreoffice.org/src/1725634df4bb3dcb1b2c91a6175f8789-GentiumBasic_1102.zip \
-    https://dev-www.libreoffice.org/src/33e1e61fab06a547851ed308b4ffef42-dejavu-fonts-ttf-2.37.zip \
-    https://dev-www.libreoffice.org/src/368f114c078f94214a308a74c7e991bc-crosextrafonts-20130214.tar.gz \
-    https://dev-www.libreoffice.org/src/5c781723a0d9ed6188960defba8e91cf-liberation-fonts-ttf-2.00.1.tar.gz \
-    https://dev-www.libreoffice.org/extern/49a64f3bcf20a7909ba2751349231d6652ded9cd2840e961b5164d09de3ffa63-opens___.ttf \
-    https://dev-www.libreoffice.org/src/noto-fonts-20171024.tar.gz \
-    https://dev-www.libreoffice.org/src/amiri-0.109.zip \
-    https://dev-www.libreoffice.org/src/ttf-kacst_2.01+mry.tar.gz \
-    https://dev-www.libreoffice.org/src/ReemKufi-0.6.tar.gz \
-    https://dev-www.libreoffice.org/src/Scheherazade-2.100.zip \
-    https://dev-www.libreoffice.org/src/EmojiOneColor-SVGinOT-1.3.tar.gz \
-    https://dev-www.libreoffice.org/src/culmus-0.131.tar.gz \
-    https://dev-www.libreoffice.org/src/libre-hebrew-1.0.tar.gz \
-    https://dev-www.libreoffice.org/src/alef-1.001.tar.gz \
-    https://dev-www.libreoffice.org/src/a8c2c5b8f09e7ede322d5c602ff6a4b6-mythes-1.2.4.tar.gz \
-    https://dev-www.libreoffice.org/src/5ade6ae2a99bc1e9e57031ca88d36dad-hyphen-2.8.8.tar.gz \
-    https://dev-www.libreoffice.org/src/48d647fbd8ef8889e5a7f422c1bfda94-clucene-core-2.3.3.4.tar.gz \
-    https://dev-www.libreoffice.org/src/boost_1_66_0.tar.bz2 \
-    https://dev-www.libreoffice.org/src/expat-2.2.5.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libjpeg-turbo-1.5.2.tar.gz \
-    https://dev-www.libreoffice.org/src/lcms2-2.8.tar.gz \
-    https://dev-www.libreoffice.org/src/0168229624cfac409e766913506961a8-ucpp-1.3.2.tar.gz \
-    https://dev-www.libreoffice.org/src/libexttextcat-3.4.5.tar.xz \
-    https://dev-www.libreoffice.org/src/1f5def51ca0026cd192958ef07228b52-rasqal-0.9.33.tar.gz \
-    https://dev-www.libreoffice.org/src/a39f6c07ddb20d7dd2ff1f95fa21e2cd-raptor2-2.0.15.tar.gz \
-    https://dev-www.libreoffice.org/src/e5be03eda13ef68aabab6e42aa67715e-redland-1.0.17.tar.gz \
-    https://dev-www.libreoffice.org/src/cppunit-1.14.0.tar.gz \
-    https://dev-www.libreoffice.org/src/openldap-2.4.45.tgz \
-    https://dev-www.libreoffice.org/src/neon-0.30.2.tar.gz \
-    https://dev-www.libreoffice.org/src/e80ebae4da01e77f68744319f01d52a3-pixman-0.34.0.tar.gz \
-    https://dev-www.libreoffice.org/src/cairo-1.15.12.tar.xz \
-    https://dev-www.libreoffice.org/src/curl-7.60.0.tar.gz \
-    https://dev-www.libreoffice.org/src/xmlsec1-1.2.26.tar.gz \
-    https://dev-www.libreoffice.org/src/liblangtag-0.6.2.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libabw-0.1.2.tar.xz \
-    https://dev-www.libreoffice.org/src/libcdr-0.1.4.tar.xz \
-    https://dev-www.libreoffice.org/src/libcmis-0.5.1.tar.gz \
-    https://dev-www.libreoffice.org/src/libe-book-0.1.3.tar.xz \
-    https://dev-www.libreoffice.org/src/libetonyek-0.1.8.tar.xz \
-    https://dev-www.libreoffice.org/src/libfreehand-0.1.2.tar.xz \
-    https://dev-www.libreoffice.org/src/libmspub-0.1.4.tar.xz \
-    https://dev-www.libreoffice.org/src/libmwaw-0.3.14.tar.xz \
-    https://dev-www.libreoffice.org/src/libodfgen-0.1.6.tar.bz2 \
-    https://dev-www.libreoffice.org/src/liborcus-0.13.4.tar.gz \
-    https://dev-www.libreoffice.org/src/libpagemaker-0.0.4.tar.xz \
-    https://dev-www.libreoffice.org/src/libpng-1.6.34.tar.xz \
-    https://dev-www.libreoffice.org/src/librevenge-0.0.4.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libstaroffice-0.0.6.tar.xz \
-    https://dev-www.libreoffice.org/src/libvisio-0.1.6.tar.xz \
-    https://dev-www.libreoffice.org/src/libwpd-0.10.2.tar.xz \
-    https://dev-www.libreoffice.org/src/libwpg-0.3.2.tar.xz \
-    https://dev-www.libreoffice.org/src/libwps-0.4.10.tar.xz \
-    https://dev-www.libreoffice.org/src/libzmf-0.0.2.tar.xz \
-    https://dev-www.libreoffice.org/src/zlib-1.2.11.tar.xz \
-    https://dev-www.libreoffice.org/src/poppler-0.66.0.tar.xz \
-    https://dev-www.libreoffice.org/src/mdds-1.3.1.tar.bz2 \
-    https://dev-www.libreoffice.org/src/openssl-1.0.2o.tar.gz \
-    https://dev-www.libreoffice.org/src/language-subtag-registry-2018-04-23.tar.bz2 \
-    https://dev-www.libreoffice.org/src/graphite2-minimal-1.3.10.tgz \
-    https://dev-www.libreoffice.org/src/harfbuzz-1.8.4.tar.bz2 \
-    https://dev-www.libreoffice.org/src/bae83fa5dc7f081768daace6e199adc3-glm-0.9.4.6-libreoffice.zip \
-    https://dev-www.libreoffice.org/src/icu4c-62_1-src.tgz \
-    https://dev-www.libreoffice.org/src/icu4c-62_1-data.zip \
-    https://dev-www.libreoffice.org/src/libxml2-2.9.8.tar.gz \
-    https://dev-www.libreoffice.org/src/libxslt-1.1.32.tar.gz \
-    https://dev-www.libreoffice.org/src/hunspell-1.6.2.tar.gz \
-    https://dev-www.libreoffice.org/src/lxml-4.1.1.tgz \
-    https://dev-www.libreoffice.org/src/freetype-2.8.1.tar.bz2 \
-    https://dev-www.libreoffice.org/src/fontconfig-2.12.6.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libepoxy-1.3.1.tar.bz2 \
-    https://dev-www.libreoffice.org/src/gpgme-1.9.0.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libassuan-2.5.1.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libgpg-error-1.27.tar.bz2 \
-    https://dev-www.libreoffice.org/src/libepubgen-0.1.1.tar.xz \
-    https://dev-www.libreoffice.org/src/libnumbertext-1.0.4.tar.xz \
-    https://dev-www.libreoffice.org/src/libqxp-0.0.1.tar.xz \
-    https://dev-www.libreoffice.org/src/a233181e03d3c307668b4c722d881661-mariadb_client-2.0.0-src.tar.gz $SRC/
-#fuzzing dictionaries
-ADD https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/gif.dict \
-    https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/jpeg.dict \
-    https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/png.dict \
-    https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/tiff.dict \
-    https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/xml.dict \
-    https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/html_tags.dict $SRC/
-#fuzzing corpuses
-ADD https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz $SRC/
-RUN mkdir afl-testcases && cd afl-testcases/ && tar xf $SRC/afl_testcases.tgz && cd .. && \
-    zip -q $SRC/jpgfuzzer_seed_corpus.zip afl-testcases/jpeg*/full/images/* && \
-    zip -q $SRC/giffuzzer_seed_corpus.zip afl-testcases/gif*/full/images/* && \
-    zip -q $SRC/bmpfuzzer_seed_corpus.zip afl-testcases/bmp*/full/images/* && \
-    zip -q $SRC/pngfuzzer_seed_corpus.zip afl-testcases/png*/full/images/*
-RUN svn export https://github.com/khaledhosny/ots/trunk/tests/fonts $SRC/sample-sft-fonts/ots
-RUN svn export https://github.com/unicode-org/text-rendering-tests/trunk/fonts/ $SRC/sample-sft-fonts/unicode-org
-RUN svn export https://github.com/harfbuzz/harfbuzz/trunk/test/shaping/data/in-house/fonts $SRC/sample-sft-fonts/harfbuzz
-ADD https://github.com/adobe-fonts/adobe-variable-font-prototype/releases/download/1.001/AdobeVFPrototype.otf $SRC/sample-sft-fonts/adobe
-RUN zip -qr $SRC/sftfuzzer_seed_corpus.zip $SRC/sample-sft-fonts
-ADD https://dev-www.libreoffice.org/corpus/wmffuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/xbmfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/xpmfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/svmfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/pcdfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/dxffuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/metfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/ppmfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/psdfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/epsfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/pctfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/pcxfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/rasfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/tgafuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/tiffuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/hwpfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/602fuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/lwpfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/pptfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/rtffuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/olefuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/cgmfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/ww2fuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/ww6fuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/ww8fuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/qpwfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/slkfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/fodtfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/fodsfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/fodgfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/fodpfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/xlsfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/scrtffuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/wksfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/diffuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/docxfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/xlsxfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/pptxfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/mmlfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/mtpfuzzer_seed_corpus.zip \
-    https://dev-www.libreoffice.org/corpus/htmlfuzzer_seed_corpus.zip $SRC/
 #clone source
-RUN git clone --depth 1 git://anongit.freedesktop.org/libreoffice/core libreoffice
+RUN git clone --depth 1 https://git.libreoffice.org/core libreoffice
 WORKDIR libreoffice
+RUN ./bin/oss-fuzz-setup.sh
 COPY build.sh $SRC/
diff --git a/projects/libreoffice/project.yaml b/projects/libreoffice/project.yaml
index bcf9a4f..43542a9 100644
--- a/projects/libreoffice/project.yaml
+++ b/projects/libreoffice/project.yaml
@@ -1,6 +1,16 @@
 homepage: "https://www.libreoffice.org/"
 language: c++
 primary_contact: "caolanm@redhat.com"
+sanitizers:
+  - address
+  - memory:
+     experimental: True
+  - undefined
+fuzzing_engines:
+  # see https://github.com/google/oss-fuzz/issues/6233 for missing afl
+  - libfuzzer
+  - honggfuzz
+builds_per_day: 2
 auto_ccs:
   - "officesecurity@lists.freedesktop.org"
   - "damjan.jov@gmail.com"
diff --git a/projects/libressl/Dockerfile b/projects/libressl/Dockerfile
index 964569a..3861c85 100644
--- a/projects/libressl/Dockerfile
+++ b/projects/libressl/Dockerfile
@@ -20,7 +20,7 @@
 RUN git clone --depth 1 https://github.com/libressl-portable/fuzz.git libressl.fuzzers
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
 WORKDIR libressl
 RUN ./update.sh
 COPY build.sh *.options $SRC/
diff --git a/projects/libressl/build.sh b/projects/libressl/build.sh
index 48cf959..5c639e6 100755
--- a/projects/libressl/build.sh
+++ b/projects/libressl/build.sh
@@ -24,9 +24,6 @@
 CFLAGS="" CXXFLAGS="" ./b2 headers
 cp -R boost/ /usr/include/
 
-# Prevent Boost compilation error with -std=c++17
-export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR"
-
 mkdir -p $WORK/libressl
 cd $WORK/libressl
 
diff --git a/projects/libsass/project.yaml b/projects/libsass/project.yaml
index 7c1c2f3..fb5521b 100644
--- a/projects/libsass/project.yaml
+++ b/projects/libsass/project.yaml
@@ -4,10 +4,11 @@
 
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 
 labels:
   data_context_fuzzer:
     - sundew
-main_repo: 'https://github.com/sass/libsass.git'
+main_repo: 'https://github.com/sass/libsass.git'
\ No newline at end of file
diff --git a/projects/libspectre/project.yaml b/projects/libspectre/project.yaml
index d988232..8509ec6 100755
--- a/projects/libspectre/project.yaml
+++ b/projects/libspectre/project.yaml
@@ -7,10 +7,8 @@
   - libfuzzer
   - afl
   - honggfuzz
-  - dataflow
 sanitizers:
   - address
   - undefined
   - memory
-  - dataflow
 main_repo: 'https://gitlab.freedesktop.org/libspectre/libspectre.git'
diff --git a/projects/libssh/project.yaml b/projects/libssh/project.yaml
index 5c64321..7cb24c4 100644
--- a/projects/libssh/project.yaml
+++ b/projects/libssh/project.yaml
@@ -7,6 +7,7 @@
  - "anderson.sasaki@gmail.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://git.libssh.org/projects/libssh.git'
+main_repo: 'https://git.libssh.org/projects/libssh.git'
\ No newline at end of file
diff --git a/projects/libssh2/build.sh b/projects/libssh2/build.sh
index decc467..26bb490 100755
--- a/projects/libssh2/build.sh
+++ b/projects/libssh2/build.sh
@@ -15,5 +15,6 @@
 #
 ################################################################################
 
+apt-get update
 # Run the OSS-Fuzz script in the project.
 ./tests/ossfuzz/ossfuzz.sh
diff --git a/projects/libtasn1/project.yaml b/projects/libtasn1/project.yaml
index 9380ae9..3490c8f 100644
--- a/projects/libtasn1/project.yaml
+++ b/projects/libtasn1/project.yaml
@@ -10,10 +10,8 @@
   - afl
   - libfuzzer
   - honggfuzz
-  - dataflow
 sanitizers:
   - address
   - memory
   - undefined
-  - dataflow
 main_repo: 'https://gitlab.com/gnutls/libtasn1.git'
diff --git a/projects/libtiff/project.yaml b/projects/libtiff/project.yaml
index 6c7666b..000f910 100644
--- a/projects/libtiff/project.yaml
+++ b/projects/libtiff/project.yaml
@@ -5,9 +5,10 @@
   - paul.l.kehrer@gmail.com
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 architectures:
   - x86_64
   - i386
-main_repo: 'https://gitlab.com/libtiff/libtiff'
+main_repo: 'https://gitlab.com/libtiff/libtiff'
\ No newline at end of file
diff --git a/projects/libtpms/Dockerfile b/projects/libtpms/Dockerfile
index 50496fe..2f18000 100644
--- a/projects/libtpms/Dockerfile
+++ b/projects/libtpms/Dockerfile
@@ -19,8 +19,8 @@
         apt-get update && \
         apt-get install -y \
         make autoconf automake libtool \
-        libstdc++-5-dev \
-        libssl-dev libseccomp-dev
+        libstdc++-9-dev \
+        libssl-dev libseccomp-dev pkg-config
 RUN git clone --depth 1 https://github.com/stefanberger/libtpms libtpms
 WORKDIR libtpms
 COPY build.sh $SRC/
diff --git a/projects/libusb/libusb_fuzzer.cc b/projects/libusb/libusb_fuzzer.cc
index 8e543a7..ad64321 100644
--- a/projects/libusb/libusb_fuzzer.cc
+++ b/projects/libusb/libusb_fuzzer.cc
@@ -21,29 +21,31 @@
 #include "libusb/libusbi.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  struct libusb_transfer *transfer;
+  struct libusb_transfer *transfer = NULL;
   FuzzedDataProvider stream(data, size);
   uint8_t bmRequestType = stream.ConsumeIntegral<uint8_t>();
   uint8_t bRequest = stream.ConsumeIntegral<uint8_t>();
   uint16_t wValue = stream.ConsumeIntegral<uint16_t>();
   uint16_t wIndex = stream.ConsumeIntegral<uint16_t>();
   uint16_t wLength = stream.ConsumeIntegral<uint16_t>();
-  std::vector<char> data_ = stream.ConsumeRemainingBytes<char>();
-  unsigned char* buffer = reinterpret_cast<unsigned char*>(data_.data());
+  std::string input = stream.ConsumeRandomLengthString();
+  const char *d = input.c_str();
 
   transfer = libusb_alloc_transfer(0);
   if (!transfer) {
     return LIBUSB_ERROR_NO_MEM;
   }
 
-  if (!buffer) {
-    libusb_free_transfer(transfer);
-    return LIBUSB_ERROR_NO_MEM;
-  }
+  libusb_fill_control_setup((unsigned char *)d, bmRequestType, bRequest, wValue, wIndex, wLength);
 
-  libusb_fill_control_setup(
-    buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
+  // Cleanup. 
+  // We cannot call libusb_free_transfer as no callbacks has occurred. Calling
+  // libusb_free_transfer without this will trigger false positive errors.
+  struct usbi_transfer *itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+  usbi_mutex_destroy(&itransfer->lock);
+  size_t priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
+  unsigned char *ptr = (unsigned char *)itransfer - priv_size;
+  free(ptr);
 
-  libusb_free_transfer(transfer);
   return 0;
 }
diff --git a/projects/libvips/Dockerfile b/projects/libvips/Dockerfile
index e792dff..378e600 100644
--- a/projects/libvips/Dockerfile
+++ b/projects/libvips/Dockerfile
@@ -16,29 +16,39 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y \
-  curl \
   automake \
+  autopoint \
   cmake \
-  nasm \
-  gtk-doc-tools \
+  curl \
+  gettext \
+  glib2.0-dev \
   gobject-introspection \
-  libfftw3-dev \
+  gtk-doc-tools \
+  libbrotli-dev \
   libexpat1-dev \
   libffi-dev \
+  libfftw3-dev \
   libselinux1-dev \
-  glib2.0-dev
+  libtool \
+  nasm \
+  python3-pip
+RUN pip3 install meson ninja
 RUN mkdir afl-testcases
 RUN curl https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz | tar xzC afl-testcases
 RUN git clone --depth 1 https://github.com/libvips/libvips
 RUN git clone --depth 1 https://github.com/madler/zlib.git
 RUN git clone --depth 1 https://github.com/libexif/libexif
+RUN git clone --depth 1 https://github.com/mm2/Little-CMS.git lcms
 RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo
 RUN git clone --depth 1 https://github.com/glennrp/libpng.git
-RUN git clone --depth 1 https://git.code.sf.net/p/giflib/code libgif
+RUN git clone --depth 1 https://github.com/randy408/libspng.git
 RUN git clone --depth 1 https://chromium.googlesource.com/webm/libwebp
-RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff 
+RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff
 RUN git clone --depth 1 https://aomedia.googlesource.com/aom
 RUN git clone --depth 1 https://github.com/strukturag/libheif
+RUN git clone --depth 1 --recursive https://github.com/libjxl/libjxl.git
+RUN git clone --depth 1 https://github.com/lovell/libimagequant.git
+RUN git clone --depth 1 https://github.com/dloebl/cgif.git
 
 WORKDIR libvips
 COPY build.sh $SRC/
diff --git a/projects/libvips/build.sh b/projects/libvips/build.sh
index 21505d6..17b4968 100755
--- a/projects/libvips/build.sh
+++ b/projects/libvips/build.sh
@@ -29,7 +29,8 @@
 pushd $SRC/libexif
 autoreconf -fi
 ./configure \
-  --enable-shared=no \
+  --enable-static \
+  --disable-shared \
   --disable-docs \
   --disable-dependency-tracking \
   --prefix=$WORK
@@ -37,6 +38,18 @@
 make install
 popd
 
+# lcms
+pushd $SRC/lcms
+./autogen.sh
+./configure \
+  --enable-static \
+  --disable-shared \
+  --disable-dependency-tracking \
+  --prefix=$WORK
+make -j$(nproc)
+make install
+popd
+
 # aom
 pushd $SRC/aom
 mkdir -p build/linux
@@ -45,7 +58,7 @@
   -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX \
   -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
   -DCMAKE_INSTALL_PREFIX=$WORK -DCMAKE_INSTALL_LIBDIR=lib \
-  -DENABLE_SHARED:bool=off -DCONFIG_PIC=1 \
+  -DENABLE_SHARED=FALSE -DCONFIG_PIC=1 \
   -DENABLE_EXAMPLES=0 -DENABLE_DOCS=0 -DENABLE_TESTS=0 \
   -DCONFIG_SIZE_LIMIT=1 \
   -DDECODE_HEIGHT_LIMIT=12288 -DDECODE_WIDTH_LIMIT=12288 \
@@ -66,7 +79,8 @@
   --enable-static \
   --disable-examples \
   --disable-go \
-  --prefix=$WORK
+  --prefix=$WORK \
+  CPPFLAGS=-I$WORK/include
 make clean
 make -j$(nproc)
 make install
@@ -74,14 +88,14 @@
 
 # libjpeg-turbo
 pushd $SRC/libjpeg-turbo
-cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DENABLE_STATIC:bool=on
+cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DENABLE_STATIC=TRUE -DENABLE_SHARED=FALSE -DWITH_TURBOJPEG=FALSE
 make -j$(nproc)
 make install
 popd
 
 # libpng
 pushd $SRC/libpng
-sed -ie "s/option WARNING /option WARNING disabled/" scripts/pnglibconf.dfa
+sed -ie "s/option WARNING /& disabled/" scripts/pnglibconf.dfa
 autoreconf -fi
 ./configure \
   --prefix=$WORK \
@@ -91,9 +105,13 @@
 make install
 popd
 
-# libgif
-pushd $SRC/libgif
-make libgif.a libgif.so install-include install-lib OFLAGS="-O2" PREFIX=$WORK
+# libspng
+pushd $SRC/libspng
+cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DSPNG_STATIC=TRUE -DSPNG_SHARED=FALSE -DZLIB_ROOT=$WORK
+make -j$(nproc)
+make install
+# Fix pkg-config file of libspng
+sed -i'.bak' "s/-lspng/&_static/" $WORK/lib/pkgconfig/libspng.pc
 popd
 
 # libwebp
@@ -127,9 +145,59 @@
 make install
 popd
 
+# jpeg-xl (libjxl)
+pushd $SRC/libjxl
+sed -i'.bak' "/add_subdirectory(tools)/d" CMakeLists.txt
+# Don't overwrite our linker flags
+sed -i'.bak' "/set(CMAKE_EXE_LINKER_FLAGS/{N;d;}" CMakeLists.txt
+cmake -G "Unix Makefiles" \
+  -DCMAKE_BUILD_TYPE=Release \
+  -DCMAKE_C_COMPILER=$CC \
+  -DCMAKE_CXX_COMPILER=$CXX \
+  -DCMAKE_C_FLAGS="$CFLAGS" \
+  -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
+  -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS" \
+  -DCMAKE_MODULE_LINKER_FLAGS="$LDFLAGS" \
+  -DCMAKE_INSTALL_PREFIX="$WORK" \
+  -DCMAKE_THREAD_LIBS_INIT="-lpthread" \
+  -DCMAKE_USE_PTHREADS_INIT=1 \
+  -DBUILD_SHARED_LIBS=0 \
+  -DBUILD_TESTING=0 \
+  -DJPEGXL_STATIC=1 \
+  -DJPEGXL_FORCE_SYSTEM_BROTLI=1 \
+  -DJPEGXL_ENABLE_FUZZERS=0 \
+  -DJPEGXL_ENABLE_MANPAGES=0 \
+  -DJPEGXL_ENABLE_BENCHMARK=0 \
+  -DJPEGXL_ENABLE_EXAMPLES=0 \
+  -DJPEGXL_ENABLE_SKCMS=0 \
+  -DJPEGXL_ENABLE_SJPEG=0 \
+  .
+make -j$(nproc)
+make install
+popd
+
+# libimagequant
+pushd $SRC/libimagequant
+meson setup --prefix=$WORK --libdir=lib --default-library=static build
+cd build
+ninja -j$(nproc)
+ninja install
+popd
+
+# cgif
+pushd $SRC/cgif
+meson setup --prefix=$WORK --libdir=lib --default-library=static build
+cd build
+ninja -j$(nproc)
+ninja install
+popd
+
 # libvips
-./autogen.sh \
+sed -i'.bak' "/test/d" Makefile.am
+sed -i'.bak' "/tools/d" Makefile.am
+PKG_CONFIG="pkg-config --static" ./autogen.sh \
   --disable-shared \
+  --disable-modules \
   --disable-gtk-doc \
   --disable-gtk-doc-html \
   --disable-dependency-tracking \
@@ -156,20 +224,27 @@
     -I/usr/lib/x86_64-linux-gnu/glib-2.0/include \
     $WORK/lib/libvips.a \
     $WORK/lib/libexif.a \
-    $WORK/lib/libturbojpeg.a \
+    $WORK/lib/liblcms2.a \
+    $WORK/lib/libjpeg.a \
     $WORK/lib/libpng.a \
+    $WORK/lib/libspng_static.a \
     $WORK/lib/libz.a \
-    $WORK/lib/libgif.a \
     $WORK/lib/libwebpmux.a \
     $WORK/lib/libwebpdemux.a \
     $WORK/lib/libwebp.a \
     $WORK/lib/libtiff.a \
     $WORK/lib/libheif.a \
     $WORK/lib/libaom.a \
+    $WORK/lib/libjxl.a \
+    $WORK/lib/libjxl_threads.a \
+    $WORK/lib/libhwy.a \
+    $WORK/lib/libimagequant.a \
+    $WORK/lib/libcgif.a \
     $LIB_FUZZING_ENGINE \
     -Wl,-Bstatic \
-    -lfftw3 -lgmodule-2.0 -lgio-2.0 -lgobject-2.0 -lffi -lglib-2.0 -lpcre -lexpat \
-    -lresolv -lsepol -lselinux \
+    -lfftw3 -lexpat -lbrotlienc -lbrotlidec -lbrotlicommon \
+    -lgmodule-2.0 -lgio-2.0 -lgobject-2.0 -lffi -lglib-2.0 \
+    -lresolv -lmount -lblkid -lselinux -lsepol -lpcre \
     -Wl,-Bdynamic -pthread
   ln -sf "seed_corpus.zip" "$OUT/${target}_seed_corpus.zip"
 done
diff --git a/projects/libvips/project.yaml b/projects/libvips/project.yaml
index d4b27f8..a00ccab 100644
--- a/projects/libvips/project.yaml
+++ b/projects/libvips/project.yaml
@@ -2,7 +2,6 @@
 language: c++
 primary_contact: "jcupitt@gmail.com"
 auto_ccs:
-  - "oscar.mira@adevinta.com"
   - "kleisauke@gmail.com"
   - "lovell.fuller@gmail.com"
 main_repo: 'https://github.com/libvips/libvips'
diff --git a/projects/libxml2/project.yaml b/projects/libxml2/project.yaml
index 873e81e..3b6abb9 100644
--- a/projects/libxml2/project.yaml
+++ b/projects/libxml2/project.yaml
@@ -1,6 +1,5 @@
 homepage: "http://www.xmlsoft.org/"
 language: c++
-primary_contact: "wellnhofer@aevum.de"
 vendor_ccs:
   - "akilsrin@apple.com"
   - "ddkilzer@apple.com"
diff --git a/projects/libxslt/project.yaml b/projects/libxslt/project.yaml
index 09fc830..69e37c7 100644
--- a/projects/libxslt/project.yaml
+++ b/projects/libxslt/project.yaml
@@ -1,6 +1,5 @@
 homepage: "http://www.xmlsoft.org/libxslt/"
 language: c++
-primary_contact: "wellnhofer@aevum.de"
 vendor_ccs:
   - "ddkilzer@apple.com"
   - "schenney@chromium.org"
diff --git a/projects/libyal/Dockerfile b/projects/libyal/Dockerfile
index c255806..3a2f067 100644
--- a/projects/libyal/Dockerfile
+++ b/projects/libyal/Dockerfile
@@ -21,6 +21,7 @@
 RUN git clone --depth 1 https://github.com/libyal/libfplist.git libfplist
 RUN git clone --depth 1 https://github.com/libyal/libftxf.git libftxf
 RUN git clone --depth 1 https://github.com/libyal/libfusn.git libfusn
+RUN git clone --depth 1 https://github.com/libyal/libfwevt.git libfwevt
 RUN git clone --depth 1 https://github.com/libyal/libfwnt.git libfwnt
 RUN git clone --depth 1 https://github.com/libyal/libfwps.git libfwps
 RUN git clone --depth 1 https://github.com/libyal/libfwsi.git libfwsi
@@ -49,11 +50,13 @@
 RUN git clone --depth 1 https://github.com/libyal/libbde.git libbde
 RUN git clone --depth 1 https://github.com/libyal/libluksde.git libluksde
 RUN git clone --depth 1 https://github.com/libyal/libvsgpt.git libvsgpt
+RUN git clone --depth 1 https://github.com/libyal/libvshadow.git libvshadow
 RUN git clone --depth 1 https://github.com/libyal/libvslvm.git libvslvm
 RUN git clone --depth 1 https://github.com/libyal/libvsmbr.git libvsmbr
 
 RUN git clone --depth 1 https://github.com/libyal/libewf.git libewf
 RUN git clone --depth 1 https://github.com/libyal/libmodi.git libmodi
+RUN git clone --depth 1 https://github.com/libyal/libodraw.git libodraw
 RUN git clone --depth 1 https://github.com/libyal/libqcow.git libqcow
 RUN git clone --depth 1 https://github.com/libyal/libsmraw.git libsmraw
 RUN git clone --depth 1 https://github.com/libyal/libvhdi.git libvhdi
diff --git a/projects/libyang/build.sh b/projects/libyang/build.sh
index cb5857d..9e15632 100755
--- a/projects/libyang/build.sh
+++ b/projects/libyang/build.sh
@@ -16,7 +16,7 @@
 ################################################################################
 
 cd libyang
-git checkout libyang2
+git checkout devel
 
 sed -i 's/add_subdirectory/#add_subdirectory/g' ./tools/CMakeLists.txt
 mkdir build && cd build
diff --git a/projects/libzip/project.yaml b/projects/libzip/project.yaml
index 2743d39..916b01a 100644
--- a/projects/libzip/project.yaml
+++ b/projects/libzip/project.yaml
@@ -6,5 +6,6 @@
 sanitizers:
   - address
   - undefined
-  - memory
-main_repo: 'https://github.com/nih-at/libzip.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: 'https://github.com/nih-at/libzip.git'
\ No newline at end of file
diff --git a/projects/lighttpd/build.sh b/projects/lighttpd/build.sh
index 5cd286a..33ef7db 100755
--- a/projects/lighttpd/build.sh
+++ b/projects/lighttpd/build.sh
@@ -20,4 +20,4 @@
 make
 cd src
 $CC $CFLAGS -c $SRC/fuzz_burl.c -I. -I../include
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_burl.o burl.o buffer.o base64.o -o $OUT/fuzz_burl
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_burl.o burl.o buffer.o base64.o ck.o -o $OUT/fuzz_burl
diff --git a/projects/linkerd2-proxy/Dockerfile b/projects/linkerd2-proxy/Dockerfile
new file mode 100644
index 0000000..1abb1d4
--- /dev/null
+++ b/projects/linkerd2-proxy/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+RUN git clone --depth 1 https://github.com/linkerd/linkerd2-proxy
+
+COPY build.sh $SRC/
+WORKDIR $SRC
diff --git a/projects/linkerd2-proxy/build.sh b/projects/linkerd2-proxy/build.sh
new file mode 100755
index 0000000..81044bc
--- /dev/null
+++ b/projects/linkerd2-proxy/build.sh
@@ -0,0 +1,48 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+TARGET_PATH="./fuzz/target/x86_64-unknown-linux-gnu/release"
+BASE="$SRC/linkerd2-proxy/linkerd"
+BUILD_FUZZER="cargo +nightly fuzz build "
+
+cd ${BASE}/app/inbound
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_inbound
+
+cd ${BASE}/addr/
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_addr
+
+cd ${BASE}/dns
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_dns
+
+cd ${BASE}/proxy/http
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_http
+
+cd ${BASE}/tls
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_tls
+
+cd ${BASE}/transport-header
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_raw $OUT/fuzz_transport_raw
+cp ${TARGET_PATH}/fuzz_target_structured $OUT/fuzz_transport_structured
+
+echo "[libfuzzer]" > $OUT/fuzz_transport_raw.options
+echo "detect_leaks=0" >> $OUT/fuzz_transport_raw.options
diff --git a/projects/linkerd2-proxy/project.yaml b/projects/linkerd2-proxy/project.yaml
new file mode 100644
index 0000000..c7ce398
--- /dev/null
+++ b/projects/linkerd2-proxy/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://linkerd.io/"
+main_repo: "https://github.com/linkerd/linkerd2-proxy"
+primary_contact: "ver@buoyant.io"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "eliza@buoyant.io"
+  - "kevinl@buoyant.io"
+  - "david@adalogics.com"
diff --git a/projects/lldb-eval/Dockerfile b/projects/lldb-eval/Dockerfile
new file mode 100644
index 0000000..dc61ec3
--- /dev/null
+++ b/projects/lldb-eval/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN apt-get update \
+    && apt-get install -y wget git patchelf zlib1g-dev python libtinfo-dev --no-install-recommends
+
+RUN git clone --depth 1 https://github.com/google/lldb-eval
+
+COPY build.sh $SRC/
+COPY lldb_vs_lldb_eval_libfuzzer_test.options $SRC/
+
+WORKDIR $SRC/lldb-eval
diff --git a/projects/lldb-eval/build.sh b/projects/lldb-eval/build.sh
new file mode 100644
index 0000000..dee5c7c
--- /dev/null
+++ b/projects/lldb-eval/build.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+(
+cd $SRC/
+GITHUB_RELEASE="https://github.com/google/lldb-eval/releases/download/oss-fuzz-ubuntu-20.04"
+
+if [ "$SANITIZER" = "address" ]
+then
+  LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release-address.tar.gz"
+elif [ "$SANITIZER" = "memory" ]
+then
+  LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release-memory.tar.gz"
+elif [ "$SANITIZER" = "undefined" ]
+then
+  LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release.tar.gz"
+elif [ "$SANITIZER" = "coverage" ]
+then
+  # For coverage we also need the original source code.
+  wget --quiet $GITHUB_RELEASE/llvm-12.0.1-source.tar.gz
+  tar -xzf llvm-12.0.1-source.tar.gz
+  wget --quiet $GITHUB_RELEASE/llvm-12.0.1-x86_64-linux-release-genfiles.tar.gz
+  tar -xzf llvm-12.0.1-x86_64-linux-release-genfiles.tar.gz
+
+  LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release.tar.gz"
+else
+  echo "Unknown sanitizer: $SANITIZER"
+  exit 1
+fi
+
+wget --quiet $GITHUB_RELEASE/$LLVM_ARCHIVE
+mkdir -p llvm && tar -xzf $LLVM_ARCHIVE --strip-components 1 -C llvm
+)
+export LLVM_INSTALL_PATH=$SRC/llvm
+
+if [ "$SANITIZER" = "undefined" ]
+then
+  # Disable vptr because it's not allowed with '-fno-rtti'
+  CFLAGS="$CFLAGS -fno-sanitize=function,vptr"
+  CXXFLAGS="$CXXFLAGS -fno-sanitize=function,vptr"
+fi
+
+# Undefine NDEBUG to enable asserts.
+export BAZEL_EXTRA_BUILD_FLAGS="--copt=-UNDEBUG"
+
+# Run the build!
+bazel_build_fuzz_tests
+
+# OSS-Fuzz rule doesn't build data dependencies
+bazel build //testdata:fuzzer_binary_gen
+
+# OSS-Fuzz rule doesn't handle dynamic dependencies
+# Copy liblldb.so
+mkdir -p $OUT/lib
+cp $SRC/llvm/lib/liblldb.so* $OUT/lib
+
+# List of targets to fuzz.
+TARGETS=(
+  lldb_eval_libfuzzer_test
+  lldb_vs_lldb_eval_libfuzzer_test
+)
+
+# Preparation of each target.
+for target in ${TARGETS[@]}; do
+  # OSS-Fuzz rule doesn't package runfiles yet:
+  # https://github.com/bazelbuild/rules_fuzzing/issues/100
+  mkdir -p $OUT/$target.runfiles
+  # fuzzer_binary
+  mkdir -p $OUT/$target.runfiles/lldb_eval/testdata
+  cp $SRC/lldb-eval/bazel-bin/testdata/fuzzer_binary $OUT/$target.runfiles/lldb_eval/testdata/
+  cp $SRC/lldb-eval/testdata/fuzzer_binary.cc $OUT/$target.runfiles/lldb_eval/testdata/
+  # lldb-server
+  mkdir -p $OUT/$target.runfiles/llvm_project/bin
+  cp $SRC/llvm/bin/lldb-server $OUT/$target.runfiles/llvm_project/bin/lldb-server
+  # Patch RPATH of the fuzz target
+  patchelf --set-rpath '$ORIGIN/lib' $OUT/$target
+done
+
+cp $SRC/lldb_vs_lldb_eval_libfuzzer_test.options $OUT/
diff --git a/projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options b/projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options
new file mode 100644
index 0000000..f9d0965
--- /dev/null
+++ b/projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+detect_leaks=0
diff --git a/projects/lldb-eval/project.yaml b/projects/lldb-eval/project.yaml
new file mode 100644
index 0000000..8568e75
--- /dev/null
+++ b/projects/lldb-eval/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/google/lldb-eval"
+main_repo: "https://github.com/google/lldb-eval"
+language: c++
+primary_contact: "werat@google.com"
+auto_ccs:
+  - "tsabolcec@google.com"
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+  - undefined
diff --git a/projects/llhttp/Dockerfile b/projects/llhttp/Dockerfile
new file mode 100644
index 0000000..c7ab958
--- /dev/null
+++ b/projects/llhttp/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool
+RUN curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
+RUN bash nodesource_setup.sh
+RUN apt install -y nodejs
+RUN git clone --depth 1 https://github.com/nodejs/llhttp llhttp
+WORKDIR llhttp
+COPY build.sh $SRC/
diff --git a/projects/llhttp/build.sh b/projects/llhttp/build.sh
new file mode 100755
index 0000000..a9a3a48
--- /dev/null
+++ b/projects/llhttp/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+npm install -g typescript
+npm link typescript
+npm install .
+make
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./test/fuzzers/fuzz_parser.c -I./build/ ./build/libllhttp.a -o $OUT/fuzz_parser
diff --git a/projects/llhttp/project.yaml b/projects/llhttp/project.yaml
new file mode 100644
index 0000000..dda736a
--- /dev/null
+++ b/projects/llhttp/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://llhttp.org/"
+main_repo: "https://github.com/nodejs/llhttp"
+language: c
+primary_contact: "fedor@indutny.com"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/loki/Dockerfile b/projects/loki/Dockerfile
index 2340618..b045f79 100644
--- a/projects/loki/Dockerfile
+++ b/projects/loki/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/grafana/loki/
 COPY build.sh $SRC/
 WORKDIR $SRC/loki
diff --git a/projects/lotus/Dockerfile b/projects/lotus/Dockerfile
index 08dccff..bdbee43 100644
--- a/projects/lotus/Dockerfile
+++ b/projects/lotus/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN apt-get update && apt-get install -y mesa-opencl-icd ocl-icd-opencl-dev gcc \
     git bzr jq pkg-config curl clang build-essential hwloc libhwloc-dev
 RUN git clone --depth 1 https://github.com/filecoin-project/lotus
diff --git a/projects/matio/Dockerfile b/projects/matio/Dockerfile
index d69281c..1b8e927 100644
--- a/projects/matio/Dockerfile
+++ b/projects/matio/Dockerfile
@@ -18,6 +18,6 @@
 RUN apt-get update && apt-get install -y make autoconf automake libtool
 RUN git clone --depth 1 https://github.com/madler/zlib
 RUN git clone --depth 1 git://git.code.sf.net/p/matio/matio matio
-ADD https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.0/src/hdf5-1.12.0.tar.gz hdf5-1.12.0.tar.gz
+ADD https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.1/src/hdf5-1.12.1.tar.gz hdf5-1.12.1.tar.gz
 WORKDIR matio
 COPY build.sh $SRC/
diff --git a/projects/mbedtls/Dockerfile b/projects/mbedtls/Dockerfile
index 3a8908f..f39ea2a 100644
--- a/projects/mbedtls/Dockerfile
+++ b/projects/mbedtls/Dockerfile
@@ -17,7 +17,7 @@
 FROM gcr.io/oss-fuzz-base/base-builder
 #TODO change
 RUN apt-get update && apt-get install -y make cmake
-RUN git clone --recursive --depth 1 https://github.com/ARMmbed/mbedtls.git mbedtls
+RUN git clone --recursive --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls.git mbedtls
 RUN git clone --depth 1 https://github.com/google/boringssl.git boringssl
 RUN git clone --depth 1 https://github.com/openssl/openssl.git openssl
 WORKDIR mbedtls
diff --git a/projects/mdbtools/build.sh b/projects/mdbtools/build.sh
index d3269bc..048d4a1 100644
--- a/projects/mdbtools/build.sh
+++ b/projects/mdbtools/build.sh
@@ -17,7 +17,7 @@
 ################################################################################
 
 autoreconf -f -i
-./configure --enable-static --disable-man --disable-glib
+./configure --enable-static --disable-man --disable-glib --disable-silent-rules
 make clean
 
 make
diff --git a/projects/mercurial/project.yaml b/projects/mercurial/project.yaml
index 2908b04..09674b1 100644
--- a/projects/mercurial/project.yaml
+++ b/projects/mercurial/project.yaml
@@ -6,8 +6,11 @@
   - "kbullock@ringworld.org"
   - "security@mercurial-scm.org"
   - "martinvonz@google.com"
+  - "raphael.gomes@octobus.net"
 sanitizers:
   - address
   - undefined
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 coverage_extra_args: -ignore-filename-regex=.*/sanpy/.*
+main_repo: "https://www.mercurial-scm.org/repo/hg"
diff --git a/projects/minify/Dockerfile b/projects/minify/Dockerfile
index 3f3516a..20d75ad 100644
--- a/projects/minify/Dockerfile
+++ b/projects/minify/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/tdewolff/minify
 RUN git clone --depth 1 https://github.com/tdewolff/parse
 COPY build.sh $SRC/
diff --git a/projects/monero/Dockerfile b/projects/monero/Dockerfile
index fe2dbbe..d8f3619 100644
--- a/projects/monero/Dockerfile
+++ b/projects/monero/Dockerfile
@@ -44,7 +44,8 @@
         libreadline-dev \
         libudev-dev \
         libprotobuf-dev \
-        protobuf-compiler
+        protobuf-compiler \
+        libexpat-dev
 
 WORKDIR monero
 
@@ -117,5 +118,8 @@
     && make \
     && make install
 
+RUN git clone https://github.com/NLnetLabs/unbound && \
+    cd unbound && ./configure && make && make install
+
 RUN git clone --depth 1 https://github.com/monero-project/monero.git monero
 COPY build.sh $SRC/
diff --git a/projects/mp4parse-rust/Dockerfile b/projects/mp4parse-rust/Dockerfile
index 990fbba..f974759 100644
--- a/projects/mp4parse-rust/Dockerfile
+++ b/projects/mp4parse-rust/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 RUN apt-get update && apt-get install -y make autoconf automake libtool curl cmake python llvm-dev libclang-dev clang
 
 RUN git clone --depth 1 --recursive https://github.com/mozilla/mp4parse-rust mp4parse-rust
diff --git a/projects/msgpack-c/Dockerfile b/projects/msgpack-c/Dockerfile
index 87efd76..385767b 100644
--- a/projects/msgpack-c/Dockerfile
+++ b/projects/msgpack-c/Dockerfile
@@ -18,7 +18,7 @@
 RUN apt-get update && apt-get install -y cmake wget bzip2
 RUN git clone --depth 1 --single-branch --branch cpp_master https://github.com/msgpack/msgpack-c.git msgpack-c
 
-RUN wget https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.bz2 && \
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2 && \
     tar xf boost_1_70_0.tar.bz2 && \
     cd boost_1_70_0 && \
     ./bootstrap.sh --with-toolset=clang --prefix=/usr && \
diff --git a/projects/mtail/Dockerfile b/projects/mtail/Dockerfile
index 7861cbc..b61263a 100644
--- a/projects/mtail/Dockerfile
+++ b/projects/mtail/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/google/mtail $GOPATH/src/github.com/google/mtail
 WORKDIR $GOPATH/src/github.com/google/mtail
 COPY build.sh $SRC/
diff --git a/projects/mtail/build.sh b/projects/mtail/build.sh
index 2c769ad..9e6eff2 100755
--- a/projects/mtail/build.sh
+++ b/projects/mtail/build.sh
@@ -15,6 +15,6 @@
 #
 ################################################################################
 
-compile_go_fuzzer github.com/google/mtail/internal/vm Fuzz vm-fuzzer
+compile_go_fuzzer github.com/google/mtail/internal/runtime Fuzz vm-fuzzer
 # Make the dictionary and seed corpus.
 make --debug $OUT/vm-fuzzer.dict $OUT/vm-fuzzer_seed_corpus.zip
diff --git a/projects/muduo/Dockerfile b/projects/muduo/Dockerfile
new file mode 100644
index 0000000..d8ba223
--- /dev/null
+++ b/projects/muduo/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make libboost-dev
+RUN git clone --depth 1 https://github.com/chenshuo/muduo
+WORKDIR muduo
+COPY build.sh muduo_http_fuzzer.cpp $SRC/
diff --git a/projects/muduo/build.sh b/projects/muduo/build.sh
new file mode 100755
index 0000000..023146e
--- /dev/null
+++ b/projects/muduo/build.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+sed -i '34 a $ENV{CXXFLAGS}' CMakeLists.txt
+mkdir -p build-dir && cd build-dir
+cmake -DCMAKE_BUILD_TYPE="release" \
+      ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -I/src/muduo \
+	-o muduo_http_fuzzer.o \
+    -c $SRC/muduo_http_fuzzer.cpp
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+	muduo_http_fuzzer.o \
+    -o $OUT/muduo_http_fuzzer \
+	./lib/libmuduo_http.a \
+	./lib/libmuduo_net.a \
+	./lib/libmuduo_base.a 
diff --git a/projects/muduo/muduo_http_fuzzer.cpp b/projects/muduo/muduo_http_fuzzer.cpp
new file mode 100644
index 0000000..d3eed6a
--- /dev/null
+++ b/projects/muduo/muduo_http_fuzzer.cpp
@@ -0,0 +1,35 @@
+/*  Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "muduo/net/http/HttpContext.h"
+#include "muduo/net/Buffer.h"
+#include "muduo/base/Timestamp.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+	char *new_str = (char *)malloc(size+1);
+	if (new_str == NULL){
+		return 0;
+	}
+	memcpy(new_str, data, size);
+	new_str[size] = '\0';
+	
+	muduo::net::HttpContext context;
+	muduo::net::Buffer input;
+	input.append(new_str);
+	context.parseRequest(&input, muduo::Timestamp::now());
+	free(new_str);
+	return 0;
+}
diff --git a/projects/muduo/project.yaml b/projects/muduo/project.yaml
new file mode 100644
index 0000000..0a22499
--- /dev/null
+++ b/projects/muduo/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/chenshuo/muduo"
+language: c++
+primary_contact: "chenshuo@chenshuo.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+main_repo: "https://github.com/chenshuo/muduo"
diff --git a/projects/mupdf/Dockerfile b/projects/mupdf/Dockerfile
index 160ce0e..8d1668e 100644
--- a/projects/mupdf/Dockerfile
+++ b/projects/mupdf/Dockerfile
@@ -22,5 +22,5 @@
     rm -rf pdf.js
 ADD https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/pdf.dict $SRC/pdf_fuzzer.dict
 WORKDIR mupdf
-COPY *.cc source/fuzz/
+COPY *.cc $SRC/
 COPY build.sh *.options $SRC/
diff --git a/projects/mupdf/build.sh b/projects/mupdf/build.sh
index d061906..6a2613c 100755
--- a/projects/mupdf/build.sh
+++ b/projects/mupdf/build.sh
@@ -15,11 +15,14 @@
 #
 ################################################################################
 
+# supp_size is unused in harfbuzz so we will avoid it being unused.
+sed -i 's/supp_size;/supp_size;(void)(supp_size);/g' ./thirdparty/harfbuzz/src/hb-subset-cff1.cc
+
 LDFLAGS="$CXXFLAGS" make -j$(nproc) HAVE_GLUT=no build=debug OUT=$WORK
 fuzz_target=pdf_fuzzer
 
 $CXX $CXXFLAGS -std=c++11 -Iinclude \
-    source/fuzz/pdf_fuzzer.cc -o $OUT/$fuzz_target \
+    $SRC/pdf_fuzzer.cc -o $OUT/$fuzz_target \
     $LIB_FUZZING_ENGINE $WORK/libmupdf.a $WORK/libmupdf-third.a
 
 mv $SRC/{*.zip,*.dict,*.options} $OUT
diff --git a/projects/myanmar-tools/build.sh b/projects/myanmar-tools/build.sh
index 771601b..e136322 100644
--- a/projects/myanmar-tools/build.sh
+++ b/projects/myanmar-tools/build.sh
@@ -1,16 +1,19 @@
+#!/bin/bash -eu
 # Copyright 2019 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-# https://www.apache.org/licenses/LICENSE-2.0
+#      http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+#
+################################################################################
 
 cd $SRC/myanmar-tools/clients/cpp
 mkdir build
@@ -30,7 +33,7 @@
 # Copy libunwind since it isn't on the ClusterFuzz bot images.
 cp /usr/lib/x86_64-linux-gnu/libunwind.so.8 $OUT/lib/
 $CXX $CXXFLAGS -std=c++11 -I../public -L$OUT/lib \
-    -Wl,-rpath,'$ORIGIN/lib' -lmyanmartools \
+    -Wl,-rpath,'$ORIGIN/lib' -lmyanmartools -lunwind \
     -o $OUT/zawgyi_detector_fuzz_target \
     ../zawgyi_detector_fuzz_target.cpp \
     $LIB_FUZZING_ENGINE
diff --git a/projects/myanmar-tools/project.yaml b/projects/myanmar-tools/project.yaml
index d2c7f32..5d583ad 100644
--- a/projects/myanmar-tools/project.yaml
+++ b/projects/myanmar-tools/project.yaml
@@ -5,6 +5,7 @@
   - "ccornelius@google.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
 coverage_extra_args: -ignore-filename-regex=.*/\.hunter/.*
 main_repo: 'https://github.com/google/myanmar-tools.git'
diff --git a/projects/mysql-server/build.sh b/projects/mysql-server/build.sh
index 6ea7b27..ee4dfd0 100644
--- a/projects/mysql-server/build.sh
+++ b/projects/mysql-server/build.sh
@@ -25,7 +25,7 @@
 else
     cmake .. -Dprotobuf_BUILD_SHARED_LIBS=OFF -DDOWNLOAD_BOOST=1 -DWITH_BOOST=. -DWITH_SSL=system -DFUZZING=1 -DCMAKE_INSTALL_PREFIX=$OUT/mysql
 fi
-make install
+make -j$(nproc) install
 mv $OUT/mysql/bin/fuzz* $OUT/
 cp ../fuzz/fuzz*.options $OUT/
 cp ../fuzz/fuzz*.dict $OUT/
diff --git a/projects/mysql-server/fix.diff b/projects/mysql-server/fix.diff
index cec23c2..b8f7825 100644
--- a/projects/mysql-server/fix.diff
+++ b/projects/mysql-server/fix.diff
@@ -1,8 +1,8 @@
 diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 3667900243c..337344e124d 100644
+index 4a4bbfa72fa..0478561e66c 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
-@@ -597,6 +597,7 @@ IF(WITH_JEMALLOC AND (WITH_TCMALLOC OR WITH_TCMALLOC_DEBUG))
+@@ -688,6 +688,7 @@ IF(WITH_JEMALLOC AND (WITH_TCMALLOC OR WITH_TCMALLOC_DEBUG))
    MESSAGE(FATAL_ERROR "Specify only *one* of WITH_TCMALLOC and WITH_JEMALLOC")
  ENDIF()
  
@@ -10,8 +10,8 @@
  OPTION(ENABLED_PROFILING "Enable profiling" ON)
  OPTION(WITHOUT_SERVER OFF)
  
-@@ -1587,6 +1588,10 @@ IF(NOT WITHOUT_SERVER AND WITH_UNIT_TESTS)
-   TARGET_LINK_LIBRARIES(server_unittest_library ${ICU_LIBRARIES})
+@@ -1804,6 +1805,10 @@ IF(NOT WITHOUT_SERVER AND WITH_UNIT_TESTS)
+   ENDIF()
  ENDIF()
  
 +IF (FUZZING)
@@ -21,8 +21,22 @@
  # scripts/mysql_config depends on client and server targets loaded above.
  # It is referenced by some of the directories below, so we insert it here.
  ADD_SUBDIRECTORY(scripts)
+diff --git a/cmake/os/Linux.cmake b/cmake/os/Linux.cmake
+index 0e25e8eb..3ae74839 100644
+--- a/cmake/os/Linux.cmake
++++ b/cmake/os/Linux.cmake
+@@ -103,7 +103,8 @@ IF(NOT WITH_ASAN AND
+    NOT WITH_LSAN AND
+    NOT WITH_MSAN AND
+    NOT WITH_TSAN AND
+-   NOT WITH_UBSAN)
++   NOT WITH_UBSAN AND
++   NOT FUZZING)
+   SET(LINK_FLAG_NO_UNDEFINED "-Wl,--no-undefined")
+   SET(LINK_FLAG_Z_DEFS "-z,defs")
+ ENDIF()
 diff --git a/include/mysql.h b/include/mysql.h
-index b805bffdf88..23d2311299e 100644
+index 4700d74b853..bdf9b765ffb 100644
 --- a/include/mysql.h
 +++ b/include/mysql.h
 @@ -262,7 +262,8 @@ enum mysql_protocol_type {
@@ -36,10 +50,10 @@
  
  enum mysql_ssl_mode {
 diff --git a/include/mysql.h.pp b/include/mysql.h.pp
-index ce785802ad9..4f048082335 100644
+index 39ebd0fcb93..c041cc4690f 100644
 --- a/include/mysql.h.pp
 +++ b/include/mysql.h.pp
-@@ -485,7 +485,8 @@ enum mysql_protocol_type {
+@@ -486,7 +486,8 @@ enum mysql_protocol_type {
    MYSQL_PROTOCOL_TCP,
    MYSQL_PROTOCOL_SOCKET,
    MYSQL_PROTOCOL_PIPE,
@@ -50,7 +64,7 @@
  enum mysql_ssl_mode {
    SSL_MODE_DISABLED = 1,
 diff --git a/include/violite.h b/include/violite.h
-index c04e82505a7..2498ba0053c 100644
+index a6ccd1a607d..8dc0d46dd7f 100644
 --- a/include/violite.h
 +++ b/include/violite.h
 @@ -108,12 +108,14 @@ enum enum_vio_type : int {
@@ -91,13 +105,13 @@
 +
  #endif /* vio_violite_h_ */
 diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
-index 4956a0dc2d8..bab0aa3b504 100644
+index 334d1b7d3ef..c37c5ad930e 100644
 --- a/libmysql/CMakeLists.txt
 +++ b/libmysql/CMakeLists.txt
-@@ -353,11 +353,11 @@ IF(UNIX)
+@@ -345,11 +345,11 @@ IF(LINUX_STANDALONE AND KERBEROS_CUSTOM_LIBRARY)
+ ENDIF()
  
-   ADD_INSTALL_RPATH_FOR_OPENSSL(libmysql)
- 
+ IF(UNIX)
 -  IF(LINK_FLAG_Z_DEFS)
 +  IF(LINK_FLAG_Z_DEFS AND NOT FUZZING)
      MY_TARGET_LINK_OPTIONS(libmysql "LINKER:${LINK_FLAG_Z_DEFS}")
@@ -105,23 +119,11 @@
  
 -  IF(LINUX)
 +  IF(LINUX AND NOT FUZZING)
+     CONFIGURE_FILE(libmysql.ver.in ${CMAKE_CURRENT_BINARY_DIR}/libmysql.ver)
      MY_TARGET_LINK_OPTIONS(libmysql
        "LINKER:--version-script=${CMAKE_CURRENT_BINARY_DIR}/libmysql.ver")
-   ENDIF() 
-diff --git a/mysys/mf_tempfile.cc b/mysys/mf_tempfile.cc
-index f4f5dffba9a..26ab2ce0917 100644
---- a/mysys/mf_tempfile.cc
-+++ b/mysys/mf_tempfile.cc
-@@ -320,6 +320,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
-       set_my_errno(ENAMETOOLONG);
-       return file;
-     }
-+    sprintf(prefix_buff, "%sXXXXXX", prefix ? prefix : "tmp.");
-     my_stpcpy(convert_dirname(to, dir, NullS), prefix_buff);
-     file = mkstemp(to);
-     file_info::RegisterFilename(file, to, file_info::OpenType::FILE_BY_MKSTEMP);
 diff --git a/mysys/my_rnd.cc b/mysys/my_rnd.cc
-index 8253e3967d4..034c71de600 100644
+index 2fc7820eaa3..248ea909db8 100644
 --- a/mysys/my_rnd.cc
 +++ b/mysys/my_rnd.cc
 @@ -48,6 +48,9 @@
@@ -158,10 +160,10 @@
      *failed = true;
      return 0;
 diff --git a/sql-common/client.cc b/sql-common/client.cc
-index 61404be555b..721802cb60c 100644
+index b8050f2b1a7..9a65178c5c4 100644
 --- a/sql-common/client.cc
 +++ b/sql-common/client.cc
-@@ -5774,6 +5774,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) {
+@@ -5892,6 +5892,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) {
      }
    }
  #endif /* _WIN32 */
@@ -175,12 +177,12 @@
    if (!net->vio &&
        (!mysql->options.protocol ||
 diff --git a/sql/mysqld.cc b/sql/mysqld.cc
-index 519926135ed..db75dc7f5e5 100644
+index 50b76e2fa75..871006c2d8f 100644
 --- a/sql/mysqld.cc
 +++ b/sql/mysqld.cc
-@@ -6862,7 +6862,9 @@ int mysqld_main(int argc, char **argv)
-     unireg_abort(MYSQLD_ABORT_EXIT);  // Will do exit
-   }
+@@ -6991,7 +6991,9 @@ int mysqld_main(int argc, char **argv)
+ 
+   keyring_lockable_init();
  
 +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    my_init_signals();
@@ -188,7 +190,7 @@
  
    size_t guardize = 0;
  #ifndef _WIN32
-@@ -7347,8 +7349,10 @@ int mysqld_main(int argc, char **argv)
+@@ -7497,8 +7499,10 @@ int mysqld_main(int argc, char **argv)
      unireg_abort(MYSQLD_ABORT_EXIT);
  
  #ifndef _WIN32
@@ -199,7 +201,7 @@
  #endif
  
    /* set all persistent options */
-@@ -7393,8 +7397,9 @@ int mysqld_main(int argc, char **argv)
+@@ -7543,8 +7547,9 @@ int mysqld_main(int argc, char **argv)
    }
  
    start_handle_manager();
@@ -210,7 +212,7 @@
  
    LogEvent()
        .type(LOG_TYPE_ERROR)
-@@ -7441,6 +7446,10 @@ int mysqld_main(int argc, char **argv)
+@@ -7591,6 +7596,10 @@ int mysqld_main(int argc, char **argv)
  
    (void)RUN_HOOK(server_state, before_handle_connection, (nullptr));
  
@@ -221,7 +223,7 @@
  #if defined(_WIN32)
    if (mysqld_socket_acceptor != nullptr)
      mysqld_socket_acceptor->check_and_spawn_admin_connection_handler_thread();
-@@ -10281,6 +10290,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) {
+@@ -10500,6 +10509,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) {
  
    if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT;
  
@@ -232,10 +234,10 @@
      LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM);
      return 1;
 diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
-index fba0684f322..8352dacbc03 100644
+index 7ecc10961ac..5f13f94eb02 100644
 --- a/storage/innobase/buf/buf0buf.cc
 +++ b/storage/innobase/buf/buf0buf.cc
-@@ -1487,18 +1487,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) {
+@@ -1476,18 +1476,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) {
        n = n_instances;
      }
  
@@ -257,7 +259,7 @@
          err = errs[id];
        }
 diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt
-index d44eebce63a..975bc878e17 100644
+index 35ab5f17f15..9b39bfdbdbf 100644
 --- a/vio/CMakeLists.txt
 +++ b/vio/CMakeLists.txt
 @@ -27,6 +27,7 @@ SET(VIO_SOURCES
@@ -269,7 +271,7 @@
  
  IF(WIN32)
 diff --git a/vio/vio.cc b/vio/vio.cc
-index 38e3d90f20e..abbc9a52478 100644
+index 368c8d7b581..50c3231a8b0 100644
 --- a/vio/vio.cc
 +++ b/vio/vio.cc
 @@ -284,6 +284,26 @@ static bool vio_init(Vio *vio, enum enum_vio_type type, my_socket sd,
@@ -311,7 +313,7 @@
                         int *len) {
 diff --git a/vio/viofuzz.cc b/vio/viofuzz.cc
 new file mode 100644
-index 00000000000..83f22a5dbb9
+index 00000000000..5b368d685cb
 --- /dev/null
 +++ b/vio/viofuzz.cc
 @@ -0,0 +1,124 @@
@@ -364,7 +366,7 @@
 +  DBUG_ENTER("vio_socket_connect");
 +
 +  /* Only for socket-based transport types. */
-+  DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
++  //DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
 +
 +  /* Initiate the connection. */
 +  return 0;
diff --git a/projects/mysql-server/project.yaml b/projects/mysql-server/project.yaml
index 68f04d2..893dfb0 100644
--- a/projects/mysql-server/project.yaml
+++ b/projects/mysql-server/project.yaml
@@ -9,7 +9,6 @@
 
 fuzzing_engines:
   - libfuzzer
-  - honggfuzz
 sanitizers:
   - address
   - undefined
diff --git a/projects/nats/Dockerfile b/projects/nats/Dockerfile
index a9dbcf4..e67288a 100644
--- a/projects/nats/Dockerfile
+++ b/projects/nats/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/nats-io/nats-server
 COPY build.sh $SRC/
 WORKDIR $SRC/nats-server
diff --git a/projects/nats/build.sh b/projects/nats/build.sh
index 2235a6e..b9ce8fd 100755
--- a/projects/nats/build.sh
+++ b/projects/nats/build.sh
@@ -15,8 +15,5 @@
 #
 ################################################################################
 
-
-
-compile_go_fuzzer ./conf Fuzz fuzz_conf
-compile_go_fuzzer ./server FuzzClient fuzz_client
-
+compile_go_fuzzer github.com/nats-io/nats-server/v2/conf Fuzz fuzz_conf
+compile_go_fuzzer github.com/nats-io/nats-server/v2/server FuzzClient fuzz_client
diff --git a/projects/ndpi/Dockerfile b/projects/ndpi/Dockerfile
index fafb081..11d426d 100644
--- a/projects/ndpi/Dockerfile
+++ b/projects/ndpi/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake autogen pkg-config libtool flex bison cmake
+RUN apt-get update && apt-get install -y make autoconf automake autogen pkg-config libtool flex bison cmake libnuma-dev libgcrypt20-dev libpcre2-dev
 RUN git clone --depth 1 https://github.com/json-c/json-c.git json-c
 RUN git clone --depth 1 https://github.com/ntop/nDPI.git ndpi
 ADD https://www.tcpdump.org/release/libpcap-1.9.1.tar.gz libpcap-1.9.1.tar.gz
diff --git a/projects/nestegg/project.yaml b/projects/nestegg/project.yaml
index 93165f3..2e4b2e5 100644
--- a/projects/nestegg/project.yaml
+++ b/projects/nestegg/project.yaml
@@ -5,12 +5,10 @@
   - afl
   - libfuzzer
   - honggfuzz
-  - dataflow
 sanitizers:
   - address
   - memory
   - undefined
-  - dataflow
 vendor_ccs:
   - "twsmith@mozilla.com"
 main_repo: 'https://github.com/kinetiknz/nestegg.git'
diff --git a/projects/net-snmp/Dockerfile b/projects/net-snmp/Dockerfile
index c9e6a79..324a732 100644
--- a/projects/net-snmp/Dockerfile
+++ b/projects/net-snmp/Dockerfile
@@ -15,11 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf libtool libssl-dev
-RUN git clone --depth 1 git://git.code.sf.net/p/net-snmp/code net-snmp
+RUN git clone -q --depth 1 https://github.com/net-snmp/net-snmp net-snmp
+RUN net-snmp/ci/install.sh
 WORKDIR net-snmp
 COPY build.sh $SRC/
-#
-# Until the project moves the fuzzers to the source tree
-COPY snmp_pdu_parse_fuzzer.c $SRC/
-COPY agentx_parse_fuzzer.c $SRC/
diff --git a/projects/net-snmp/agentx_parse_fuzzer.c b/projects/net-snmp/agentx_parse_fuzzer.c
deleted file mode 100644
index 4360112..0000000
--- a/projects/net-snmp/agentx_parse_fuzzer.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This fuzzer exercises the agentx PDU parsing code.
- */
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-/* We build with the agent/mibgroup/agentx dir in an -I */
-#include <protocol.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-int LLVMFuzzerInitialize(int *argc, char ***argv) {
-    if (getenv("NETSNMP_DEBUGGING") != NULL) {
-        /*
-         * Turn on all debugging, to help understand what
-         * bits of the parser are running.
-         */
-        snmp_enable_stderrlog();
-        snmp_set_do_debugging(1);
-        debug_register_tokens("");
-    }
-    return 0;
-}
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-    netsnmp_pdu *pdu = SNMP_MALLOC_TYPEDEF(netsnmp_pdu);
-    netsnmp_session session;
-
-    session.version = AGENTX_VERSION_1;
-    agentx_parse(&session, pdu, (unsigned char *)data, size);
-    snmp_free_pdu(pdu);
-    return 0;
-}
diff --git a/projects/net-snmp/build.sh b/projects/net-snmp/build.sh
index b7bceda..3753b76 100755
--- a/projects/net-snmp/build.sh
+++ b/projects/net-snmp/build.sh
@@ -15,21 +15,6 @@
 #
 ################################################################################
 
-# build project
-./configure --with-openssl=/usr --with-defaults --with-logfile="/dev/null" --with-persistent-directory="/dev/null"
-# net-snmp build is not parallel-make safe; do not add -j
-make
-
-# build fuzzers (remember to link statically)
-$CC $CFLAGS -c -Iinclude $SRC/snmp_pdu_parse_fuzzer.c -o $WORK/snmp_pdu_parse_fuzzer.o
-$CXX $CXXFLAGS $WORK/snmp_pdu_parse_fuzzer.o \
-      $LIB_FUZZING_ENGINE snmplib/.libs/libnetsnmp.a \
-      -Wl,-Bstatic -lcrypto -Wl,-Bdynamic -lm \
-      -o $OUT/snmp_pdu_parse_fuzzer
-
-$CC $CFLAGS -c -Iinclude -Iagent/mibgroup/agentx $SRC/agentx_parse_fuzzer.c -o $WORK/agentx_parse_fuzzer.o
-$CXX $CXXFLAGS $WORK/agentx_parse_fuzzer.o \
-      $LIB_FUZZING_ENGINE snmplib/.libs/libnetsnmp.a \
-      agent/.libs/libnetsnmpagent.a \
-      -Wl,-Bstatic -lcrypto -Wl,-Bdynamic -lm \
-      -o $OUT/agentx_parse_fuzzer
+# Configure and build Net-SNMP and the fuzzers.
+export CC CXX CFLAGS CXXFLAGS SRC WORK OUT LIB_FUZZING_ENGINE
+ci/build.sh
diff --git a/projects/net-snmp/project.yaml b/projects/net-snmp/project.yaml
index 3392038..5a27e2e 100644
--- a/projects/net-snmp/project.yaml
+++ b/projects/net-snmp/project.yaml
@@ -6,4 +6,5 @@
    - "fenner@gmail.com"
    - "bvanassche@acm.org"
    - "magfr@lysator.liu.se"
+   - "david@adalogics.com"
 main_repo: 'git://git.code.sf.net/p/net-snmp/code'
diff --git a/projects/net-snmp/snmp_pdu_parse_fuzzer.c b/projects/net-snmp/snmp_pdu_parse_fuzzer.c
deleted file mode 100644
index 6d45552..0000000
--- a/projects/net-snmp/snmp_pdu_parse_fuzzer.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This fuzzer exercises the SNMP PDU parsing code, including ASN.1.
- */
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-int LLVMFuzzerInitialize(int *argc, char ***argv) {
-    if (getenv("NETSNMP_DEBUGGING") != NULL) {
-        /*
-         * Turn on all debugging, to help understand what
-         * bits of the parser are running.
-         */
-        snmp_enable_stderrlog();
-        snmp_set_do_debugging(1);
-        debug_register_tokens("");
-    }
-    return 0;
-}
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-    size_t bytes_remaining = size;
-    netsnmp_pdu *pdu = SNMP_MALLOC_TYPEDEF(netsnmp_pdu);
-
-    snmp_pdu_parse(pdu, (unsigned char *)data, &bytes_remaining);
-    snmp_free_pdu(pdu);
-    return 0;
-}
diff --git a/projects/netcdf/Dockerfile b/projects/netcdf/Dockerfile
new file mode 100644
index 0000000..41f0aca
--- /dev/null
+++ b/projects/netcdf/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y cmake m4 zlib1g-dev
+RUN git clone --depth 1 https://github.com/Unidata/netcdf-c
+COPY build.sh $SRC
+WORKDIR $SRC/netcdf-c
diff --git a/projects/netcdf/build.sh b/projects/netcdf/build.sh
new file mode 100755
index 0000000..eeae9cd
--- /dev/null
+++ b/projects/netcdf/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# build project
+mkdir build
+cd build
+cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_HDF5=OFF -DENABLE_DAP=OFF ..
+make -j$(nproc)
+cp fuzz/fuzz* $OUT/
diff --git a/projects/netcdf/project.yaml b/projects/netcdf/project.yaml
new file mode 100644
index 0000000..794e5cb
--- /dev/null
+++ b/projects/netcdf/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://www.unidata.ucar.edu/software/netcdf/docs/index.html"
+language: c++
+primary_contact: "wfisher@ucar.edu"
+auto_ccs:
+- "p.antoine@catenacyber.fr"
+- "dmh@ucar.edu"
+
+sanitizers:
+- address
+- undefined
+main_repo: 'https://github.com/Unidata/netcdf-c'
diff --git a/projects/nettle/Dockerfile b/projects/nettle/Dockerfile
index 5367c20..b7b987c 100644
--- a/projects/nettle/Dockerfile
+++ b/projects/nettle/Dockerfile
@@ -15,11 +15,11 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get install -y software-properties-common python-software-properties make autoconf build-essential wget lzip libtool
+RUN apt-get install -y software-properties-common make autoconf build-essential wget lzip libtool python
 RUN git clone --depth 1 https://git.lysator.liu.se/nettle/nettle
 RUN git clone --depth 1 https://github.com/randombit/botan.git
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
 RUN wget https://gmplib.org/download/gmp/gmp-6.2.0.tar.lz
 COPY build.sh $SRC/
diff --git a/projects/nettle/build.sh b/projects/nettle/build.sh
index 0101831..e10c5d7 100755
--- a/projects/nettle/build.sh
+++ b/projects/nettle/build.sh
@@ -56,24 +56,18 @@
         cp -R $SRC/nettle $SRC/nettle-with-libgmp/
         cd $SRC/nettle-with-libgmp/
         bash .bootstrap
+        export NETTLE_LIBDIR=`realpath ../nettle-with-libgmp-install`/lib
         if [[ $CFLAGS != *sanitize=memory* ]]
         then
-            ./configure --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-libgmp-install`
+            ./configure --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-libgmp-install` --libdir="$NETTLE_LIBDIR"
         else
-            ./configure --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-libgmp-install`
+            ./configure --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-libgmp-install` --libdir="$NETTLE_LIBDIR"
         fi
         make -j$(nproc)
         make install
 
-        if [[ $CFLAGS != *-m32* ]]
-        then
-        export LIBNETTLE_A_PATH=`realpath ../nettle-with-libgmp-install/lib/libnettle.a`
-        export LIBHOGWEED_A_PATH=`realpath ../nettle-with-libgmp-install/lib/libhogweed.a`
-        ls -l $LIBHOGWEED_A_PATH
-        else
-        export LIBNETTLE_A_PATH=`realpath ../nettle-with-libgmp-install/lib32/libnettle.a`
-        export LIBHOGWEED_A_PATH=`realpath ../nettle-with-libgmp-install/lib32/libhogweed.a`
-        fi
+        export LIBNETTLE_A_PATH=$NETTLE_LIBDIR/libnettle.a
+        export LIBHOGWEED_A_PATH=$NETTLE_LIBDIR/libhogweed.a
         export NETTLE_INCLUDE_PATH=`realpath ../nettle-with-libgmp-install/include`
         export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NETTLE"
         export LINK_FLAGS="$LINK_FLAGS /usr/local/lib/libgmp.a"
@@ -121,24 +115,18 @@
     cp -R $SRC/nettle $SRC/nettle-with-mini-gmp/
     cd $SRC/nettle-with-mini-gmp/
     bash .bootstrap
+    export NETTLE_LIBDIR=`realpath ../nettle-with-mini-gmp-install`/lib
     if [[ $CFLAGS != *sanitize=memory* ]]
     then
-        ./configure --enable-mini-gmp --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-mini-gmp-install`
+        ./configure --enable-mini-gmp --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-mini-gmp-install` --libdir="$NETTLE_LIBDIR"
     else
-        ./configure --enable-mini-gmp --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-mini-gmp-install`
+        ./configure --enable-mini-gmp --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-mini-gmp-install` --libdir="$NETTLE_LIBDIR"
     fi
     make -j$(nproc)
     make install
 
-    if [[ $CFLAGS != *-m32* ]]
-    then
-    export LIBNETTLE_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib/libnettle.a`
-    export LIBHOGWEED_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib/libhogweed.a`
-    ls -l $LIBHOGWEED_A_PATH
-    else
-    export LIBNETTLE_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib32/libnettle.a`
-    export LIBHOGWEED_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib32/libhogweed.a`
-    fi
+    export LIBNETTLE_A_PATH=$NETTLE_LIBDIR/libnettle.a
+    export LIBHOGWEED_A_PATH=$NETTLE_LIBDIR/libhogweed.a
     export NETTLE_INCLUDE_PATH=`realpath ../nettle-with-mini-gmp-install/include`
     export LINK_FLAGS=""
     export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NETTLE"
diff --git a/projects/nettle/project.yaml b/projects/nettle/project.yaml
index 77b348c..698d20b 100644
--- a/projects/nettle/project.yaml
+++ b/projects/nettle/project.yaml
@@ -6,7 +6,8 @@
 sanitizers:
  - address
  - undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
 architectures:
  - x86_64
  - i386
diff --git a/projects/nginx/build.sh b/projects/nginx/build.sh
index fcfb70b..88bfb59 100644
--- a/projects/nginx/build.sh
+++ b/projects/nginx/build.sh
@@ -25,7 +25,8 @@
 
 auto/configure \
     --with-ld-opt="-Wl,--wrap=listen -Wl,--wrap=setsockopt -Wl,--wrap=bind -Wl,--wrap=shutdown -Wl,--wrap=connect -Wl,--wrap=getpwnam -Wl,--wrap=getgrnam -Wl,--wrap=chmod -Wl,--wrap=chown" \
-    --with-http_v2_module
+    --with-cc-opt='-DNGX_DEBUG_PALLOC=1' \
+    --with-http_v2_module 
 make -f objs/Makefile fuzzers
 
 cp objs/*_fuzzer $OUT/
diff --git a/projects/nginx/fuzz/http_request_fuzzer.cc b/projects/nginx/fuzz/http_request_fuzzer.cc
index 8d69e82..317826c 100644
--- a/projects/nginx/fuzz/http_request_fuzzer.cc
+++ b/projects/nginx/fuzz/http_request_fuzzer.cc
@@ -230,6 +230,9 @@
   ngx_event_actions.init = init_event;
   ngx_io.send_chain = send_chain;
   ngx_event_flags = 1;
+  ngx_queue_init(&ngx_posted_accept_events);
+  ngx_queue_init(&ngx_posted_next_events);
+  ngx_queue_init(&ngx_posted_events);
   ngx_event_timer_init(cycle->log);
   return 0;
 }
@@ -286,6 +289,7 @@
       255, &ngx_log); // 255 - (hopefully unused) socket descriptor
 
   c->shared = 1;
+  c->destroyed = 0;
   c->type = SOCK_STREAM;
   c->pool = ngx_create_pool(256, ngx_cycle->log);
   c->sockaddr = ls->sockaddr;
@@ -301,10 +305,24 @@
   c->socklen = ls->socklen;
   c->local_sockaddr = ls->sockaddr;
   c->local_socklen = ls->socklen;
+  c->data = NULL;
 
   read_event1.ready = 1;
   write_event1.ready = write_event1.delayed = 1;
 
   // Will redirect to http parser
   ngx_http_init_connection(c);
+
+  // We do not provide working timers or events, and thus we have to manually
+  // clean up the requests we created. We do this here.
+  // Cross-referencing: https://trac.nginx.org/nginx/ticket/2080#no1).I
+  // This is a fix that should be bettered in the future, by creating proper
+  // timers and events.
+  if (c->destroyed != 1) {
+    if (c->read->data != NULL) {
+      ngx_connection_t *c2 = (ngx_connection_t*)c->read->data;
+      ngx_http_free_request((ngx_http_request_t*)c2->data, 0);
+    }
+    ngx_http_close_connection(c);
+  }
 }
diff --git a/projects/nginx/project.yaml b/projects/nginx/project.yaml
index 0aa9020..0bbff0a 100644
--- a/projects/nginx/project.yaml
+++ b/projects/nginx/project.yaml
@@ -1,8 +1,9 @@
 homepage: "http://nginx.org"
+main_repo: "https://github.com/nginx/nginx"
 language: c
 primary_contact: "xim.andrew@gmail.com"
 auto_ccs:
-  - ouyangyunshu@google.com
-  - mmoroz@google.com
+  - pluknet@gmail.com
+  - david@adalogics.com
 sanitizers:
   - address
diff --git a/projects/ninja/project.yaml b/projects/ninja/project.yaml
index d35fdc4..2f6baf4 100644
--- a/projects/ninja/project.yaml
+++ b/projects/ninja/project.yaml
@@ -6,5 +6,6 @@
 sanitizers:
   - address
   - undefined
-  - memory
-main_repo: "https://github.com/ninja-build/ninja"
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: "https://github.com/ninja-build/ninja"
\ No newline at end of file
diff --git a/projects/njs/project.yaml b/projects/njs/project.yaml
index bd92434..65b2bf8 100644
--- a/projects/njs/project.yaml
+++ b/projects/njs/project.yaml
@@ -1,12 +1,13 @@
 homepage: "https://nginx.org/en/docs/njs/"
 language: c++
-primary_contact: "xeioex@nginx.com"
+primary_contact: "xeioexception@gmail.com"
 auto_ccs:
- - "alexander.borisov@nginx.com"
+ - "lex.borisov@gmail.com"
  - "devrep@nginx.com"
- - "mmoroz@google.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 coverage_extra_args: -ignore-filename-regex=.*/pcre/.*
+main_repo: 'https://github.com/nginx/njs.git'
\ No newline at end of file
diff --git a/projects/nom/Dockerfile b/projects/nom/Dockerfile
index 167550e..793d785 100644
--- a/projects/nom/Dockerfile
+++ b/projects/nom/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN git clone --depth 1 https://github.com/Geal/nom/
 WORKDIR $SRC
diff --git a/projects/nss/Dockerfile b/projects/nss/Dockerfile
index 5ad8b5e..1bc729b 100644
--- a/projects/nss/Dockerfile
+++ b/projects/nss/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make mercurial zlib1g-dev gyp ninja-build libssl-dev
+RUN apt-get update && apt-get install -y make mercurial zlib1g-dev gyp ninja-build libssl-dev python
 
 RUN hg clone https://hg.mozilla.org/projects/nspr nspr
 RUN hg clone https://hg.mozilla.org/projects/nss nss
diff --git a/projects/oak/Dockerfile b/projects/oak/Dockerfile
index e6f44f3..16f7741 100644
--- a/projects/oak/Dockerfile
+++ b/projects/oak/Dockerfile
@@ -14,26 +14,34 @@
 #
 ################################################################################
 
-# TODO(https://github.com/google/oss-fuzz/issues/3093): Stop specifying the
-# image SHA once the bug is fixed.
-FROM gcr.io/oss-fuzz-base/base-builder@sha256:276813aef0ce5972db43c0230f96162003994fa742fb1b2f4e66c67498575c65
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
-# Use a fixed Bazel version.
-# https://github.com/google/asylo/blob/088ea3490dd4579655bd5b65b0e31fe18de7f6dd/asylo/distrib/toolchain/Dockerfile#L48-L71
-ARG bazel_version=1.1.0
-ARG bazel_sha=138b47ffd54924e3c0264c65d31d3927803fb9025db4d5b18107df79ee3bda95
-ARG bazel_url=https://storage.googleapis.com/bazel-apt/pool/jdk1.8/b/bazel/bazel_${bazel_version}_amd64.deb
+RUN apt-get --yes update \
+   && apt-get install --no-install-recommends --yes \
+   libssl-dev \
+   pkg-config \
+   python \
+   && apt-get clean \
+   && rm --recursive --force /var/lib/apt/lists/*
 
-# Install Bazel.
-RUN apt-get update && \
-    apt-get install -y wget && \
-    wget "${bazel_url}" -nv -o- -O bazel.deb && \
-    echo "${bazel_sha}  bazel.deb" > bazel.sha256 && \
-    sha256sum --check bazel.sha256 && \
-    apt-get install -y ./bazel.deb && \
-    rm bazel.deb bazel.sha256 && \
-    apt-get clean
+# Install WebAssembly target for Rust.
+RUN rustup target add wasm32-unknown-unknown
+
+# Install Protobuf compiler.
+ARG protobuf_version=3.13.0
+ARG protobuf_sha256=4a3b26d1ebb9c1d23e933694a6669295f6a39ddc64c3db2adf671f0a6026f82e
+ARG protobuf_dir=/usr/local/protobuf
+ARG protobuf_temp=/tmp/protobuf.zip
+ENV PATH "${protobuf_dir}/bin:${PATH}"
+RUN curl --location https://github.com/protocolbuffers/protobuf/releases/download/v${protobuf_version}/protoc-${protobuf_version}-linux-x86_64.zip > ${protobuf_temp} \
+  && sha256sum --binary ${protobuf_temp} && echo "${protobuf_sha256} *${protobuf_temp}" | sha256sum --check \
+  && unzip ${protobuf_temp} -d ${protobuf_dir} \
+  && rm ${protobuf_temp} \
+  && chmod --recursive a+rwx ${protobuf_dir} \
+  && protoc --version
 
 RUN git clone --depth 1 https://github.com/project-oak/oak oak
+
 WORKDIR oak
 COPY build.sh $SRC/
+COPY rustc.py $SRC/
diff --git a/projects/oak/build.sh b/projects/oak/build.sh
index 2e46c77..8a27208 100755
--- a/projects/oak/build.sh
+++ b/projects/oak/build.sh
@@ -15,62 +15,22 @@
 #
 ################################################################################
 
-# Mostly copied from
-# https://github.com/google/oss-fuzz/blob/7f8013db108e62727fba1c3cbcccac07d543682b/projects/grpc/build.sh
+cd oak_functions/loader/
 
-# Copy $CFLAGS and $CXXFLAGS into Bazel command-line flags, for both
-# compilation and linking.
-#
-# Some flags, such as `-stdlib=libc++`, generate warnings if used on a C source
-# file. Since the build runs with `-Werror` this will cause it to break, so we
-# use `--conlyopt` and `--cxxopt` instead of `--copt`.
-readonly EXTRA_BAZEL_FLAGS="$(
-for f in ${CFLAGS}; do
-  echo "--conlyopt=${f}" "--linkopt=${f}"
-done
-for f in ${CXXFLAGS}; do
-  echo "--cxxopt=${f}" "--linkopt=${f}"
-done
-if [ "${SANITIZER}" = "undefined" ]
+if [ "$SANITIZER" = "coverage" ]
 then
-  # Bazel uses clang to link binary, which does not link clang_rt ubsan library for C++ automatically.
-  # See issue: https://github.com/bazelbuild/bazel/issues/8777
-  echo "--linkopt=$(find $(llvm-config --libdir) -name libclang_rt.ubsan_standalone_cxx-x86_64.a | head -1)"
+  export RUSTFLAGS="$RUSTFLAGS -C debug-assertions=no"
+  chmod +x $SRC/rustc.py
+  export RUSTC="$SRC/rustc.py"
 fi
-)"
 
-# Temporary hack, see https://github.com/google/oss-fuzz/issues/383
-readonly NO_VPTR='--copt=-fno-sanitize=vptr --linkopt=-fno-sanitize=vptr'
+cargo fuzz build --release
 
-readonly FUZZER_TARGETS=()
-readonly ENABLED=false
+FUZZ_TARGET_OUTPUT_DIR=fuzz/target/x86_64-unknown-linux-gnu/release
+for f in fuzz/fuzz_targets/*.rs
+do
+    FUZZ_TARGET_NAME=$(basename ${f%.*})
+    cp $FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME $OUT/
+done
 
-if [ "$ENABLED" = true ]; then
-  bazel build \
-    --client_env=CC=${CC} \
-    --client_env=CXX=${CXX} \
-    --dynamic_mode=off \
-    --spawn_strategy=standalone \
-    --genrule_strategy=standalone \
-    ${NO_VPTR} \
-    --strip=never \
-    --linkopt=-lc++ \
-    --linkopt=-pthread \
-    --cxxopt=-std=c++11 \
-    --copt=${LIB_FUZZING_ENGINE} \
-    --linkopt=${LIB_FUZZING_ENGINE} \
-    --remote_cache=https://storage.googleapis.com/oak-bazel-cache \
-    --remote_upload_local_results=false \
-    ${EXTRA_BAZEL_FLAGS} \
-    ${FUZZER_TARGETS[@]}
 
-  for target in ${FUZZER_TARGETS}; do
-    # Replace : with /.
-    fuzzer_name="${target/:/\/}"
-    cp "./bazel-bin/${fuzzer_name}" "${OUT}/"
-  done
-
-  # Cleanup bazel- symlinks to avoid oss-fuzz trying to copy out of the build
-  # cache.
-  rm -f ./bazel-*
-fi
diff --git a/projects/oak/project.yaml b/projects/oak/project.yaml
index 3f79c7f..8436891 100644
--- a/projects/oak/project.yaml
+++ b/projects/oak/project.yaml
@@ -1,15 +1,15 @@
-disabled: True
 homepage: "https://github.com/project-oak/oak"
-language: c++
+language: rust
 primary_contact: "tzn@google.com"
 auto_ccs:
   - "project-oak-team@google.com"
   - "benblaxill@google.com"
-  - "drysdale@google.com"
   - "grobler@google.com"
   - "iovi@google.com"
   - "ivanpetrov@google.com"
-  - "mks@google.com"
+  - "razieh@google.com"
+sanitizers:
+  - address
 fuzzing_engines:
   - libfuzzer
 main_repo: 'https://github.com/project-oak/oak'
diff --git a/projects/oak/rustc.py b/projects/oak/rustc.py
new file mode 100644
index 0000000..55ce4c4
--- /dev/null
+++ b/projects/oak/rustc.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import subprocess
+
+#Disable coverage for troubling crates.
+sys.argv[0] = "rustc"
+if "tokio_util" in sys.argv or "hyper" in sys.argv:
+    try:
+        sys.argv.remove("-Zinstrument-coverage")
+    except:
+        pass
+    print(sys.argv)
+subprocess.call(sys.argv)
diff --git a/projects/oatpp/Dockerfile b/projects/oatpp/Dockerfile
new file mode 100644
index 0000000..43ef579
--- /dev/null
+++ b/projects/oatpp/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool
+RUN git clone --depth 1 https://github.com/oatpp/oatpp.git oatpp 
+WORKDIR oatpp
+COPY build.sh $SRC/
diff --git a/projects/oatpp/build.sh b/projects/oatpp/build.sh
new file mode 100755
index 0000000..8fc23cd
--- /dev/null
+++ b/projects/oatpp/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir build && cd build
+cmake ../
+make
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE ../fuzzers/oatpp/parser/json/mapping/ObjectMapper.cpp -o $OUT/fuzz_mapper \
+    ./src/liboatpp.a -I../src
diff --git a/projects/oatpp/project.yaml b/projects/oatpp/project.yaml
new file mode 100644
index 0000000..47203f6
--- /dev/null
+++ b/projects/oatpp/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://oatpp.io/"
+language: c++
+primary_contact: "bugs@oatpp.io"
+main_repo: "https://github.com/oatpp/oatpp"
+auto_ccs: 
+  - "leonid@oatpp.io"
+  - "david@adalogics.com"
diff --git a/projects/open62541/build.sh b/projects/open62541/build.sh
index db59c12..74051db 100755
--- a/projects/open62541/build.sh
+++ b/projects/open62541/build.sh
@@ -27,7 +27,7 @@
 # <= 600 FATAL
 # > 600 No LOG output
 
-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUA_ENABLE_AMALGAMATION=OFF \
+cmake -DCMAKE_BUILD_TYPE=Debug -DUA_ENABLE_AMALGAMATION=OFF \
       -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python2 \
       -DBUILD_SHARED_LIBS=OFF -DUA_BUILD_EXAMPLES=OFF -DUA_LOGLEVEL=600 \
       -DUA_ENABLE_ENCRYPTION=ON \
diff --git a/projects/open62541/project.yaml b/projects/open62541/project.yaml
index 7f0447c..f5c0ef9 100644
--- a/projects/open62541/project.yaml
+++ b/projects/open62541/project.yaml
@@ -5,8 +5,11 @@
  - "julius.pfrommer@gmail.com"
  - "chris_paul.iatrou@tu-dresden.de"
  - "ari.breitkreuz@gmail.com"
+fuzzing_engines:
+ - libfuzzer
+ - afl
 sanitizers:
-- address
-- undefined
-- memory
+ - address
+ - undefined
+ - memory
 main_repo: 'https://github.com/open62541/open62541.git'
diff --git a/projects/opencensus-cpp/.bazelrc b/projects/opencensus-cpp/.bazelrc
new file mode 100644
index 0000000..02f1b24
--- /dev/null
+++ b/projects/opencensus-cpp/.bazelrc
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Force the use of Clang for C++ builds.
+build --action_env=CC=clang
+build --action_env=CXX=clang++
+
+# Define the --config=asan-libfuzzer configuration.
+build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine
+build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz
+build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none
diff --git a/projects/opencensus-cpp/Dockerfile b/projects/opencensus-cpp/Dockerfile
new file mode 100644
index 0000000..8a3248c
--- /dev/null
+++ b/projects/opencensus-cpp/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN git clone --depth 1 https://github.com/census-instrumentation/opencensus-cpp
+COPY WORKSPACE .bazelrc $SRC/
+RUN cat WORKSPACE >> $SRC/opencensus-cpp/WORKSPACE
+RUN cat .bazelrc >> $SRC/opencensus-cpp/.bazelrc
+COPY build.sh $SRC/
+WORKDIR $SRC/opencensus-cpp
diff --git a/projects/opencensus-cpp/WORKSPACE b/projects/opencensus-cpp/WORKSPACE
new file mode 100644
index 0000000..6a9ee93
--- /dev/null
+++ b/projects/opencensus-cpp/WORKSPACE
@@ -0,0 +1,32 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+    name = "rules_fuzzing",
+    sha256 = "71fa2724c9802c597199a86111a0499fc4fb22426d322334d3f191dadeff5132",
+    strip_prefix = "rules_fuzzing-0.1.0",
+    urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/v0.1.0.zip"],
+)
+
+load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
+
+rules_fuzzing_dependencies()
+
+load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
+
+rules_fuzzing_init()
diff --git a/projects/opencensus-cpp/build.sh b/projects/opencensus-cpp/build.sh
new file mode 100755
index 0000000..04b7903
--- /dev/null
+++ b/projects/opencensus-cpp/build.sh
@@ -0,0 +1,22 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+git grep cc_fuzz_target.bzl | grep BUILD | cut -d: -f1 | uniq | while read i; do sed -i -e 's=//bazel:cc_fuzz_target.bzl=@rules_fuzzing//fuzzing:cc_defs.bzl=' $i; done
+
+git grep fuzz_target\( | grep BUILD | cut -d: -f1 | uniq | while read i; do sed -i -e 's/fuzz_target/fuzz_test/' $i; done
+
+bazel_build_fuzz_tests
diff --git a/projects/opencensus-cpp/project.yaml b/projects/opencensus-cpp/project.yaml
new file mode 100644
index 0000000..b84d07f
--- /dev/null
+++ b/projects/opencensus-cpp/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://opencensus.io/"
+language: c++
+primary_contact: "joshuasuereth@google.com"
+auto_ccs :
+- "p.antoine@catenacyber.fr"
+
+sanitizers:
+- address
+- memory
+main_repo: 'https://github.com/census-instrumentation/opencensus-cpp'
diff --git a/projects/opencv/project.yaml b/projects/opencv/project.yaml
index e6b085c..3062a93 100644
--- a/projects/opencv/project.yaml
+++ b/projects/opencv/project.yaml
@@ -12,11 +12,12 @@
 sanitizers:
   - address
   - undefined
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 
 labels:
   imdecode_fuzzer:
     - sundew
   imread_fuzzer:
     - sundew
-main_repo: 'https://github.com/opencv/opencv.git'
+main_repo: 'https://github.com/opencv/opencv.git'
\ No newline at end of file
diff --git a/projects/opendnp3/project.yaml b/projects/opendnp3/project.yaml
index 47c72b6..cc6a300 100644
--- a/projects/opendnp3/project.yaml
+++ b/projects/opendnp3/project.yaml
@@ -7,6 +7,7 @@
 
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 main_repo: 'https://github.com/dnp3/opendnp3.git'
diff --git a/projects/openexr/build.sh b/projects/openexr/build.sh
index 80a2e49..2b9e411 100755
--- a/projects/openexr/build.sh
+++ b/projects/openexr/build.sh
@@ -19,17 +19,16 @@
 
 CMAKE_SETTINGS=(
   "-D BUILD_SHARED_LIBS=OFF"         # Build static libraries only
-  "-D PYILMBASE_ENABLE=OFF"          # Don't build Python support
   "-D BUILD_TESTING=OFF"             # Or tests
-  "-D INSTALL_OPENEXR_EXAMPLES=OFF"  # Or examples
+  "-D OPENEXR_INSTALL_EXAMPLES=OFF"  # Or examples
   "-D OPENEXR_LIB_SUFFIX="           # Don't append the version number to library files
-  "-D ILMBASE_LIB_SUFFIX="
 )
 cmake $SRC/openexr ${CMAKE_SETTINGS[@]}
 make -j$(nproc)
 
 INCLUDES=(
   "-I $SRC"
+  "-I $SRC/openexr/src/lib/OpenEXRCore"
   "-I $SRC/openexr/src/lib/OpenEXR"
   "-I $SRC/openexr/src/lib/OpenEXRUtil"
   "-I $WORK/cmake"
@@ -38,6 +37,7 @@
 LIBS=(
   "$WORK/src/lib/OpenEXRUtil/libOpenEXRUtil.a"
   "$WORK/src/lib/OpenEXR/libOpenEXR.a"
+  "$WORK/src/lib/OpenEXRCore/libOpenEXRCore.a"
   "$WORK/src/lib/IlmThread/libIlmThread.a"
   "$WORK/src/lib/Iex/libIex.a"
   "$WORK/_deps/imath-build/src/Imath/libImath*.a"
diff --git a/projects/openexr/project.yaml b/projects/openexr/project.yaml
index 521e767..b4af565 100644
--- a/projects/openexr/project.yaml
+++ b/projects/openexr/project.yaml
@@ -4,4 +4,5 @@
 auto_ccs:
   - "cbpilm@gmail.com"
   - "security@openexr.org"
+  - "kdt3rd@gmail.com"
 main_repo: 'https://github.com/AcademySoftwareFoundation/openexr'
diff --git a/projects/openh264/Dockerfile b/projects/openh264/Dockerfile
index f7cc712..c32bdc8 100644
--- a/projects/openh264/Dockerfile
+++ b/projects/openh264/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && \
-    apt-get install -y libstdc++-5-dev libstdc++-5-dev:i386 nasm subversion
+    apt-get install -y libstdc++-9-dev libstdc++-9-dev:i386 nasm subversion
 RUN git clone --depth 1 https://github.com/cisco/openh264.git openh264
 WORKDIR openh264
 COPY build.sh decoder_fuzzer.cpp $SRC/
diff --git a/projects/opensc/project.yaml b/projects/opensc/project.yaml
index 79d794e..03360d8 100644
--- a/projects/opensc/project.yaml
+++ b/projects/opensc/project.yaml
@@ -8,4 +8,5 @@
   - "andreas.schwier@cardcontact.de"
   - "deengert@gmail.com"
   - "jakuje@gmail.com"
+  - "xhanulik@gmail.com"
 main_repo: 'https://github.com/OpenSC/OpenSC'
diff --git a/projects/opensips/Dockerfile b/projects/opensips/Dockerfile
new file mode 100755
index 0000000..c7b364a
--- /dev/null
+++ b/projects/opensips/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y bison flex libssl-dev pkg-config
+RUN git clone https://github.com/OpenSIPS/opensips
+
+COPY patch.diff $SRC/
+COPY build.sh $SRC/
+COPY fuzz_*.c $SRC/opensips/parser/
+
+WORKDIR opensips
diff --git a/projects/opensips/build.sh b/projects/opensips/build.sh
new file mode 100755
index 0000000..6dc94ea
--- /dev/null
+++ b/projects/opensips/build.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+git apply  --ignore-space-change --ignore-whitespace $SRC/patch.diff
+
+make static
+
+rm main.o
+mkdir objects && find . -name "*.o" -exec cp {} ./objects/ \;
+ar -r libopensips.a ./objects/*.o
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./parser/fuzz_msg_parser.o ./libopensips.a  -ldl -lresolv -o $OUT/fuzz_msg_parser
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./parser/fuzz_uri_parser.o ./libopensips.a  -ldl -lresolv -o $OUT/fuzz_uri_parser
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./parser/fuzz_csv_parser.o ./libopensips.a  -ldl -lresolv -o $OUT/fuzz_csv_parser
diff --git a/projects/opensips/fuzz_csv_parser.c b/projects/opensips/fuzz_csv_parser.c
new file mode 100644
index 0000000..8104881
--- /dev/null
+++ b/projects/opensips/fuzz_csv_parser.c
@@ -0,0 +1,54 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "../cachedb/test/test_cachedb.h"
+#include "../lib/test/test_csv.h"
+#include "../mem/test/test_malloc.h"
+#include "../str.h"
+#include "../ut.h"
+#include "../lib/csv.h"
+
+#include "../context.h"
+#include "../dprint.h"
+#include "../globals.h"
+#include "../lib/list.h"
+#include "../sr_module.h"
+#include "../sr_module_deps.h"
+
+int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+  // Ensure we have one byte for the "decider" variable
+  if (size == 0) {
+    return 0;
+  }
+  char *decider = *data;
+  data++;
+  size--;
+
+  ensure_global_context();
+  struct sip_uri u;
+
+  char *new_str = (char *)malloc(size + 1);
+  if (new_str == NULL) {
+    return 0;
+  }
+  memcpy(new_str, data, size);
+  new_str[size] = '\0';
+
+  csv_record *ret = NULL;
+  if (((int)decider % 2) == 0) {
+    ret = parse_csv_record(_str(new_str));
+  }
+  else {
+    ret = _parse_csv_record(_str(new_str), CSV_RFC_4180);
+  }
+  free_csv_record(ret);
+  free(new_str);
+}
diff --git a/projects/opensips/fuzz_msg_parser.c b/projects/opensips/fuzz_msg_parser.c
new file mode 100644
index 0000000..4daec42
--- /dev/null
+++ b/projects/opensips/fuzz_msg_parser.c
@@ -0,0 +1,41 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "../parser/sdp/sdp.h"
+
+#include "../cachedb/test/test_cachedb.h"
+#include "../lib/test/test_csv.h"
+#include "../mem/test/test_malloc.h"
+#include "../str.h"
+
+#include "../context.h"
+#include "../dprint.h"
+#include "../globals.h"
+#include "../lib/list.h"
+#include "../sr_module.h"
+#include "../sr_module_deps.h"
+
+int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+  ensure_global_context();
+  struct sip_uri u;
+
+  if (size <= 1) {
+    return 0;
+  }
+
+  struct sip_msg orig_inv = {};
+  orig_inv.buf = (char *)data;
+  orig_inv.len = size;
+
+  parse_msg(orig_inv.buf, orig_inv.len, &orig_inv);
+  free_sip_msg(&orig_inv);
+  return 0;
+}
diff --git a/projects/opensips/fuzz_uri_parser.c b/projects/opensips/fuzz_uri_parser.c
new file mode 100644
index 0000000..1a16474
--- /dev/null
+++ b/projects/opensips/fuzz_uri_parser.c
@@ -0,0 +1,40 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include "../cachedb/test/test_cachedb.h"
+#include "../lib/test/test_csv.h"
+#include "../mem/test/test_malloc.h"
+#include "../str.h"
+
+#include "../context.h"
+#include "../dprint.h"
+#include "../globals.h"
+#include "../lib/list.h"
+#include "../sr_module.h"
+#include "../sr_module_deps.h"
+
+#include "parse_uri.h"
+
+int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+  ensure_global_context();
+  struct sip_uri u;
+
+  char *new_str = (char *)malloc(size + 1);
+  if (new_str == NULL) {
+    return 0;
+  }
+  memcpy(new_str, data, size);
+  new_str[size] = '\0';
+
+  parse_uri(STR_L(new_str), &u);
+
+  free(new_str);
+}
diff --git a/projects/opensips/patch.diff b/projects/opensips/patch.diff
new file mode 100644
index 0000000..a382129
--- /dev/null
+++ b/projects/opensips/patch.diff
@@ -0,0 +1,57 @@
+diff --git a/Makefile.conf.template b/Makefile.conf.template
+index 5a76e0a35..2570db165 100644
+--- a/Makefile.conf.template
++++ b/Makefile.conf.template
+@@ -69,17 +69,19 @@ exclude_modules?= aaa_diameter aaa_radius auth_jwt b2b_logic_xml cachedb_cassand
+ 
+ include_modules?=
+ 
+-DEFS+= -DPKG_MALLOC #Use a faster malloc
+-DEFS+= -DSHM_MMAP #Use mmap instead of SYSV shared memory
+-DEFS+= -DUSE_MCAST #Compile in support for IP Multicast
++#DEFS+= -DPKG_MALLOC #Use a faster malloc
++#DEFS+= -DSHM_MMAP #Use mmap instead of SYSV shared memory
++#DEFS+= -DUSE_MCAST #Compile in support for IP Multicast
+ DEFS+= -DDISABLE_NAGLE #Disable the TCP NAgle Algorithm ( lower delay )
+ DEFS+= -DSTATISTICS #Enable the statistics manager
++DEFS+= -DSYSTEM_MALLOC
++DEFS+= -DSHM_MMAP
+ DEFS+= -DHAVE_RESOLV_RES #Support for changing some of the resolver parameters
+ # Specifying exactly 1 allocator will cause it to be inlined (fastest)
+-DEFS+= -DF_MALLOC #Fast memory allocator with minimal runtime overhead
+-DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks
+-DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking
+-DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors
++#DEFS+= -DF_MALLOC #Fast memory allocator with minimal runtime overhead
++#DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks
++#DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking
++#DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors
+ #DEFS+= -DNO_DEBUG #Compile out all debug messages
+ #DEFS+= -DNO_LOG #Compile out all logging
+ #DEFS_GROUP_START
+diff --git a/parser/msg_parser.c b/parser/msg_parser.c
+index db09aff7f..99ea58435 100644
+--- a/parser/msg_parser.c
++++ b/parser/msg_parser.c
+@@ -263,7 +263,7 @@ error_bad_hdr:
+ 	set_err_reply(400, "bad headers");
+ error:
+ 	LM_DBG("error exit\n");
+-	update_stat( bad_msg_hdr, 1);
++	//update_stat( bad_msg_hdr, 1);
+ 	hdr->type=HDR_ERROR_T;
+ 	hdr->len=tmp-hdr->name.s;
+ 	return tmp;
+diff --git a/parser/parse_uri.c b/parser/parse_uri.c
+index 364d91c1f..2f1ff1130 100644
+--- a/parser/parse_uri.c
++++ b/parser/parse_uri.c
+@@ -1628,7 +1628,7 @@ error_bug:
+ error_exit:
+ 	ser_error=E_BAD_URI;
+ 	uri->type=ERROR_URI_T;
+-	update_stat(bad_URIs, 1);
++	//update_stat(bad_URIs, 1);
+ 	return E_BAD_URI;
+ }
+ 
diff --git a/projects/opensips/project.yaml b/projects/opensips/project.yaml
new file mode 100755
index 0000000..a4e1184
--- /dev/null
+++ b/projects/opensips/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://opensips.org/"
+main_repo: "https://github.com/OpenSIPS/opensips"
+primary_contact: "liviu@opensips.org"
+language: c
+auto_ccs:
+  - "david@adalogics.com"
+  - "liviu.chircu@gmail.com"
+  - "bogdan.andrei.iancu@gmail.com"
+  - "rvlad.patrascu@gmail.com"
+  - "razvan.crainea@gmail.com"
diff --git a/projects/opensk/Dockerfile b/projects/opensk/Dockerfile
new file mode 100644
index 0000000..b9b9810
--- /dev/null
+++ b/projects/opensk/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+RUN apt-get update && apt-get install -y make autoconf automake libtool curl \
+    cmake python llvm-dev libclang-dev clang uuid-runtime pkg-config libssl-dev
+
+RUN git clone --depth=1 --branch=develop https://github.com/google/OpenSK  && \
+    cd OpenSK && \
+    ./setup.sh && \
+    ./fuzzing_setup.sh
+
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/opensk/build.sh b/projects/opensk/build.sh
new file mode 100755
index 0000000..4d25209
--- /dev/null
+++ b/projects/opensk/build.sh
@@ -0,0 +1,40 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FUZZ_TARGET_OUTPUT_DIR=fuzz/target/x86_64-unknown-linux-gnu/release
+
+build_and_copy() {
+  pushd "$1"
+  cargo +nightly fuzz build --release --debug-assertions
+  for f in fuzz/fuzz_targets/*.rs
+  do
+    cp ${FUZZ_TARGET_OUTPUT_DIR}/$(basename ${f%.*}) $OUT/
+  done
+  popd
+}
+
+cd OpenSK
+
+# Main OpenSK fuzzing targets
+build_and_copy "."
+
+# persistent storage library
+build_and_copy libraries/persistent_store
+
+# CBOR crate
+build_and_copy libraries/cbor
+
diff --git a/projects/opensk/project.yaml b/projects/opensk/project.yaml
new file mode 100644
index 0000000..65f7a76
--- /dev/null
+++ b/projects/opensk/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/google/OpenSK"
+main_repo: "https://github.com/google/OpenSK"
+primary_contact: "opensk@google.com"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "jmichel@google.com"
+  - "kaczmarczyck@google.com"
+  - "cretin@google.com"
+  - "david@adalogics.com"
diff --git a/projects/openssh/Dockerfile b/projects/openssh/Dockerfile
index 929d57c..e2cf257 100644
--- a/projects/openssh/Dockerfile
+++ b/projects/openssh/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y make autoconf automake libtool
-RUN apt-get install -y libz-dev libssl1.0.0 libssl-dev libedit-dev zip
+RUN apt-get install -y libz-dev libssl1.1 libssl-dev libedit-dev zip
 RUN git clone --depth 1 https://github.com/openssh/openssh-portable openssh
 RUN git clone --depth 1 https://github.com/djmdjm/openssh-fuzz-cases
 WORKDIR openssh
diff --git a/projects/openssh/project.yaml b/projects/openssh/project.yaml
index 53ac442..3bf759f 100644
--- a/projects/openssh/project.yaml
+++ b/projects/openssh/project.yaml
@@ -2,6 +2,6 @@
 language: c++
 primary_contact: "djm@mindrot.org"
 auto_ccs:
-        - "dtucker@dtucker.net.au"
+        - "dtucker@dtucker.net"
         - "djm@google.com"
 main_repo: 'https://github.com/openssh/openssh-portable'
diff --git a/projects/openthread/project.yaml b/projects/openthread/project.yaml
index c772d3b..5d93c49 100644
--- a/projects/openthread/project.yaml
+++ b/projects/openthread/project.yaml
@@ -8,5 +8,4 @@
 sanitizers:
   - address
   - undefined
-  - dataflow
 main_repo: 'https://github.com/openthread/openthread'
diff --git a/projects/openvpn/Dockerfile b/projects/openvpn/Dockerfile
new file mode 100644
index 0000000..24397ae
--- /dev/null
+++ b/projects/openvpn/Dockerfile
@@ -0,0 +1,28 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool libssl-dev liblzo2-dev libpam-dev 
+
+RUN git clone --depth 1 https://github.com/google/boringssl.git boringssl
+RUN git clone https://github.com/OpenVPN/openvpn openvpn
+WORKDIR openvpn
+COPY build.sh $SRC/
+COPY fuzz*.cpp $SRC/
+COPY fuzz*.c $SRC/
+COPY fuzz*.h $SRC/openvpn/src/openvpn/
+
+COPY crypto_patch.txt $SRC/crypto_patch.txt
diff --git a/projects/openvpn/build.sh b/projects/openvpn/build.sh
new file mode 100755
index 0000000..f83f6b9
--- /dev/null
+++ b/projects/openvpn/build.sh
@@ -0,0 +1,83 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+BASE=${SRC}/openvpn/src/openvpn
+
+apply_sed_changes() {
+  sed -i 's/read(/fuzz_read(/g' ${BASE}/console_systemd.c
+  sed -i 's/fgets(/fuzz_fgets(/g' ${BASE}/console_builtin.c
+  sed -i 's/fgets(/fuzz_fgets(/g' ${BASE}/misc.c
+  sed -i 's/#include "forward.h"/#include "fuzz_header.h"\n#include "forward.h"/g' ${BASE}/proxy.c
+  sed -i 's/select(/fuzz_select(/g' ${BASE}/proxy.c
+  sed -i 's/send(/fuzz_send(/g' ${BASE}/proxy.c
+  sed -i 's/recv(/fuzz_recv(/g' ${BASE}/proxy.c
+  sed -i 's/isatty/fuzz_isatty/g' ${BASE}/console_builtin.c
+
+  sed -i 's/fopen/fuzz_fopen/g' ${BASE}/console_builtin.c
+  sed -i 's/fclose/fuzz_fclose/g' ${BASE}/console_builtin.c
+
+  sed -i 's/sendto/fuzz_sendto/g' ${BASE}/socket.h
+  sed -i 's/#include "misc.h"/#include "misc.h"\nextern size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen);/g' ${BASE}/socket.h
+
+  sed -i 's/fp = (flags/fp = stdout;\n\/\//g' ${BASE}/error.c
+
+  sed -i 's/crypto_msg(M_FATAL/crypto_msg(M_WARN/g' ${BASE}/crypto_openssl.c
+  sed -i 's/msg(M_FATAL, \"Cipher/return;msg(M_FATAL, \"Cipher/g' ${BASE}/crypto.c
+  sed -i 's/msg(M_FATAL/msg(M_WARN/g' ${BASE}/crypto.c
+
+  sed -i 's/= write/= fuzz_write/g' ${BASE}/packet_id.c
+}
+
+# Changes in the code so we can fuzz it.
+git apply $SRC/crypto_patch.txt
+
+echo "" >> ${BASE}/openvpn.c
+echo "#include \"fake_fuzz_header.h\"" >> ${BASE}/openvpn.c
+echo "ssize_t fuzz_get_random_data(void *buf, size_t len) { return 0; }" >> ${BASE}/fake_fuzz_header.h
+echo "int fuzz_success;" >> ${BASE}/fake_fuzz_header.h
+
+# Apply hooking changes
+apply_sed_changes
+
+# Copy corpuses out
+zip -r $OUT/fuzz_verify_cert_seed_corpus.zip $SRC/boringssl/fuzz/cert_corpus
+
+# Build openvpn
+autoreconf -ivf
+./configure --disable-lz4 --with-crypto-library=openssl OPENSSL_LIBS="-L/usr/local/ssl/ -lssl -lcrypto" OPENSSL_CFLAGS="-I/usr/local/ssl/include/"
+make
+
+# Make openvpn object files into a library we can link fuzzers to
+cd src/openvpn
+rm openvpn.o
+ar r libopenvpn.a *.o
+
+# Compile our fuzz helper
+$CXX $CXXFLAGS -g -c $SRC/fuzz_randomizer.cpp -o $SRC/fuzz_randomizer.o
+
+# Compile the fuzzers
+for fuzzname in dhcp misc base64 proxy buffer route packet_id mroute list verify_cert forward crypto; do
+    $CC -DHAVE_CONFIG_H -I. -I../.. -I../../include -I../../src/compat \
+      -DPLUGIN_LIBDIR=\"/usr/local/lib/openvpn/plugins\" -std=c99 $CFLAGS \
+      -c $SRC/fuzz_${fuzzname}.c -o $SRC/fuzz_${fuzzname}.o
+
+    # Link with CXX
+    $CXX ${CXXFLAGS} ${LIB_FUZZING_ENGINE} $SRC/fuzz_${fuzzname}.o -o $OUT/fuzz_${fuzzname} $SRC/fuzz_randomizer.o \
+        libopenvpn.a ../../src/compat/.libs/libcompat.a /usr/lib/x86_64-linux-gnu/libnsl.a \
+        /usr/lib/x86_64-linux-gnu/libresolv.a /usr/lib/x86_64-linux-gnu/liblzo2.a \
+        -lssl -lcrypto -ldl
+done
diff --git a/projects/openvpn/crypto_patch.txt b/projects/openvpn/crypto_patch.txt
new file mode 100644
index 0000000..8caedaf
--- /dev/null
+++ b/projects/openvpn/crypto_patch.txt
@@ -0,0 +1,109 @@
+diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
+index b9c95225..7adff4bb 100644
+--- a/src/openvpn/crypto.c
++++ b/src/openvpn/crypto.c
+@@ -133,7 +133,10 @@ openvpn_encrypt_aead(struct buffer *buf, struct buffer work,
+     ASSERT(buf_inc_len(&work, outlen));
+ 
+     /* Flush the encryption buffer */
+-    ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
++    //ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
++    if (!(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen))) {
++      goto err;
++    }
+     ASSERT(buf_inc_len(&work, outlen));
+ 
+     /* Write authentication tag */
+@@ -737,6 +740,7 @@ warn_insecure_key_type(const char *ciphername, const cipher_kt_t *cipher)
+ /*
+  * Build a struct key_type.
+  */
++extern int fuzz_success;
+ void
+ init_key_type(struct key_type *kt, const char *ciphername,
+               const char *authname, bool tls_mode, bool warn)
+@@ -752,6 +756,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+         kt->cipher = cipher_kt_get(ciphername);
+         if (!kt->cipher)
+         {
++            fuzz_success = 0;
+             msg(M_FATAL, "Cipher %s not supported", ciphername);
+         }
+ 
+@@ -766,11 +771,13 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ #endif
+               ))
+         {
++            fuzz_success = 0;
+             msg(M_FATAL, "Cipher '%s' mode not supported", ciphername);
+         }
+ 
+         if (OPENVPN_MAX_CIPHER_BLOCK_SIZE < cipher_kt_block_size(kt->cipher))
+         {
++            fuzz_success = 0;
+             msg(M_FATAL, "Cipher '%s' not allowed: block size too big.", ciphername);
+         }
+         if (warn)
+@@ -782,6 +789,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+     {
+         if (warn)
+         {
++            fuzz_success = 0;
+             msg(M_WARN, "******* WARNING *******: '--cipher none' was specified. "
+                 "This means NO encryption will be performed and tunnelled "
+                 "data WILL be transmitted in clear text over the network! "
+@@ -797,6 +805,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ 
+             if (OPENVPN_MAX_HMAC_SIZE < kt->hmac_length)
+             {
++                fuzz_success = 0;
+                 msg(M_FATAL, "HMAC '%s' not allowed: digest size too big.", authname);
+             }
+         }
+@@ -805,6 +814,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+     {
+         if (warn)
+         {
++            fuzz_success = 0;
+             msg(M_WARN, "******* WARNING *******: '--auth none' was specified. "
+                 "This means no authentication will be performed on received "
+                 "packets, meaning you CANNOT trust that the data received by "
+@@ -812,6 +822,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+                 "PLEASE DO RECONSIDER THIS SETTING!");
+         }
+     }
++            fuzz_success = 1;
+ }
+ 
+ /* given a key and key_type, build a key_ctx */
+@@ -1037,6 +1048,7 @@ generate_key_random(struct key *key, const struct key_type *kt)
+         if (!rand_bytes(key->cipher, cipher_len)
+             || !rand_bytes(key->hmac, hmac_len))
+         {
++          fuzz_success = 0;
+             msg(M_FATAL, "ERROR: Random number generator cannot obtain entropy for key generation");
+         }
+ 
+@@ -1050,6 +1062,7 @@ generate_key_random(struct key *key, const struct key_type *kt)
+     } while (kt && !check_key(key, kt));
+ 
+     gc_free(&gc);
++    fuzz_success = 1;
+ }
+ 
+ /*
+@@ -1390,10 +1403,14 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags)
+ 
+         if (state != PARSE_FINISHED)
+         {
++          fuzz_success = 0;
+             msg(M_FATAL, "Footer text not found in file '%s' (%d/%d/%d bytes found/min/max)",
+                 print_key_filename(file, flags & RKF_INLINE), count, onekeylen,
+                 keylen);
+         }
++        else {
++          fuzz_success = 1;
++        }
+     }
+ 
+     /* zero file read buffer if not an inline file */
diff --git a/projects/openvpn/fuzz.h b/projects/openvpn/fuzz.h
new file mode 100644
index 0000000..10e33c3
--- /dev/null
+++ b/projects/openvpn/fuzz.h
@@ -0,0 +1,47 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+// Returns a NULL-terminated C string that should be freed by the caller.
+char *get_modifiable_string(FuzzedDataProvider &provider) {
+  std::string s1 = provider.ConsumeRandomLengthString();
+  char *tmp = (char *)malloc(s1.size() + 1);
+  memcpy(tmp, s1.c_str(), s1.size());
+  tmp[s1.size()] = '\0';
+  return tmp;
+}
+
+FuzzedDataProvider *prov = NULL;
+
+
+extern "C" ssize_t fuzz_get_random_data(void *buf, size_t len) {
+  size_t ret_val;
+  char *cbuf = (char*)buf;
+
+  if (prov->remaining_bytes() == 0) {
+    return -1;
+  }
+
+  double prob = prov->ConsumeProbability<double>();
+  if (prob < 0.05) {
+    return 0;
+  }
+
+  if (len == 1) {
+    ret_val = prov->ConsumeData(buf, 1);
+    return ret_val;
+  }
+  ret_val = prov->ConsumeData(buf, len);
+  return ret_val;
+}
+
diff --git a/projects/openvpn/fuzz_base64.c b/projects/openvpn/fuzz_base64.c
new file mode 100644
index 0000000..c9c45b8
--- /dev/null
+++ b/projects/openvpn/fuzz_base64.c
@@ -0,0 +1,43 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base64.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size > 500) {
+    return 0;
+  }
+
+  char *new_str = (char *)malloc(size + 1);
+  if (new_str == NULL) {
+    return 0;
+  }
+  memcpy(new_str, data, size);
+  new_str[size] = '\0';
+
+  char *str = NULL;
+  openvpn_base64_encode(data, size, &str);
+  if(str != NULL) {
+    free(str);
+  }
+
+  uint16_t outsize = 10000;
+  char *output_buf = (char *)malloc(outsize);
+  openvpn_base64_decode(new_str, output_buf, outsize);
+  free(output_buf);
+
+  free(new_str);
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_buffer.c b/projects/openvpn/fuzz_buffer.c
new file mode 100644
index 0000000..af114ec
--- /dev/null
+++ b/projects/openvpn/fuzz_buffer.c
@@ -0,0 +1,266 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#include "config.h"
+#include "syshead.h"
+#include "misc.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data,size);
+
+  struct gc_arena gc;
+  struct buffer *bufp;
+  struct buffer buf, buf2;
+  struct buffer_list *buflistp = NULL;
+  ssize_t generic_ssizet, _size;
+  char *tmp;
+  char *tmp2;
+  char match;
+
+  gc = gc_new();
+  bufp = NULL;
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+  for (int i = 0; i < total_to_fuzz; i++) {
+    if (bufp == NULL) {
+      generic_ssizet = fuzz_randomizer_get_int(0, 1);
+      if (generic_ssizet == 0) {
+        _size = fuzz_randomizer_get_int(0, 100);
+        buf = alloc_buf_gc(_size, &gc);
+        bufp = &buf;
+      } else {
+        tmp = get_random_string();
+        buf = string_alloc_buf(tmp, &gc);
+        bufp = &buf;
+        free(tmp);
+        tmp = NULL;
+      }
+    } else {
+#define NUM_TARGETS 32
+      generic_ssizet = fuzz_randomizer_get_int(0, NUM_TARGETS);
+      switch (generic_ssizet) {
+      case 0:
+        buf_clear(bufp);
+        break;
+      case 1:
+        buf2 = clone_buf(bufp);
+        free_buf(&buf2);
+        break;
+      case 2:
+        buf_defined(bufp);
+        break;
+      case 3:
+        buf_valid(bufp);
+        break;
+      case 4:
+        buf_bptr(bufp);
+        break;
+      case 5:
+        buf_len(bufp);
+        break;
+      case 6:
+        buf_bend(bufp);
+        break;
+      case 7:
+        buf_blast(bufp);
+        break;
+      case 8:
+        buf_str(bufp);
+        break;
+      case 9:
+        generic_ssizet = fuzz_randomizer_get_int(0, 255);
+        buf_rmtail(bufp, (uint8_t)generic_ssizet);
+        break;
+      case 10:
+        buf_chomp(bufp);
+        break;
+      case 11:
+        tmp = get_random_string();
+        skip_leading_whitespace(tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 12:
+        tmp = get_random_string();
+        chomp(tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 13:
+        tmp = get_random_string();
+        tmp2 = get_random_string();
+        rm_trailing_chars(tmp, tmp2);
+        free(tmp);
+        free(tmp2);
+        tmp = NULL;
+        tmp2 = NULL;
+        break;
+      case 14:
+        tmp = get_random_string();
+        string_clear(tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 15:
+        tmp = get_random_string();
+        buf_string_match_head_str(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 16:
+        tmp = get_random_string();
+        buf_string_compare_advance(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 17:
+        generic_ssizet = fuzz_randomizer_get_int(0, 255);
+
+        tmp = get_random_string();
+        if (strlen(tmp) > 0) {
+          buf_parse(bufp, (int)generic_ssizet, tmp, strlen(tmp));
+        }
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 18:
+        tmp = get_random_string();
+        string_mod(tmp, fuzz_randomizer_get_int(0, 12312),
+                   fuzz_randomizer_get_int(0, 23141234),
+                   (char)fuzz_randomizer_get_int(0, 255));
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 19:
+        tmp = get_random_string();
+        match = (char)fuzz_randomizer_get_int(0, 255);
+        if (match != 0) {
+          string_replace_leading(tmp, match, (char)fuzz_randomizer_get_int(0, 255));
+        }
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 20:
+        tmp = get_random_string();
+        buf_write(bufp, tmp, strlen(tmp));
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 21:
+        tmp = get_random_string();
+
+        buf_write_prepend(bufp, tmp, strlen(tmp));
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 22:
+        buf_write_u8(bufp, fuzz_randomizer_get_int(0, 255));
+        break;
+      case 23:
+        buf_write_u16(bufp, fuzz_randomizer_get_int(0, 1024));
+        break;
+      case 24:
+        buf_write_u32(bufp, fuzz_randomizer_get_int(0, 12312));
+        break;
+      case 25:
+        tmp = get_random_string();
+        buf_catrunc(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 26:
+        convert_to_one_line(bufp);
+        break;
+      case 27:
+        buf_advance(bufp, fuzz_randomizer_get_int(0, 25523));
+        break;
+      case 28:
+        buf_prepend(bufp, fuzz_randomizer_get_int(0, 251235));
+        break;
+      case 29:
+        buf_reverse_capacity(bufp);
+        break;
+      case 30:
+        buf_forward_capacity_total(bufp);
+        break;
+      case 31:
+        buf_forward_capacity(bufp);
+        break;
+      case 32:
+        tmp = get_random_string();
+        buf_puts(bufp, tmp);
+        free(tmp);
+        tmp = NULL;
+        break;
+      }
+    }
+
+    if (buflistp == NULL) {
+      buflistp = buffer_list_new(fuzz_randomizer_get_int(0, 200));
+    } else {
+#define NUM_LIST_TARGETS 6
+      generic_ssizet = fuzz_randomizer_get_int(0, NUM_LIST_TARGETS);
+      switch (generic_ssizet) {
+      case 0:
+        buffer_list_free(buflistp);
+        buflistp = NULL;
+        break;
+      case 1:
+        buffer_list_defined(buflistp);
+        break;
+      case 2:
+        tmp = get_random_string();
+        if (strlen(tmp) < BUF_SIZE_MAX) {
+          buffer_list_push(buflistp, tmp);
+        }
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 3:
+        buffer_list_peek(buflistp);
+        break;
+      case 4:
+        buffer_list_pop(buflistp);
+        break;
+      case 5:
+        tmp = get_random_string();
+        buffer_list_aggregate_separator(
+            buflistp, fuzz_randomizer_get_int(0, 1024), tmp);
+
+        free(tmp);
+        tmp = NULL;
+        break;
+      case 6:
+        buffer_list_aggregate(buflistp,
+                              fuzz_randomizer_get_int(0, 1024));
+        break;
+      }
+    }
+  }
+
+  // Cleanup
+  buffer_list_free(buflistp);
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_crypto.c b/projects/openvpn/fuzz_crypto.c
new file mode 100644
index 0000000..e9a851b
--- /dev/null
+++ b/projects/openvpn/fuzz_crypto.c
@@ -0,0 +1,257 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#include "config.h"
+#include "syshead.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "fuzz_verify_cert.h"
+#include "misc.h"
+#include "manage.h"
+#include "otime.h"
+#include "base64.h"
+#include "ssl_verify.h"
+#include "ssl_verify_backend.h"
+
+#include "fuzz_randomizer.h"
+
+static void key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key,
+                                       size_t key_len) {
+  const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
+
+  /* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
+  if (cipher_kt_mode_aead(cipher_kt)) {
+    size_t impl_iv_len = 0;
+    ASSERT(cipher_kt_iv_size(cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN);
+    impl_iv_len = cipher_kt_iv_size(cipher_kt) - sizeof(packet_id_type);
+    ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
+    ASSERT(impl_iv_len <= key_len);
+    memcpy(ctx->implicit_iv, key, impl_iv_len);
+    ctx->implicit_iv_len = impl_iv_len;
+  }
+}
+
+static int init_frame(struct frame *frame) {
+  frame->link_mtu = fuzz_randomizer_get_int(100, 1000);
+  frame->extra_buffer = fuzz_randomizer_get_int(100, 1000);
+  frame->link_mtu_dynamic = fuzz_randomizer_get_int(100, 1000);
+  frame->extra_frame = fuzz_randomizer_get_int(100, 1000);
+  frame->extra_tun = fuzz_randomizer_get_int(100, 1000);
+  frame->extra_link = fuzz_randomizer_get_int(100, 1000);
+  frame->align_flags = 0;
+  frame->align_adjust = 0;
+  if (TUN_MTU_SIZE(frame) <= 0) {
+    return -1;
+  }
+  return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  OPENSSL_malloc_init();
+  SSL_library_init();
+  ERR_load_crypto_strings();
+
+  OpenSSL_add_all_algorithms();
+  OpenSSL_add_ssl_algorithms();
+
+  SSL_load_error_strings();
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+  fuzz_success = 1;
+  bool key_ctx_dec_initialized = false;
+  bool key_ctx_enc_initialized = false;
+  struct key_ctx key_ctx_dec;
+  memset(&key_ctx_dec, 0, sizeof(struct key_ctx));
+  struct key_ctx key_ctx_enc;
+  memset(&key_ctx_enc, 0, sizeof(struct key_ctx));
+
+  struct gc_arena gc;
+  struct tls_session *session = NULL;
+  X509 *x509 = NULL;
+  gc = gc_new();
+
+  gb_init();
+
+  // Read key file
+  struct key2 key2;
+  char *keydata = gb_get_random_string();
+  read_key_file(&key2, keydata, RKF_INLINE);
+
+  // init key type
+  struct key_type kt;
+  memset(&kt, 0, sizeof(struct key_type));
+
+  char *ciphername = gb_get_random_string();
+  char *authname = gb_get_random_string();
+  bool key_type_initialized = false;
+
+  if (strcmp(ciphername, "AES-256-GCM") == 0 ||
+      strcmp(ciphername, "AES-128-GCM") == 0 ||
+      strcmp(ciphername, "AES-192-GCM") == 0 ||
+      strcmp(ciphername, "CAMELLIA-128-CFB128") == 0) {
+
+    int v = fuzz_randomizer_get_int(0, 1);
+    if (v == 0) {
+      init_key_type(&kt, ciphername, authname, true, 0);
+    } else {
+      init_key_type(&kt, ciphername, authname, false, 0);
+    }
+    key_type_initialized = true;
+  }
+
+  if (fuzz_success == 0) {
+    goto cleanup;
+  }
+
+  // Generate key.
+  // Identify which one we should do, read or generate a random key.
+  int c = fuzz_randomizer_get_int(0, 1);
+  const uint8_t d[1024];
+  int key_read = 0;
+  struct key key;
+  if (c == 0) {
+    if (fuzz_get_random_data(d, 1024) != 1024) {
+      struct buffer buf = alloc_buf(1024);
+      buf_write(&buf, d, 1024);
+      if (read_key(&key, &kt, &buf) == 1) {
+        key_read = 1;
+      }
+      free_buf(&buf);
+    }
+  }
+  else {
+    if (key_type_initialized == true) {
+      generate_key_random(&key, &kt);
+    }
+  }
+
+  if (fuzz_success == 0) {
+    goto cleanup;
+  }
+  key_read = 1;
+
+  // init decryption context
+  if (key_type_initialized && key_read) {
+    init_key_ctx(&key_ctx_dec, &key, &kt, OPENVPN_OP_DECRYPT, "x");
+    key_ctx_update_implicit_iv(&key_ctx_dec, &(key.hmac), MAX_HMAC_KEY_LENGTH);
+    key_ctx_dec_initialized = true;
+  }
+
+  // init encryption context
+  if (key_type_initialized && key_read) {
+    init_key_ctx(&key_ctx_enc, &key, &kt, OPENVPN_OP_DECRYPT, "x");
+    key_ctx_update_implicit_iv(&key_ctx_enc, &(key.hmac), MAX_HMAC_KEY_LENGTH);
+    key_ctx_enc_initialized = true;
+  }
+
+  // perform encryption
+  struct frame frame;
+  memset(&frame, 0, sizeof(struct frame));
+  if (key_ctx_enc_initialized == true && key_ctx_dec_initialized == true &&
+      init_frame(&frame) == 0) {
+    struct crypto_options opt;
+    memset(&opt, 0, sizeof(opt));
+    opt.pid_persist = NULL;
+    opt.key_ctx_bi.encrypt = key_ctx_enc;
+    opt.key_ctx_bi.decrypt = key_ctx_dec;
+    opt.key_ctx_bi.initialized = true;
+    opt.packet_id.rec.initialized = true;
+    opt.packet_id.rec.seq_list = NULL;
+    opt.packet_id.rec.name = NULL;
+
+    void *buf_p;
+
+    struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+    struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+    struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
+    struct buffer buf = clear_buf();
+
+    int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
+
+    ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
+    ASSERT(buf_init(&src, 0));
+    src.len = x;
+    ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
+
+    buf = work;
+    buf_p = buf_write_alloc(&buf, BLEN(&src));
+    ASSERT(buf_p);
+    memcpy(buf_p, BPTR(&src), BLEN(&src));
+
+    ASSERT(buf_init(&encrypt_workspace, FRAME_HEADROOM(&(frame))));
+
+    openvpn_encrypt(&buf, encrypt_workspace, &opt);
+  }
+
+  // perform decryption
+  memset(&frame, 0, sizeof(struct frame));
+  if (key_ctx_dec_initialized == true && key_ctx_enc_initialized == true &&
+      init_frame(&frame) == 0) {
+    struct crypto_options opt;
+    memset(&opt, 0, sizeof(opt));
+    opt.pid_persist = NULL;
+    opt.key_ctx_bi.encrypt = key_ctx_enc;
+    opt.key_ctx_bi.decrypt = key_ctx_dec;
+    opt.key_ctx_bi.initialized = true;
+    opt.packet_id.rec.initialized = true;
+    opt.packet_id.rec.seq_list = NULL;
+    opt.packet_id.rec.name = NULL;
+
+    void *buf_p;
+
+    struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+    struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+    struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
+    struct buffer buf = clear_buf();
+
+    int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
+
+    ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
+    ASSERT(buf_init(&src, 0));
+    src.len = x;
+    ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
+
+    buf = work;
+    buf_p = buf_write_alloc(&buf, BLEN(&src));
+    ASSERT(buf_p);
+    memcpy(buf_p, BPTR(&src), BLEN(&src));
+
+    ASSERT(buf_init(&decrypt_workspace, FRAME_HEADROOM(&(frame))));
+    
+    openvpn_decrypt(&buf, decrypt_workspace, &opt, &frame, BPTR(&buf));
+  }
+
+cleanup:
+  // cleanup
+  gc_free(&gc);
+
+  if (key_ctx_dec_initialized == true) {
+    free_key_ctx(&key_ctx_dec);
+  }
+
+  if (key_ctx_enc_initialized == true) {
+    free_key_ctx(&key_ctx_enc);
+  }
+  fuzz_random_destroy();
+
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_dhcp.c b/projects/openvpn/fuzz_dhcp.c
new file mode 100644
index 0000000..1368ac2
--- /dev/null
+++ b/projects/openvpn/fuzz_dhcp.c
@@ -0,0 +1,37 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "dhcp.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  struct buffer ipbuf;
+  in_addr_t ret;
+
+  fuzz_random_init(data, size);
+  char *ran_val = get_random_string();
+
+  ipbuf = alloc_buf(strlen(ran_val));
+  if (buf_write(&ipbuf, ran_val, strlen(ran_val)) != false) {
+    ret = dhcp_extract_router_msg(&ipbuf);
+  }
+  free_buf(&ipbuf);
+
+  fuzz_random_destroy();
+  free(ran_val);
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_forward.c b/projects/openvpn/fuzz_forward.c
new file mode 100644
index 0000000..dff3e93
--- /dev/null
+++ b/projects/openvpn/fuzz_forward.c
@@ -0,0 +1,228 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include <sys/time.h>
+#include "syshead.h"
+#include "interval.h"
+#include "init.h"
+#include "buffer.h"
+#include "forward.h"
+
+#include "fuzz_randomizer.h"
+
+
+static int init_c2_outgoing_link(struct context_2 *c2, struct gc_arena *gc) {
+  struct link_socket_actual *to_link_addr = NULL;
+  struct link_socket *link_socket = NULL;
+  struct socks_proxy_info *socks_proxy = NULL;
+  struct buffer buf;
+
+  c2->tun_write_bytes = 0;
+  ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc);
+  memset(link_socket, 0, sizeof(*link_socket));
+
+  c2->link_socket = link_socket;
+
+  if (fuzz_randomizer_get_int(0, 2) != 0) {
+    c2->link_socket->info.proto = PROTO_UDP;
+  } else {
+    c2->link_socket->info.proto = PROTO_TCP_SERVER;
+  }
+
+  ALLOC_ARRAY_GC(socks_proxy, struct socks_proxy_info, 1, gc);
+  memset(socks_proxy, 0, sizeof(*socks_proxy));
+  c2->link_socket->socks_proxy = socks_proxy;
+
+  c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff);
+  c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff);
+  c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff);
+  c2->frame.link_mtu = fuzz_randomizer_get_int(0, 0xfffffff);
+
+  ALLOC_ARRAY_GC(to_link_addr, struct link_socket_actual, 1, gc);
+  memset(to_link_addr, 0, sizeof(*to_link_addr));
+  c2->to_link_addr = to_link_addr;
+
+  c2->to_link_addr->dest.addr.sa.sa_family = AF_INET;
+  c2->to_link_addr->dest.addr.in4.sin_addr.s_addr = 1;
+
+  char *tmp = get_random_string();
+  buf = alloc_buf_gc(strlen(tmp), gc);
+  buf_write(&buf, tmp, strlen(tmp));
+  int val = fuzz_randomizer_get_int(0, strlen(tmp));
+  buf.offset = val;
+  free(tmp);
+
+  c2->link_socket->stream_buf.maxlen = BLEN(&buf);
+  c2->to_link = buf;
+
+  if (buf.offset < 10) {
+    return -1;
+  }
+  return 0;
+}
+
+void fuzz_process_outgoing_link(const uint8_t *data, size_t size) {
+  struct context ctx;
+  struct gc_arena gc = gc_new();
+  memset(&ctx, 0, sizeof(ctx));
+
+  if (init_c2_outgoing_link(&ctx.c2, &gc) == 0) {
+    process_outgoing_link(&ctx);
+  }
+
+  gc_free(&gc);
+}
+
+static int _init_options(struct options *options, struct client_nat_entry **cne,
+                         struct gc_arena *gc) {
+  options->passtos = false;
+  options->mode = MODE_POINT_TO_POINT;
+  options->allow_recursive_routing = true;
+  options->client_nat = new_client_nat_list(gc);
+
+  struct client_nat_entry *_cne;
+  ALLOC_ARRAY_GC(cne[0], struct client_nat_entry, 1, gc);
+  _cne = cne[0];
+  memset(_cne, 0, sizeof(struct client_nat_entry));
+
+  struct client_nat_option_list clist;
+  clist.n = 1;
+  clist.entries[0] = *_cne;
+  copy_client_nat_option_list(options->client_nat, &clist);
+  options->route_gateway_via_dhcp = false;
+
+  return 0;
+}
+
+static int init_c2_incoming_tun(struct context_2 *c2, struct gc_arena *gc) {
+  struct buffer buf;
+  memset(&buf, 0, sizeof(buf));
+
+  struct link_socket *link_socket = NULL;
+  ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc);
+  c2->link_socket = link_socket;
+
+  ALLOC_OBJ_GC(c2->link_socket_info, struct link_socket_info, gc);
+  ALLOC_OBJ_GC(c2->link_socket_info->lsa, struct link_socket_addr, gc);
+  c2->link_socket_info->lsa->bind_local = NULL;
+  c2->link_socket_info->lsa->remote_list = NULL;
+  c2->link_socket_info->lsa->current_remote = NULL;
+  c2->link_socket_info->lsa->remote_list = NULL;
+  c2->es = env_set_create(gc);
+
+  c2->frame.link_mtu_dynamic = 0;
+  c2->frame.extra_frame = 0;
+  c2->frame.extra_tun = 0;
+  c2->to_link_addr = NULL;
+
+  char *tmp = get_random_string();
+  buf = alloc_buf(strlen(tmp));
+  buf_write(&buf, tmp, strlen(tmp));
+
+  int retval;
+  if (strlen(tmp) > 5) {
+    retval = 0;
+  } else {
+    retval = 1;
+  }
+
+  free(tmp);
+
+  c2->buf = buf;
+  c2->buffers = init_context_buffers(&c2->frame);
+  c2->log_rw = false;
+
+  return retval;
+}
+
+int run_process_incoming_tun(const uint8_t *data, size_t size) {
+  struct gc_arena gc;
+  struct context ctx;
+  struct client_nat_entry *cne[MAX_CLIENT_NAT];
+  struct route_list route_list;
+
+  memset(&ctx, 0, sizeof(ctx));
+  memset(cne, 0, sizeof(cne));
+
+  gc = gc_new();
+
+  _init_options(&ctx.options, cne, &gc);
+
+  // Init tuntap
+  struct tuntap tuntap;
+  tuntap.type = DEV_TYPE_TAP;
+
+  ctx.c1.tuntap = &tuntap;
+
+  int retval = init_c2_incoming_tun(&ctx.c2, &gc);
+  ctx.c1.route_list = &route_list;
+  if (retval == 0) {
+    process_incoming_tun(&ctx);
+  }
+
+  free(ctx.c2.buf.data);
+  free_context_buffers(ctx.c2.buffers);
+  gc_free(&gc);
+}
+
+static int init_c2_outgoing_tun(struct context_2 *c2, struct gc_arena *gc) {
+  struct buffer buf;
+
+  c2->tun_write_bytes = 0;
+  c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff);
+  c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff);
+  c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff);
+
+  char *tmp = get_random_string();
+  buf = alloc_buf_gc(strlen(tmp), gc);
+  buf_write(&buf, tmp, strlen(tmp));
+  free(tmp);
+
+  c2->to_tun = buf;
+  return 0;
+}
+
+void run_process_outgoing_tun(uint8_t *data, size_t size) {
+  struct gc_arena gc;
+  struct context ctx;
+  struct tuntap tuntap;
+
+  memset(&ctx, 0, sizeof(ctx));
+  gc = gc_new();
+
+  tuntap.type = DEV_TYPE_TAP;
+  ctx.c1.tuntap = &tuntap;
+
+  init_c2_outgoing_tun(&ctx.c2, &gc);
+  process_outgoing_tun(&ctx);
+
+  gc_free(&gc);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  int dec = fuzz_randomizer_get_int(0, 2);
+  if (dec == 0) {
+    run_process_incoming_tun(data, size);
+  }
+	else if (dec == 1) {
+		run_process_outgoing_tun(data, size);
+	}
+  else {
+    fuzz_process_outgoing_link(data, size);
+  }
+
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_header.h b/projects/openvpn/fuzz_header.h
new file mode 100644
index 0000000..e86b70c
--- /dev/null
+++ b/projects/openvpn/fuzz_header.h
@@ -0,0 +1,79 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef FUZZ_H
+#define FUZZ_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+// Forward declared because we want to use FuzzedDataProvider,
+// which requires CPP.
+extern ssize_t fuzz_get_random_data(void *buf, size_t len);
+
+ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags){
+	return fuzz_get_random_data(buf, len);
+}
+
+ssize_t fuzz_read(int sockfd, void *buf, size_t len){
+	return fuzz_get_random_data(buf, len);
+}
+
+ssize_t fuzz_write(int fd, const void *buf, size_t count) {
+  return count;
+}
+
+int fuzz_isatty(int fd) {
+  return 1;
+}
+
+char *fuzz_fgets(char *s, int size, FILE *stream) {
+  ssize_t v = fuzz_get_random_data(s, size-1);
+  // We use fgets to get trusted input. As such, assume we have
+  // an ascii printable char at the beginning.
+  printf("Calling into fgets\n");
+  if (s[0] <= 0x21 || s[0] >= 0x7f) {
+    s[0] = 'A';
+  }
+  s[size-1] = '\0';
+  return s;
+}
+
+int fuzz_select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout) {
+  char val;
+  ssize_t c = fuzz_get_random_data(&val, 1);
+  return c;
+}
+
+ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags) {
+  return len;
+}
+
+FILE *fp_p = NULL;
+FILE *fuzz_fopen(const char *pathname, const char *mode) {
+   if (mode == NULL) return fp_p;
+   return fp_p;
+}
+
+int fuzz_fclose(FILE *stream) {
+   if (stream == NULL) return 1;
+   return 2;
+}
+
+size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen) {
+  if (buf == NULL) {
+    return len;
+  }
+  return len;
+}
+
+#endif
diff --git a/projects/openvpn/fuzz_list.c b/projects/openvpn/fuzz_list.c
new file mode 100644
index 0000000..1e8fe62
--- /dev/null
+++ b/projects/openvpn/fuzz_list.c
@@ -0,0 +1,135 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "list.h"
+
+#include "fuzz_randomizer.h"
+
+#define KEY_SIZE 23
+
+/* Required for hash_init() */
+static uint32_t word_hash_function(const void *key, uint32_t iv) {
+  return hash_func(key, KEY_SIZE, iv);
+}
+
+/* Required for hash_init() */
+static bool word_compare_function(const void *key1, const void *key2) {
+  return ((size_t)key1 & 0xFFF) == ((size_t)key1 & 0xFFF);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  struct gc_arena gc;
+  struct hash *hash = NULL;
+  ssize_t generic_ssizet, generic_ssizet2, num_loops;
+
+  fuzz_random_init(data, size);
+
+  gc = gc_new();
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+  for (int i = 0; i < total_to_fuzz; i++) {
+    generic_ssizet = fuzz_randomizer_get_int(0, 8);
+
+    switch (generic_ssizet) {
+    case 0:
+      if (hash == NULL) {
+        int n_buckets = fuzz_randomizer_get_int(1, 1000);
+        uint32_t iv;
+
+        hash =
+            hash_init(n_buckets, iv, word_hash_function, word_compare_function);
+      }
+      break;
+    case 1:
+      if (hash) {
+        hash_free(hash);
+        hash = NULL;
+      }
+      break;
+    case 2:
+      if (hash) {
+        struct hash_iterator hi;
+        struct hash_element *he;
+        hash_iterator_init(hash, &hi);
+        while ((he = hash_iterator_next(&hi))) {
+          void *w = he->value;
+        }
+        hash_iterator_free(&hi);
+      }
+      break;
+    case 3:
+      if (hash) {
+        void *key;
+        void *value;
+        char arr[KEY_SIZE];
+        memset(arr, 0, KEY_SIZE);
+        fuzz_get_random_data(arr, KEY_SIZE);
+        key = (void *)arr;
+        if (!hash_lookup(hash, key)) {
+          generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+          value = (void *)generic_ssizet;
+          hash_add(hash, key, value, false);
+        }
+      }
+      break;
+    case 4:
+      if (hash) {
+        hash_n_elements(hash);
+      }
+      break;
+    case 5:
+      if (hash) {
+        hash_n_buckets(hash);
+      }
+      break;
+    case 6:
+      if (hash) {
+        uint32_t hv;
+        generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+        hv = generic_ssizet;
+        hash_bucket(hash, hv);
+      }
+      break;
+    case 7:
+      if (hash) {
+        void *key;
+        char arr[KEY_SIZE];
+        memset(arr, 0, KEY_SIZE);
+        fuzz_get_random_data(arr, KEY_SIZE);
+        key = (void *)arr;
+        hash_remove(hash, key);
+      }
+      break;
+    case 8:
+      if (hash) {
+        void *value;
+        generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+        value = (void *)generic_ssizet;
+        hash_remove_by_value(hash, value);
+      }
+    default:
+      break;
+    }
+  }
+
+  if (hash) {
+    hash_free(hash);
+  }
+
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_misc.c b/projects/openvpn/fuzz_misc.c
new file mode 100644
index 0000000..06d7b32
--- /dev/null
+++ b/projects/openvpn/fuzz_misc.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+#include "config.h"
+#include "syshead.h"
+#include "misc.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct gc_arena gc;
+  struct env_set *es;
+  gc = gc_new();
+  es = env_set_create(&gc);
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 9);
+  for (int i = 0; i <total_to_fuzz; i++) {
+    int type = fuzz_randomizer_get_int(0, 5);
+    char *tmp1 = get_random_string();
+    char *tmp2 = get_random_string();
+
+    switch (type) {
+    case 0:
+      env_set_del(es, tmp1);
+      break;
+    case 1:
+      env_set_add(es, tmp1);
+      break;
+    case 2:
+      env_set_get(es, tmp1);
+      break;
+    case 3:
+      if (strlen(tmp1) > 1 && strlen(tmp2) > 1) {
+        setenv_str(es, tmp2, tmp1);
+      }
+      break;
+    case 4:
+      hostname_randomize(tmp1, &gc);
+      break;
+    case 5:
+      if (strlen(tmp1) > 0) {
+        get_auth_challenge(tmp1, &gc);
+      }
+      break;
+    default:
+      sanitize_control_message(tmp1, &gc);
+    }
+    free(tmp1);
+    free(tmp2);
+  }
+
+  env_set_destroy(es);
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_mroute.c b/projects/openvpn/fuzz_mroute.c
new file mode 100644
index 0000000..63d0ce2
--- /dev/null
+++ b/projects/openvpn/fuzz_mroute.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "init.h"
+#include "mroute.h"
+
+#include "fuzz_randomizer.h"
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+  fuzz_random_init(data, size);
+  struct buffer buf;
+  struct gc_arena gc;
+
+  gc = gc_new();
+
+  char *tmp = get_random_string();
+  buf = string_alloc_buf(tmp, &gc);
+  free(tmp);
+
+  struct mroute_addr src_addr;
+  struct mroute_addr dst_addr;
+  mroute_addr_init(&src_addr);
+  mroute_addr_init(&dst_addr);
+  unsigned int ret = mroute_extract_addr_ip(&src_addr, &dst_addr, &buf);
+
+  if (ret & MROUTE_EXTRACT_SUCCEEDED) {
+    mroute_addr_mask_host_bits(&src_addr);
+    mroute_addr_print(&src_addr, &gc);
+    mroute_learnable_address(&src_addr, &gc);
+  }
+
+  uint16_t vid;
+  struct mroute_addr a1, a2;
+  mroute_addr_init(&a1);
+  mroute_addr_init(&a2);
+  mroute_extract_addr_ether(&a1, &a2, vid, &buf);
+
+  if (size > sizeof(struct openvpn_sockaddr)) {
+    struct openvpn_sockaddr local_sock;
+    memcpy(&local_sock, data, sizeof(struct openvpn_sockaddr));
+    mroute_extract_openvpn_sockaddr(&a1, &local_sock, true);
+    mroute_extract_openvpn_sockaddr(&a1, &local_sock, false);
+  }
+
+  struct mroute_helper *mhelper = NULL;
+  mhelper = mroute_helper_init(fuzz_randomizer_get_int(0, 0xfffffff));
+  if (mhelper != NULL) {
+    mroute_helper_add_iroute46(mhelper, fuzz_randomizer_get_int(0, MR_HELPER_NET_LEN-1));
+    mroute_helper_free(mhelper);
+  }
+
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+  return 0;
+}
+
diff --git a/projects/openvpn/fuzz_packet_id.c b/projects/openvpn/fuzz_packet_id.c
new file mode 100644
index 0000000..9297d0b
--- /dev/null
+++ b/projects/openvpn/fuzz_packet_id.c
@@ -0,0 +1,104 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "init.h"
+#include "packet_id.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct packet_id pid;
+  struct packet_id_net pin;
+  const int seq_backtrack = 10;
+  const int time_backtrack = 10;
+
+  packet_id_init(&pid, seq_backtrack, time_backtrack, "name", 0);
+
+  int total_sends = fuzz_randomizer_get_int(0, 10);
+  for (int i = 0; i < total_sends; i++) {
+    update_time();
+    pin.time = fuzz_randomizer_get_int(0, 0xfffffff);
+    pin.id = fuzz_randomizer_get_int(0, 0xfffffff);
+
+    packet_id_reap_test(&pid.rec);
+    bool test = packet_id_test(&pid.rec, &pin);
+    if (test) {
+      packet_id_add(&pid.rec, &pin);
+    }
+  }
+  packet_id_free(&pid);
+
+  // packet id send
+  char *tmp2 = get_random_string();
+  if (strlen(tmp2) > sizeof(struct packet_id_send)) {
+    struct packet_id_send pidsend;
+    memcmp(&pidsend, tmp2, sizeof(struct packet_id_send));
+
+    struct timeval tv;
+    tv.tv_sec = pidsend.time;
+    tv.tv_usec = 0;
+    if (localtime(&tv)) {
+      struct buffer iv_buffer;
+      buf_set_write(&iv_buffer, tmp2, strlen(tmp2));
+      packet_id_write(&pidsend, &iv_buffer, false, false);
+      packet_id_write(&pidsend, &iv_buffer, false, true);
+      packet_id_write(&pidsend, &iv_buffer, true, true);
+      packet_id_write(&pidsend, &iv_buffer, true, false);
+    }
+  }
+  free(tmp2);
+
+  struct gc_arena gc;
+  gc = gc_new();
+  struct buffer buf;
+  char *tmp = get_random_string();
+  buf = string_alloc_buf(tmp, &gc);
+  free(tmp);
+  packet_id_read(&pid, &buf, false);
+  packet_id_read(&pid, &buf, true);
+  gc_free(&gc);
+
+	char filename[256];
+	sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+
+	FILE *fp = fopen(filename, "wb");
+	if (!fp) {
+    return 0;
+	}
+	fwrite(data, size, 1, fp);
+	fclose(fp);
+ 
+  struct packet_id_persist p;
+  memset(&p, 0, sizeof(struct packet_id_persist));
+  packet_id_persist_init(&p);
+  packet_id_persist_load(&p, filename);
+  //p.time = NULL;
+  struct timeval tv;
+  tv.tv_sec = p.time;
+  tv.tv_usec = 0;
+  if (localtime(&tv) != NULL) {
+    gc = gc_new();
+    p.id_last_written = fuzz_randomizer_get_int(0, 0xfffffff);
+    //packet_id_persist_print(&p, &gc);
+    packet_id_persist_save(&p);
+    gc_free(&gc);
+  }
+
+  packet_id_persist_close(&p); 
+
+  fuzz_random_destroy();
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_proxy.c b/projects/openvpn/fuzz_proxy.c
new file mode 100644
index 0000000..128a6d0
--- /dev/null
+++ b/projects/openvpn/fuzz_proxy.c
@@ -0,0 +1,144 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include <sys/time.h>
+#include "syshead.h"
+#include "interval.h"
+#include "proxy.h"
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+    OPENSSL_malloc_init();
+    SSL_library_init();
+    ERR_load_crypto_strings();
+
+    OpenSSL_add_all_algorithms();
+    OpenSSL_add_ssl_algorithms();
+    OpenSSL_add_all_digests();
+
+    SSL_load_error_strings();
+    return 1;
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+	char *tmp = NULL;
+  char *tmp2 = NULL;
+
+  if (size < 500) {
+    return 0;
+  }
+  fuzz_random_init(data, size);
+
+  struct gc_arena gc = gc_new();
+  struct http_proxy_info pi;
+  ssize_t generic_ssizet;
+  int signal_received = 0;
+  struct buffer lookahead = alloc_buf(1024);
+  struct event_timeout evt;
+
+  memset(&evt, 0, sizeof(struct event_timeout));
+  memset(&pi, 0, sizeof(struct http_proxy_info));
+  memset(&pi, 0, sizeof(pi));
+
+  generic_ssizet = 0;
+  char *fuzz_usrnm = fuzz_random_get_string_max_length(USER_PASS_LEN);
+  strcpy(pi.up.username, fuzz_usrnm);
+  if (strlen(pi.up.username) == 0) {
+    gc_free(&gc);
+    free_buf(&lookahead);
+    free(fuzz_usrnm);
+    fuzz_random_destroy();
+    return 0;
+  }
+
+  char *pswd = fuzz_random_get_string_max_length(USER_PASS_LEN);
+  strcpy(pi.up.password, pswd);
+  if (strlen(pi.up.password) == 0) {
+    gc_free(&gc);
+    free_buf(&lookahead);
+
+    free(pswd);
+    free(fuzz_usrnm);
+    fuzz_random_destroy();
+    return 0;
+  }
+
+  generic_ssizet = fuzz_randomizer_get_int(0, 4);
+  switch (generic_ssizet) {
+  case 0:
+    pi.auth_method = HTTP_AUTH_NONE;
+    break;
+  case 1:
+     pi.auth_method = HTTP_AUTH_BASIC;
+    break;
+  case 2:
+    pi.auth_method = HTTP_AUTH_DIGEST;
+    break;
+  case 3:
+    pi.auth_method = HTTP_AUTH_NTLM;
+    break;
+  case 4:
+    pi.auth_method = HTTP_AUTH_NTLM2;
+    break;
+  }
+  pi.options.http_version = "1.1";
+
+  generic_ssizet = fuzz_randomizer_get_int(0, 4);
+  switch (generic_ssizet) {
+  case 0:
+    pi.options.auth_retry = PAR_NO;
+    break;
+  case 1:
+    pi.options.auth_retry = PAR_ALL;
+    break;
+  case 2:
+    pi.options.auth_retry = PAR_NCT;
+    break;
+  }
+
+  char *tmp_authenticate = get_random_string();
+  pi.proxy_authenticate = tmp_authenticate;
+
+  //if (provider.ConsumeProbability<double>() < 0.5) {
+    //tmp = get_modifiable_string(provider);
+    tmp = get_random_string();
+    pi.options.custom_headers[0].name = tmp;
+    //if (provider.ConsumeProbability<double>() < 0.5) {
+      //tmp2 = get_modifiable_string(provider);
+      tmp2 = get_random_string();
+      pi.options.custom_headers[0].content = tmp2;
+    //}
+  //}
+
+  establish_http_proxy_passthru(&pi, 0, "1.2.3.4", "777", &evt, &lookahead,
+                                &signal_received);
+  free(pi.proxy_authenticate);
+  gc_free(&gc);
+  free_buf(&lookahead);
+
+  if (tmp != NULL)  free(tmp);
+  if (tmp2 != NULL) free(tmp2);
+
+    free(pswd);
+    free(fuzz_usrnm);
+  fuzz_random_destroy();
+
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_randomizer.cpp b/projects/openvpn/fuzz_randomizer.cpp
new file mode 100644
index 0000000..367c558
--- /dev/null
+++ b/projects/openvpn/fuzz_randomizer.cpp
@@ -0,0 +1,107 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <assert.h>
+
+FuzzedDataProvider *prov = NULL;
+
+extern "C" void fuzz_random_init(const uint8_t *data, size_t size) {
+   assert(prov == NULL);
+   prov = new FuzzedDataProvider(data, size);
+}
+
+extern "C" void fuzz_random_destroy() {
+   assert(prov != NULL);
+  delete prov;
+  prov = NULL;
+}
+
+extern "C" char *get_random_string() {
+   assert(prov != NULL);
+
+   std::string s1 = prov->ConsumeRandomLengthString();
+   char *tmp = (char *)malloc(s1.size() + 1);
+   memcpy(tmp, s1.c_str(), s1.size());
+   tmp[s1.size()] = '\0';
+   return tmp;
+}
+
+extern "C" int fuzz_randomizer_get_int(int min, int max) {
+   assert(prov != NULL);
+   return prov->ConsumeIntegralInRange<int>(min, max);
+} 
+
+extern "C" char *fuzz_random_get_string_max_length(int max_len) {
+  assert(prov != NULL);
+
+  std::string s1 = prov->ConsumeBytesAsString(
+                           prov->ConsumeIntegralInRange<uint32_t>(1, max_len));
+  char *tmp123 = (char*)malloc(s1.size()+1);
+  memcpy(tmp123, s1.c_str(), s1.size());
+  tmp123[s1.size()] = '\0';
+
+  return tmp123;
+}
+
+extern "C" size_t fuzz_get_random_data(void *buf, size_t len) {
+  assert(prov != NULL);
+  size_t ret_val;
+  char *cbuf = (char*)buf;
+
+  if (prov->remaining_bytes() == 0) {
+    return -1;
+  }
+
+  double prob = prov->ConsumeProbability<double>();
+  if (prob < 0.05) {
+    return 0;
+  }
+
+  //if (len == 1) {
+  //  ret_val = prov->ConsumeData(buf, 1);
+  //  return ret_val;
+  //}
+  ret_val = prov->ConsumeData(buf, len);
+  return ret_val;
+}
+ 
+
+// Simple garbage collector
+#define GB_SIZE 100
+void *pointer_arr[GB_SIZE];
+static int pointer_idx = 0;
+
+// If the garbage collector is used then this must be called as first thing
+// during a fuzz run.
+extern "C" void gb_init() {
+  pointer_idx = 0;
+
+   for (int i = 0; i < GB_SIZE; i++) {
+     pointer_arr[i] = NULL;
+   }
+}
+
+extern "C" void gb_cleanup() {
+  for(int i = 0; i < GB_SIZE; i++) {
+    if (pointer_arr[i] != NULL) {
+      free(pointer_arr[i]);
+    }
+  }
+}
+
+extern "C" char *gb_get_random_string() {
+  char *tmp = get_random_string();
+  pointer_arr[pointer_idx++] = (void*)tmp;
+  return tmp;
+}
+
diff --git a/projects/openvpn/fuzz_randomizer.h b/projects/openvpn/fuzz_randomizer.h
new file mode 100644
index 0000000..a063eca
--- /dev/null
+++ b/projects/openvpn/fuzz_randomizer.h
@@ -0,0 +1,27 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+
+void fuzz_random_init(const uint8_t *data, size_t size);
+void fuzz_random_destroy();
+char *get_random_string();
+int fuzz_randomizer_get_int(int min, int max);
+size_t fuzz_get_random_data(void *buf, size_t len);
+char *fuzz_random_get_string_max_length(int max_len);
+
+void gb_init();
+void gb_cleanup();
+char *gb_get_random_string();
+
+int fuzz_success;
diff --git a/projects/openvpn/fuzz_route.c b/projects/openvpn/fuzz_route.c
new file mode 100644
index 0000000..2ca27a3
--- /dev/null
+++ b/projects/openvpn/fuzz_route.c
@@ -0,0 +1,201 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+#include "init.h"
+#include "proxy.h"
+#include "interval.h"
+#include "route.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+  fuzz_random_init(data, size);
+
+  gb_init();
+
+  struct route_option_list *opt;
+  struct route_list rl;
+
+  int route_list_inited = 0;
+  int route_list_ipv6_inited = 0;
+
+  struct context c;
+  memset(&c, 0, sizeof(struct context));
+  gc_init(&c.gc);
+  c.es = env_set_create(&c.gc);
+  init_options(&c.options, true);
+  net_ctx_init(&c, &c.net_ctx);
+  init_verb_mute(&c, IVM_LEVEL_1);
+
+  init_options_dev(&c.options);
+
+  // options_postprocess(&c.options);
+  pre_setup(&c.options);
+
+  setenv_settings(c.es, &c.options);
+
+  ALLOC_OBJ_CLEAR_GC(c.options.connection_list, struct connection_list,
+                     &c.options.gc);
+  context_init_1(&c);
+
+  in_addr_t remote_host;
+  ssize_t default_metric;
+
+  struct route_ipv6_list rl6;
+  struct route_ipv6_option_list *opt6;
+
+  memset(&rl, 0, sizeof(rl));
+  memset(&rl6, 0, sizeof(rl6));
+  memset(&opt, 0, sizeof(opt));
+  memset(&opt6, 0, sizeof(opt6));
+
+  opt6 = new_route_ipv6_option_list(&c.gc);
+  opt = new_route_option_list(&c.gc);
+
+  int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+  for (int i = 0; i < total_to_fuzz; i++) {
+    int selector = fuzz_randomizer_get_int(0, 13);
+    switch (selector) {
+    case 0:
+      if (route_list_inited == 0) {
+        const char *remote_endpoint = gb_get_random_string();
+        memset(&rl, 0, sizeof(struct route_list));
+        rl.flags = fuzz_randomizer_get_int(0, 0xffffff);
+
+        init_route_list(&rl, opt, remote_endpoint, default_metric, remote_host,
+                        c.es, &c);
+        route_list_inited = 1;
+      }
+      break;
+    case 1:
+      if (route_list_inited) {
+        in_addr_t addr;
+        route_list_add_vpn_gateway(&rl, c.es, addr);
+      }
+      break;
+    case 2:
+      if (route_list_inited && route_list_ipv6_inited) {
+        struct tuntap tt;
+        memset(&tt, 0, sizeof(tt));
+        add_routes(&rl, &rl6, &tt, 0, c.es, &c);
+      }
+      break;
+    case 3:
+      if (route_list_inited) {
+        setenv_routes(c.es, &rl);
+      }
+      break;
+    case 4:
+      if (route_list_inited) {
+        struct route_ipv4 r;
+        struct route_option ro;
+        ro.network = gb_get_random_string();
+        ro.netmask = gb_get_random_string();
+        ro.gateway = gb_get_random_string();
+        ro.metric = gb_get_random_string();
+        ro.next = NULL;
+
+        memset(&r, 0, sizeof(struct route_ipv4));
+        r.option = &ro;
+        r.flags = RT_DEFINED;
+        add_route(&r, NULL, 0, NULL, c.es, &c);
+      }
+      break;
+    case 5:
+      if (route_list_inited) {
+        char *s1 = get_random_string();
+        is_special_addr(s1);
+        free(s1);
+      }
+      break;
+    case 6:
+      if (route_list_ipv6_inited == 0) {
+        const char *remote_endpoint = gb_get_random_string();
+        memset(&rl, 0, sizeof(struct route_list));
+        struct in6_addr remote_host;
+
+        rl6.rgi6.flags = fuzz_randomizer_get_int(0, 0xffffff);
+        fuzz_get_random_data(&rl6.rgi6.hwaddr, 6);
+
+        char *t1 = gb_get_random_string();
+        if (strlen(t1) > 16) {
+          memcpy(rl6.rgi6.iface, t1, 16);
+        } else {
+          memcpy(rl6.rgi6.iface, t1, strlen(t1));
+        }
+
+        init_route_ipv6_list(&rl6, opt6, remote_endpoint, 0, &remote_host, c.es,
+                             &c);
+        route_list_ipv6_inited = 1;
+      }
+      break;
+    case 7: {
+      unsigned int flags;
+      struct route_ipv6 r6;
+      struct tuntap tt;
+      memset(&tt, 0, sizeof(tt));
+      tt.actual_name = gb_get_random_string();
+      r6.iface = gb_get_random_string();
+      r6.flags = fuzz_randomizer_get_int(0, 0xfffff);
+      r6.netbits = fuzz_randomizer_get_int(0, 0xfffff);
+      r6.metric = fuzz_randomizer_get_int(0, 0xfffff);
+
+      r6.next = NULL;
+
+      add_route_ipv6(&r6, &tt, 0, c.es, &c);
+    } break;
+    case 8:
+      if (route_list_ipv6_inited && route_list_inited) {
+        delete_routes(&rl, &rl6, NULL, 0, c.es, &c);
+        route_list_ipv6_inited = 0;
+        route_list_inited = 0;
+      }
+      break;
+    case 9:
+      if (route_list_ipv6_inited) {
+        setenv_routes_ipv6(c.es, &rl6);
+      }
+      break;
+    case 10: {
+      add_route_ipv6_to_option_list(opt6, gb_get_random_string(),
+                                    gb_get_random_string(),
+                                    gb_get_random_string());
+    } break;
+    case 11: {
+      print_route_options(opt, M_NONFATAL);
+    } break;
+    case 12: {
+      add_route_to_option_list(opt, gb_get_random_string(),
+                               gb_get_random_string(), gb_get_random_string(),
+                               gb_get_random_string());
+    } break;
+    default:
+      break;
+    }
+  }
+
+  if (route_list_inited) {
+    gc_free(&rl.gc);
+  }
+  env_set_destroy(c.es);
+  context_gc_free(&c);
+
+  fuzz_random_destroy();
+
+  gb_cleanup();
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_verify_cert.c b/projects/openvpn/fuzz_verify_cert.c
new file mode 100644
index 0000000..c73a6ac
--- /dev/null
+++ b/projects/openvpn/fuzz_verify_cert.c
@@ -0,0 +1,167 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+#include "syshead.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "fuzz_verify_cert.h"
+#include "misc.h"
+#include "manage.h"
+#include "otime.h"
+#include "base64.h"
+#include "ssl_verify.h"
+#include "ssl_verify_backend.h"
+
+#include "fuzz_randomizer.h"
+
+
+static int parse_x509(const uint8_t *data, size_t size, X509 **out) {
+  *out = d2i_X509(NULL, (const unsigned char **)&data, size);
+  if (*out == NULL) {
+    return -1;
+  }
+
+  return 0;
+}
+
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  OPENSSL_malloc_init();
+  SSL_library_init();
+  ERR_load_crypto_strings();
+
+  OpenSSL_add_all_algorithms();
+  OpenSSL_add_ssl_algorithms();
+
+  SSL_load_error_strings();
+  return 1;
+}
+
+
+static int init_session_opt(struct tls_options **_opt, struct gc_arena *gc) {
+  ssize_t nid;
+  ssize_t generic_ssizet;
+  struct tls_options *opt;
+  int r;
+
+  ALLOC_OBJ_GC(*_opt, struct tls_options, gc);
+  if (opt == NULL) {
+		return -1;
+  }
+
+  opt = *_opt;
+
+  memset(opt, 0xFE, sizeof(struct tls_options));
+
+  opt->es = env_set_create(gc);
+  opt->x509_username_field[0] = NULL;
+  opt->remote_cert_eku = NULL;
+
+  /* Prevents failure if x509 sha1 hashes do not match */
+  opt->verify_hash = NULL;
+
+  /* Prevent attempt to run --tls-verify script */
+  opt->verify_command = NULL;
+
+  /* Do not verify against CRL file */
+  opt->crl_file = NULL;
+
+  /* Do not run --tls-verify plugins */
+  opt->plugins = NULL;
+
+  r = fuzz_randomizer_get_int(0, 1);
+  if (r == 0) {
+    opt->x509_username_field[0] = nidstrs[fuzz_randomizer_get_int(0, (sizeof(nidstrs)/sizeof(nidstrs[0])) - 1)];
+  } 
+  else {
+    opt->x509_username_field[0] = "ext:subjectAltName";
+  }
+  opt->x509_username_field[1] = NULL;
+
+  r = fuzz_randomizer_get_int(0, 2);
+  if (r == 0)
+    opt->ns_cert_type = NS_CERT_CHECK_CLIENT;
+  else if (r == 1)
+    opt->ns_cert_type = NS_CERT_CHECK_SERVER;
+  else
+    opt->ns_cert_type = NS_CERT_CHECK_NONE;
+
+  opt->x509_track = NULL;
+
+  r = fuzz_randomizer_get_int(0, 1);
+  if (r == 0)
+    opt->remote_cert_eku = NULL;
+  else
+    opt->remote_cert_eku = get_random_string();
+
+  return 0;
+}
+
+
+static int init_session(struct tls_session **_session, struct gc_arena *gc) {
+  struct tls_session *session;
+
+  ALLOC_OBJ_GC(*_session, struct tls_session, gc);
+  if (*_session == NULL) {
+		return -1;
+  }
+
+  session = *_session;
+  memset(session, 0xFE, sizeof(struct tls_session));
+
+  /* Accessed in set_common_name() */
+  session->common_name = get_random_string();;
+
+  /* Initialize the session->opt structure */
+  if (init_session_opt(&(session->opt), gc) == -1) {
+    free(session->common_name);
+		return -1;
+  }
+
+  /* Accessed in server_untrusted() */
+  session->untrusted_addr.dest.addr.sa.sa_family = AF_UNSPEC;
+
+  return 0;
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  fuzz_random_init(data, size);
+
+  struct gc_arena gc;
+  struct tls_session *session = NULL;
+  X509 *x509 = NULL;
+  gc = gc_new();
+
+  if (parse_x509(data, size, &x509) == 0) {
+    if (init_session(&session, &gc) == 0) {
+      verify_cert(session, x509, 100);
+      if (session->opt->remote_cert_eku != NULL) {
+        free(session->opt->remote_cert_eku);
+      }
+      free(session->common_name);
+    }
+    
+  }
+
+  X509_free(x509);
+  gc_free(&gc);
+
+  fuzz_random_destroy();
+
+  return 0;
+}
diff --git a/projects/openvpn/fuzz_verify_cert.h b/projects/openvpn/fuzz_verify_cert.h
new file mode 100644
index 0000000..8a53669
--- /dev/null
+++ b/projects/openvpn/fuzz_verify_cert.h
@@ -0,0 +1,1065 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+static char* nidstrs[] = {
+"AD_DVCS",
+"AES-128-CBC",
+"AES-128-CBC-HMAC-SHA1",
+"AES-128-CBC-HMAC-SHA256",
+"AES-128-CFB",
+"AES-128-CFB1",
+"AES-128-CFB8",
+"AES-128-CTR",
+"AES-128-ECB",
+"AES-128-OCB",
+"AES-128-OFB",
+"AES-128-XTS",
+"AES-192-CBC",
+"AES-192-CBC-HMAC-SHA1",
+"AES-192-CBC-HMAC-SHA256",
+"AES-192-CFB",
+"AES-192-CFB1",
+"AES-192-CFB8",
+"AES-192-CTR",
+"AES-192-ECB",
+"AES-192-OCB",
+"AES-192-OFB",
+"AES-256-CBC",
+"AES-256-CBC-HMAC-SHA1",
+"AES-256-CBC-HMAC-SHA256",
+"AES-256-CFB",
+"AES-256-CFB1",
+"AES-256-CFB8",
+"AES-256-CTR",
+"AES-256-ECB",
+"AES-256-OCB",
+"AES-256-OFB",
+"AES-256-XTS",
+"AuthDSS",
+"AuthECDSA",
+"AuthGOST01",
+"AuthGOST12",
+"AuthNULL",
+"AuthPSK",
+"AuthRSA",
+"AuthSRP",
+"BF-CBC",
+"BF-CFB",
+"BF-ECB",
+"BF-OFB",
+"BLAKE2b512",
+"BLAKE2s256",
+"C",
+"CAMELLIA-128-CBC",
+"CAMELLIA-128-CCM",
+"CAMELLIA-128-CFB",
+"CAMELLIA-128-CFB1",
+"CAMELLIA-128-CFB8",
+"CAMELLIA-128-CMAC",
+"CAMELLIA-128-CTR",
+"CAMELLIA-128-ECB",
+"CAMELLIA-128-GCM",
+"CAMELLIA-128-OFB",
+"CAMELLIA-192-CBC",
+"CAMELLIA-192-CCM",
+"CAMELLIA-192-CFB",
+"CAMELLIA-192-CFB1",
+"CAMELLIA-192-CFB8",
+"CAMELLIA-192-CMAC",
+"CAMELLIA-192-CTR",
+"CAMELLIA-192-ECB",
+"CAMELLIA-192-GCM",
+"CAMELLIA-192-OFB",
+"CAMELLIA-256-CBC",
+"CAMELLIA-256-CCM",
+"CAMELLIA-256-CFB",
+"CAMELLIA-256-CFB1",
+"CAMELLIA-256-CFB8",
+"CAMELLIA-256-CMAC",
+"CAMELLIA-256-CTR",
+"CAMELLIA-256-ECB",
+"CAMELLIA-256-GCM",
+"CAMELLIA-256-OFB",
+"CAST5-CBC",
+"CAST5-CFB",
+"CAST5-ECB",
+"CAST5-OFB",
+"CMAC",
+"CN",
+"CRLReason",
+"CSPName",
+"ChaCha20",
+"ChaCha20-Poly1305",
+"CrlID",
+"DC",
+"DES-CBC",
+"DES-CDMF",
+"DES-CFB",
+"DES-CFB1",
+"DES-CFB8",
+"DES-ECB",
+"DES-EDE",
+"DES-EDE-CBC",
+"DES-EDE-CFB",
+"DES-EDE-OFB",
+"DES-EDE3",
+"DES-EDE3-CBC",
+"DES-EDE3-CFB",
+"DES-EDE3-CFB1",
+"DES-EDE3-CFB8",
+"DES-EDE3-OFB",
+"DES-OFB",
+"DESX-CBC",
+"DOD",
+"DSA",
+"DSA-SHA",
+"DSA-SHA1",
+"DSA-SHA1-old",
+"DSA-old",
+"DVCS",
+"GN",
+"HKDF",
+"HMAC",
+"HMAC-MD5",
+"HMAC-SHA1",
+"IANA",
+"IDEA-CBC",
+"IDEA-CFB",
+"IDEA-ECB",
+"IDEA-OFB",
+"INN",
+"ISO",
+"ISO-US",
+"ITU-T",
+"JOINT-ISO-ITU-T",
+"KISA",
+"KxDHE",
+"KxDHE-PSK",
+"KxECDHE",
+"KxECDHE-PSK",
+"KxGOST",
+"KxPSK",
+"KxRSA",
+"KxRSA_PSK",
+"KxSRP",
+"L",
+"LocalKeySet",
+"MD2",
+"MD4",
+"MD5",
+"MD5-SHA1",
+"MDC2",
+"MGF1",
+"Mail",
+"NULL",
+"Netscape",
+"Nonce",
+"O",
+"OCSP",
+"OCSPSigning",
+"OGRN",
+"ORG",
+"OU",
+"Oakley-EC2N-3",
+"Oakley-EC2N-4",
+"PBE-MD2-DES",
+"PBE-MD2-RC2-64",
+"PBE-MD5-DES",
+"PBE-MD5-RC2-64",
+"PBE-SHA1-2DES",
+"PBE-SHA1-3DES",
+"PBE-SHA1-DES",
+"PBE-SHA1-RC2-128",
+"PBE-SHA1-RC2-40",
+"PBE-SHA1-RC2-64",
+"PBE-SHA1-RC4-128",
+"PBE-SHA1-RC4-40",
+"PBES2",
+"PBKDF2",
+"PBMAC1",
+"PKIX",
+"PSPECIFIED",
+"RC2-40-CBC",
+"RC2-64-CBC",
+"RC2-CBC",
+"RC2-CFB",
+"RC2-ECB",
+"RC2-OFB",
+"RC4",
+"RC4-40",
+"RC4-HMAC-MD5",
+"RC5-CBC",
+"RC5-CFB",
+"RC5-ECB",
+"RC5-OFB",
+"RIPEMD160",
+"RSA",
+"RSA-MD2",
+"RSA-MD4",
+"RSA-MD5",
+"RSA-MDC2",
+"RSA-NP-MD5",
+"RSA-RIPEMD160",
+"RSA-SHA",
+"RSA-SHA1",
+"RSA-SHA1-2",
+"RSA-SHA224",
+"RSA-SHA256",
+"RSA-SHA384",
+"RSA-SHA512",
+"RSAES-OAEP",
+"RSASSA-PSS",
+"SEED-CBC",
+"SEED-CFB",
+"SEED-ECB",
+"SEED-OFB",
+"SHA",
+"SHA1",
+"SHA224",
+"SHA256",
+"SHA384",
+"SHA512",
+"SMIME",
+"SMIME-CAPS",
+"SN",
+"SNILS",
+"ST",
+"SXNetID",
+"TLS1-PRF",
+"UID",
+"UNDEF",
+"X25519",
+"X448",
+"X500",
+"X500algorithms",
+"X509",
+"X9-57",
+"X9cm",
+"ZLIB",
+"aRecord",
+"aaControls",
+"ac-auditEntity",
+"ac-proxying",
+"ac-targeting",
+"acceptableResponses",
+"account",
+"ad_timestamping",
+"algorithm",
+"ansi-X9-62",
+"anyExtendedKeyUsage",
+"anyPolicy",
+"archiveCutoff",
+"associatedDomain",
+"associatedName",
+"audio",
+"authorityInfoAccess",
+"authorityKeyIdentifier",
+"authorityRevocationList",
+"basicConstraints",
+"basicOCSPResponse",
+"biometricInfo",
+"brainpoolP160r1",
+"brainpoolP160t1",
+"brainpoolP192r1",
+"brainpoolP192t1",
+"brainpoolP224r1",
+"brainpoolP224t1",
+"brainpoolP256r1",
+"brainpoolP256t1",
+"brainpoolP320r1",
+"brainpoolP320t1",
+"brainpoolP384r1",
+"brainpoolP384t1",
+"brainpoolP512r1",
+"brainpoolP512t1",
+"buildingName",
+"businessCategory",
+"c2onb191v4",
+"c2onb191v5",
+"c2onb239v4",
+"c2onb239v5",
+"c2pnb163v1",
+"c2pnb163v2",
+"c2pnb163v3",
+"c2pnb176v1",
+"c2pnb208w1",
+"c2pnb272w1",
+"c2pnb304w1",
+"c2pnb368w1",
+"c2tnb191v1",
+"c2tnb191v2",
+"c2tnb191v3",
+"c2tnb239v1",
+"c2tnb239v2",
+"c2tnb239v3",
+"c2tnb359v1",
+"c2tnb431r1",
+"cACertificate",
+"cNAMERecord",
+"caIssuers",
+"caRepository",
+"capwapAC",
+"capwapWTP",
+"caseIgnoreIA5StringSyntax",
+"certBag",
+"certicom-arc",
+"certificateIssuer",
+"certificatePolicies",
+"certificateRevocationList",
+"challengePassword",
+"characteristic-two-field",
+"clearance",
+"clientAuth",
+"codeSigning",
+"contentType",
+"countersignature",
+"crlBag",
+"crlDistributionPoints",
+"crlNumber",
+"crossCertificatePair",
+"cryptocom",
+"cryptopro",
+"ct_cert_scts",
+"ct_precert_poison",
+"ct_precert_scts",
+"ct_precert_signer",
+"dITRedirect",
+"dNSDomain",
+"dSAQuality",
+"data",
+"dcobject",
+"deltaCRL",
+"deltaRevocationList",
+"description",
+"destinationIndicator",
+"dh-cofactor-kdf",
+"dh-std-kdf",
+"dhKeyAgreement",
+"dhSinglePass-cofactorDH-sha1kdf-scheme",
+"dhSinglePass-cofactorDH-sha224kdf-scheme",
+"dhSinglePass-cofactorDH-sha256kdf-scheme",
+"dhSinglePass-cofactorDH-sha384kdf-scheme",
+"dhSinglePass-cofactorDH-sha512kdf-scheme",
+"dhSinglePass-stdDH-sha1kdf-scheme",
+"dhSinglePass-stdDH-sha224kdf-scheme",
+"dhSinglePass-stdDH-sha256kdf-scheme",
+"dhSinglePass-stdDH-sha384kdf-scheme",
+"dhSinglePass-stdDH-sha512kdf-scheme",
+"dhpublicnumber",
+"directory",
+"distinguishedName",
+"dmdName",
+"dnQualifier",
+"document",
+"documentAuthor",
+"documentIdentifier",
+"documentLocation",
+"documentPublisher",
+"documentSeries",
+"documentTitle",
+"documentVersion",
+"domain",
+"domainRelatedObject",
+"dsa_with_SHA224",
+"dsa_with_SHA256",
+"ecdsa-with-Recommended",
+"ecdsa-with-SHA1",
+"ecdsa-with-SHA224",
+"ecdsa-with-SHA256",
+"ecdsa-with-SHA384",
+"ecdsa-with-SHA512",
+"ecdsa-with-Specified",
+"emailAddress",
+"emailProtection",
+"enhancedSearchGuide",
+"enterprises",
+"experimental",
+"extReq",
+"extendedCertificateAttributes",
+"extendedKeyUsage",
+"extendedStatus",
+"facsimileTelephoneNumber",
+"favouriteDrink",
+"freshestCRL",
+"friendlyCountry",
+"friendlyCountryName",
+"friendlyName",
+"generationQualifier",
+"gost-mac",
+"gost-mac-12",
+"gost2001",
+"gost2001cc",
+"gost2012_256",
+"gost2012_512",
+"gost89",
+"gost89-cbc",
+"gost89-cnt",
+"gost89-cnt-12",
+"gost89-ctr",
+"gost89-ecb",
+"gost94",
+"gost94cc",
+"grasshopper-cbc",
+"grasshopper-cfb",
+"grasshopper-ctr",
+"grasshopper-ecb",
+"grasshopper-mac",
+"grasshopper-ofb",
+"hmacWithMD5",
+"hmacWithSHA1",
+"hmacWithSHA224",
+"hmacWithSHA256",
+"hmacWithSHA384",
+"hmacWithSHA512",
+"holdInstructionCallIssuer",
+"holdInstructionCode",
+"holdInstructionNone",
+"holdInstructionReject",
+"homePostalAddress",
+"homeTelephoneNumber",
+"host",
+"houseIdentifier",
+"iA5StringSyntax",
+"id-DHBasedMac",
+"id-Gost28147-89-CryptoPro-A-ParamSet",
+"id-Gost28147-89-CryptoPro-B-ParamSet",
+"id-Gost28147-89-CryptoPro-C-ParamSet",
+"id-Gost28147-89-CryptoPro-D-ParamSet",
+"id-Gost28147-89-CryptoPro-KeyMeshing",
+"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+"id-Gost28147-89-None-KeyMeshing",
+"id-Gost28147-89-TestParamSet",
+"id-Gost28147-89-cc",
+"id-GostR3410-2001-CryptoPro-A-ParamSet",
+"id-GostR3410-2001-CryptoPro-B-ParamSet",
+"id-GostR3410-2001-CryptoPro-C-ParamSet",
+"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+"id-GostR3410-2001-ParamSet-cc",
+"id-GostR3410-2001-TestParamSet",
+"id-GostR3410-2001DH",
+"id-GostR3410-94-CryptoPro-A-ParamSet",
+"id-GostR3410-94-CryptoPro-B-ParamSet",
+"id-GostR3410-94-CryptoPro-C-ParamSet",
+"id-GostR3410-94-CryptoPro-D-ParamSet",
+"id-GostR3410-94-CryptoPro-XchA-ParamSet",
+"id-GostR3410-94-CryptoPro-XchB-ParamSet",
+"id-GostR3410-94-CryptoPro-XchC-ParamSet",
+"id-GostR3410-94-TestParamSet",
+"id-GostR3410-94-a",
+"id-GostR3410-94-aBis",
+"id-GostR3410-94-b",
+"id-GostR3410-94-bBis",
+"id-GostR3410-94DH",
+"id-GostR3411-94-CryptoProParamSet",
+"id-GostR3411-94-TestParamSet",
+"id-GostR3411-94-with-GostR3410-2001",
+"id-GostR3411-94-with-GostR3410-2001-cc",
+"id-GostR3411-94-with-GostR3410-94",
+"id-GostR3411-94-with-GostR3410-94-cc",
+"id-HMACGostR3411-94",
+"id-PasswordBasedMAC",
+"id-aca",
+"id-aca-accessIdentity",
+"id-aca-authenticationInfo",
+"id-aca-chargingIdentity",
+"id-aca-encAttrs",
+"id-aca-group",
+"id-aca-role",
+"id-ad",
+"id-aes128-CCM",
+"id-aes128-GCM",
+"id-aes128-wrap",
+"id-aes128-wrap-pad",
+"id-aes192-CCM",
+"id-aes192-GCM",
+"id-aes192-wrap",
+"id-aes192-wrap-pad",
+"id-aes256-CCM",
+"id-aes256-GCM",
+"id-aes256-wrap",
+"id-aes256-wrap-pad",
+"id-alg",
+"id-alg-PWRI-KEK",
+"id-alg-des40",
+"id-alg-dh-pop",
+"id-alg-dh-sig-hmac-sha1",
+"id-alg-noSignature",
+"id-camellia128-wrap",
+"id-camellia192-wrap",
+"id-camellia256-wrap",
+"id-cct",
+"id-cct-PKIData",
+"id-cct-PKIResponse",
+"id-cct-crs",
+"id-ce",
+"id-characteristic-two-basis",
+"id-cmc",
+"id-cmc-addExtensions",
+"id-cmc-confirmCertAcceptance",
+"id-cmc-dataReturn",
+"id-cmc-decryptedPOP",
+"id-cmc-encryptedPOP",
+"id-cmc-getCRL",
+"id-cmc-getCert",
+"id-cmc-identification",
+"id-cmc-identityProof",
+"id-cmc-lraPOPWitness",
+"id-cmc-popLinkRandom",
+"id-cmc-popLinkWitness",
+"id-cmc-queryPending",
+"id-cmc-recipientNonce",
+"id-cmc-regInfo",
+"id-cmc-responseInfo",
+"id-cmc-revokeRequest",
+"id-cmc-senderNonce",
+"id-cmc-statusInfo",
+"id-cmc-transactionId",
+"id-ct-asciiTextWithCRLF",
+"id-ct-xml",
+"id-ecPublicKey",
+"id-hex-multipart-message",
+"id-hex-partial-message",
+"id-it",
+"id-it-caKeyUpdateInfo",
+"id-it-caProtEncCert",
+"id-it-confirmWaitTime",
+"id-it-currentCRL",
+"id-it-encKeyPairTypes",
+"id-it-implicitConfirm",
+"id-it-keyPairParamRep",
+"id-it-keyPairParamReq",
+"id-it-origPKIMessage",
+"id-it-preferredSymmAlg",
+"id-it-revPassphrase",
+"id-it-signKeyPairTypes",
+"id-it-subscriptionRequest",
+"id-it-subscriptionResponse",
+"id-it-suppLangTags",
+"id-it-unsupportedOIDs",
+"id-kp",
+"id-mod-attribute-cert",
+"id-mod-cmc",
+"id-mod-cmp",
+"id-mod-cmp2000",
+"id-mod-crmf",
+"id-mod-dvcs",
+"id-mod-kea-profile-88",
+"id-mod-kea-profile-93",
+"id-mod-ocsp",
+"id-mod-qualified-cert-88",
+"id-mod-qualified-cert-93",
+"id-mod-timestamp-protocol",
+"id-on",
+"id-on-permanentIdentifier",
+"id-on-personalData",
+"id-pda",
+"id-pda-countryOfCitizenship",
+"id-pda-countryOfResidence",
+"id-pda-dateOfBirth",
+"id-pda-gender",
+"id-pda-placeOfBirth",
+"id-pe",
+"id-pkinit",
+"id-pkip",
+"id-pkix-mod",
+"id-pkix1-explicit-88",
+"id-pkix1-explicit-93",
+"id-pkix1-implicit-88",
+"id-pkix1-implicit-93",
+"id-ppl",
+"id-ppl-anyLanguage",
+"id-ppl-independent",
+"id-ppl-inheritAll",
+"id-qcs",
+"id-qcs-pkixQCSyntax-v1",
+"id-qt",
+"id-qt-cps",
+"id-qt-unotice",
+"id-regCtrl",
+"id-regCtrl-authenticator",
+"id-regCtrl-oldCertID",
+"id-regCtrl-pkiArchiveOptions",
+"id-regCtrl-pkiPublicationInfo",
+"id-regCtrl-protocolEncrKey",
+"id-regCtrl-regToken",
+"id-regInfo",
+"id-regInfo-certReq",
+"id-regInfo-utf8Pairs",
+"id-scrypt",
+"id-set",
+"id-smime-aa",
+"id-smime-aa-contentHint",
+"id-smime-aa-contentIdentifier",
+"id-smime-aa-contentReference",
+"id-smime-aa-dvcs-dvc",
+"id-smime-aa-encapContentType",
+"id-smime-aa-encrypKeyPref",
+"id-smime-aa-equivalentLabels",
+"id-smime-aa-ets-CertificateRefs",
+"id-smime-aa-ets-RevocationRefs",
+"id-smime-aa-ets-archiveTimeStamp",
+"id-smime-aa-ets-certCRLTimestamp",
+"id-smime-aa-ets-certValues",
+"id-smime-aa-ets-commitmentType",
+"id-smime-aa-ets-contentTimestamp",
+"id-smime-aa-ets-escTimeStamp",
+"id-smime-aa-ets-otherSigCert",
+"id-smime-aa-ets-revocationValues",
+"id-smime-aa-ets-sigPolicyId",
+"id-smime-aa-ets-signerAttr",
+"id-smime-aa-ets-signerLocation",
+"id-smime-aa-macValue",
+"id-smime-aa-mlExpandHistory",
+"id-smime-aa-msgSigDigest",
+"id-smime-aa-receiptRequest",
+"id-smime-aa-securityLabel",
+"id-smime-aa-signatureType",
+"id-smime-aa-signingCertificate",
+"id-smime-aa-smimeEncryptCerts",
+"id-smime-aa-timeStampToken",
+"id-smime-alg",
+"id-smime-alg-3DESwrap",
+"id-smime-alg-CMS3DESwrap",
+"id-smime-alg-CMSRC2wrap",
+"id-smime-alg-ESDH",
+"id-smime-alg-ESDHwith3DES",
+"id-smime-alg-ESDHwithRC2",
+"id-smime-alg-RC2wrap",
+"id-smime-cd",
+"id-smime-cd-ldap",
+"id-smime-ct",
+"id-smime-ct-DVCSRequestData",
+"id-smime-ct-DVCSResponseData",
+"id-smime-ct-TDTInfo",
+"id-smime-ct-TSTInfo",
+"id-smime-ct-authData",
+"id-smime-ct-authEnvelopedData",
+"id-smime-ct-compressedData",
+"id-smime-ct-contentCollection",
+"id-smime-ct-contentInfo",
+"id-smime-ct-publishCert",
+"id-smime-ct-receipt",
+"id-smime-cti",
+"id-smime-cti-ets-proofOfApproval",
+"id-smime-cti-ets-proofOfCreation",
+"id-smime-cti-ets-proofOfDelivery",
+"id-smime-cti-ets-proofOfOrigin",
+"id-smime-cti-ets-proofOfReceipt",
+"id-smime-cti-ets-proofOfSender",
+"id-smime-mod",
+"id-smime-mod-cms",
+"id-smime-mod-ess",
+"id-smime-mod-ets-eSigPolicy-88",
+"id-smime-mod-ets-eSigPolicy-97",
+"id-smime-mod-ets-eSignature-88",
+"id-smime-mod-ets-eSignature-97",
+"id-smime-mod-msg-v3",
+"id-smime-mod-oid",
+"id-smime-spq",
+"id-smime-spq-ets-sqt-unotice",
+"id-smime-spq-ets-sqt-uri",
+"id-tc26",
+"id-tc26-agreement",
+"id-tc26-agreement-gost-3410-2012-256",
+"id-tc26-agreement-gost-3410-2012-512",
+"id-tc26-algorithms",
+"id-tc26-cipher",
+"id-tc26-cipher-constants",
+"id-tc26-constants",
+"id-tc26-digest",
+"id-tc26-digest-constants",
+"id-tc26-gost-28147-constants",
+"id-tc26-gost-28147-param-Z",
+"id-tc26-gost-3410-2012-512-constants",
+"id-tc26-gost-3410-2012-512-paramSetA",
+"id-tc26-gost-3410-2012-512-paramSetB",
+"id-tc26-gost-3410-2012-512-paramSetTest",
+"id-tc26-hmac-gost-3411-2012-256",
+"id-tc26-hmac-gost-3411-2012-512",
+"id-tc26-mac",
+"id-tc26-sign",
+"id-tc26-sign-constants",
+"id-tc26-signwithdigest",
+"id-tc26-signwithdigest-gost3410-2012-256",
+"id-tc26-signwithdigest-gost3410-2012-512",
+"identified-organization",
+"info",
+"inhibitAnyPolicy",
+"initials",
+"international-organizations",
+"internationaliSDNNumber",
+"invalidityDate",
+"ipsecEndSystem",
+"ipsecIKE",
+"ipsecTunnel",
+"ipsecUser",
+"issuerAltName",
+"issuerSignTool",
+"issuingDistributionPoint",
+"janetMailbox",
+"jurisdictionC",
+"jurisdictionL",
+"jurisdictionST",
+"keyBag",
+"keyUsage",
+"lastModifiedBy",
+"lastModifiedTime",
+"localKeyID",
+"mXRecord",
+"mail",
+"mailPreferenceOption",
+"manager",
+"md_gost12_256",
+"md_gost12_512",
+"md_gost94",
+"member",
+"member-body",
+"messageDigest",
+"mgmt",
+"mime-mhs",
+"mime-mhs-bodies",
+"mime-mhs-headings",
+"mobileTelephoneNumber",
+"msCTLSign",
+"msCodeCom",
+"msCodeInd",
+"msEFS",
+"msExtReq",
+"msSGC",
+"msSmartcardLogin",
+"msUPN",
+"nSRecord",
+"name",
+"nameConstraints",
+"noCheck",
+"noRevAvail",
+"nsBaseUrl",
+"nsCaPolicyUrl",
+"nsCaRevocationUrl",
+"nsCertExt",
+"nsCertSequence",
+"nsCertType",
+"nsComment",
+"nsDataType",
+"nsRenewalUrl",
+"nsRevocationUrl",
+"nsSGC",
+"nsSslServerName",
+"onBasis",
+"organizationalStatus",
+"otherMailbox",
+"owner",
+"pagerTelephoneNumber",
+"path",
+"pbeWithMD5AndCast5CBC",
+"personalSignature",
+"personalTitle",
+"photo",
+"physicalDeliveryOfficeName",
+"pilot",
+"pilotAttributeSyntax",
+"pilotAttributeType",
+"pilotAttributeType27",
+"pilotDSA",
+"pilotGroups",
+"pilotObject",
+"pilotObjectClass",
+"pilotOrganization",
+"pilotPerson",
+"pkInitClientAuth",
+"pkInitKDC",
+"pkcs",
+"pkcs1",
+"pkcs3",
+"pkcs5",
+"pkcs7",
+"pkcs7-data",
+"pkcs7-digestData",
+"pkcs7-encryptedData",
+"pkcs7-envelopedData",
+"pkcs7-signedAndEnvelopedData",
+"pkcs7-signedData",
+"pkcs8ShroudedKeyBag",
+"pkcs9",
+"policyConstraints",
+"policyMappings",
+"postOfficeBox",
+"postalAddress",
+"postalCode",
+"ppBasis",
+"preferredDeliveryMethod",
+"presentationAddress",
+"prf-gostr3411-94",
+"prime-field",
+"prime192v1",
+"prime192v2",
+"prime192v3",
+"prime239v1",
+"prime239v2",
+"prime239v3",
+"prime256v1",
+"private",
+"privateKeyUsagePeriod",
+"protocolInformation",
+"proxyCertInfo",
+"pseudonym",
+"pss",
+"qcStatements",
+"qualityLabelledData",
+"rFC822localPart",
+"registeredAddress",
+"role",
+"roleOccupant",
+"room",
+"roomNumber",
+"rsaEncryption",
+"rsaOAEPEncryptionSET",
+"rsaSignature",
+"rsadsi",
+"sOARecord",
+"safeContentsBag",
+"sbgp-autonomousSysNum",
+"sbgp-ipAddrBlock",
+"sbgp-routerIdentifier",
+"sdsiCertificate",
+"searchGuide",
+"secp112r1",
+"secp112r2",
+"secp128r1",
+"secp128r2",
+"secp160k1",
+"secp160r1",
+"secp160r2",
+"secp192k1",
+"secp224k1",
+"secp224r1",
+"secp256k1",
+"secp384r1",
+"secp521r1",
+"secretBag",
+"secretary",
+"sect113r1",
+"sect113r2",
+"sect131r1",
+"sect131r2",
+"sect163k1",
+"sect163r1",
+"sect163r2",
+"sect193r1",
+"sect193r2",
+"sect233k1",
+"sect233r1",
+"sect239k1",
+"sect283k1",
+"sect283r1",
+"sect409k1",
+"sect409r1",
+"sect571k1",
+"sect571r1",
+"secureShellClient",
+"secureShellServer",
+"security",
+"seeAlso",
+"selected-attribute-types",
+"sendOwner",
+"sendProxiedOwner",
+"sendProxiedRouter",
+"sendRouter",
+"serialNumber",
+"serverAuth",
+"serviceLocator",
+"set-addPolicy",
+"set-attr",
+"set-brand",
+"set-brand-AmericanExpress",
+"set-brand-Diners",
+"set-brand-IATA-ATA",
+"set-brand-JCB",
+"set-brand-MasterCard",
+"set-brand-Novus",
+"set-brand-Visa",
+"set-certExt",
+"set-ctype",
+"set-msgExt",
+"set-policy",
+"set-policy-root",
+"set-rootKeyThumb",
+"setAttr-Cert",
+"setAttr-GenCryptgrm",
+"setAttr-IssCap",
+"setAttr-IssCap-CVM",
+"setAttr-IssCap-Sig",
+"setAttr-IssCap-T2",
+"setAttr-PGWYcap",
+"setAttr-SecDevSig",
+"setAttr-T2Enc",
+"setAttr-T2cleartxt",
+"setAttr-TokICCsig",
+"setAttr-Token-B0Prime",
+"setAttr-Token-EMV",
+"setAttr-TokenType",
+"setCext-IssuerCapabilities",
+"setCext-PGWYcapabilities",
+"setCext-TokenIdentifier",
+"setCext-TokenType",
+"setCext-Track2Data",
+"setCext-cCertRequired",
+"setCext-certType",
+"setCext-hashedRoot",
+"setCext-merchData",
+"setCext-setExt",
+"setCext-setQualf",
+"setCext-tunneling",
+"setct-AcqCardCodeMsg",
+"setct-AcqCardCodeMsgTBE",
+"setct-AuthReqTBE",
+"setct-AuthReqTBS",
+"setct-AuthResBaggage",
+"setct-AuthResTBE",
+"setct-AuthResTBEX",
+"setct-AuthResTBS",
+"setct-AuthResTBSX",
+"setct-AuthRevReqBaggage",
+"setct-AuthRevReqTBE",
+"setct-AuthRevReqTBS",
+"setct-AuthRevResBaggage",
+"setct-AuthRevResData",
+"setct-AuthRevResTBE",
+"setct-AuthRevResTBEB",
+"setct-AuthRevResTBS",
+"setct-AuthTokenTBE",
+"setct-AuthTokenTBS",
+"setct-BCIDistributionTBS",
+"setct-BatchAdminReqData",
+"setct-BatchAdminReqTBE",
+"setct-BatchAdminResData",
+"setct-BatchAdminResTBE",
+"setct-CRLNotificationResTBS",
+"setct-CRLNotificationTBS",
+"setct-CapReqTBE",
+"setct-CapReqTBEX",
+"setct-CapReqTBS",
+"setct-CapReqTBSX",
+"setct-CapResData",
+"setct-CapResTBE",
+"setct-CapRevReqTBE",
+"setct-CapRevReqTBEX",
+"setct-CapRevReqTBS",
+"setct-CapRevReqTBSX",
+"setct-CapRevResData",
+"setct-CapRevResTBE",
+"setct-CapTokenData",
+"setct-CapTokenSeq",
+"setct-CapTokenTBE",
+"setct-CapTokenTBEX",
+"setct-CapTokenTBS",
+"setct-CardCInitResTBS",
+"setct-CertInqReqTBS",
+"setct-CertReqData",
+"setct-CertReqTBE",
+"setct-CertReqTBEX",
+"setct-CertReqTBS",
+"setct-CertResData",
+"setct-CertResTBE",
+"setct-CredReqTBE",
+"setct-CredReqTBEX",
+"setct-CredReqTBS",
+"setct-CredReqTBSX",
+"setct-CredResData",
+"setct-CredResTBE",
+"setct-CredRevReqTBE",
+"setct-CredRevReqTBEX",
+"setct-CredRevReqTBS",
+"setct-CredRevReqTBSX",
+"setct-CredRevResData",
+"setct-CredRevResTBE",
+"setct-ErrorTBS",
+"setct-HODInput",
+"setct-MeAqCInitResTBS",
+"setct-OIData",
+"setct-PANData",
+"setct-PANOnly",
+"setct-PANToken",
+"setct-PCertReqData",
+"setct-PCertResTBS",
+"setct-PI",
+"setct-PI-TBS",
+"setct-PIData",
+"setct-PIDataUnsigned",
+"setct-PIDualSignedTBE",
+"setct-PIUnsignedTBE",
+"setct-PInitResData",
+"setct-PResData",
+"setct-RegFormReqTBE",
+"setct-RegFormResTBS",
+"setext-cv",
+"setext-genCrypt",
+"setext-miAuth",
+"setext-pinAny",
+"setext-pinSecure",
+"setext-track2",
+"signingTime",
+"simpleSecurityObject",
+"singleLevelQuality",
+"snmpv2",
+"street",
+"subjectAltName",
+"subjectDirectoryAttributes",
+"subjectInfoAccess",
+"subjectKeyIdentifier",
+"subjectSignTool",
+"subtreeMaximumQuality",
+"subtreeMinimumQuality",
+"supportedAlgorithms",
+"supportedApplicationContext",
+"targetInformation",
+"telephoneNumber",
+"teletexTerminalIdentifier",
+"telexNumber",
+"textEncodedORAddress",
+"textNotice",
+"timeStamping",
+"title",
+"tlsfeature",
+"tpBasis",
+"trustRoot",
+"ucl",
+"uid",
+"uniqueMember",
+"unstructuredAddress",
+"unstructuredName",
+"userCertificate",
+"userClass",
+"userPassword",
+"valid",
+"wap",
+"wap-wsg",
+"wap-wsg-idm-ecid-wtls1",
+"wap-wsg-idm-ecid-wtls10",
+"wap-wsg-idm-ecid-wtls11",
+"wap-wsg-idm-ecid-wtls12",
+"wap-wsg-idm-ecid-wtls3",
+"wap-wsg-idm-ecid-wtls4",
+"wap-wsg-idm-ecid-wtls5",
+"wap-wsg-idm-ecid-wtls6",
+"wap-wsg-idm-ecid-wtls7",
+"wap-wsg-idm-ecid-wtls8",
+"wap-wsg-idm-ecid-wtls9",
+"whirlpool",
+"x121Address",
+"x500UniqueIdentifier",
+"x509Certificate",
+"x509Crl",
+};
diff --git a/projects/openvpn/project.yaml b/projects/openvpn/project.yaml
new file mode 100644
index 0000000..ee352d9
--- /dev/null
+++ b/projects/openvpn/project.yaml
@@ -0,0 +1,6 @@
+homepage: "http://community.openvpn.net"
+language: c
+primary_contact: "arne@rfc2549.org"
+main_repo: "https://github.com/OpenVPN/openvpn"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/openvswitch/Dockerfile b/projects/openvswitch/Dockerfile
index f7c149f..65a4ea4 100644
--- a/projects/openvswitch/Dockerfile
+++ b/projects/openvswitch/Dockerfile
@@ -17,7 +17,7 @@
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y make autoconf automake \
     libtool python python3-pip \
-    libz-dev libssl-dev libssl1.0.0 wget
+    libz-dev libssl-dev libssl1.1 wget
 RUN pip3 install six
 RUN git clone --depth 1 https://github.com/openvswitch/ovs.git openvswitch
 RUN git clone --depth 1 https://github.com/openvswitch/ovs-fuzzing-corpus.git \
diff --git a/projects/openvswitch/project.yaml b/projects/openvswitch/project.yaml
index 4ee3e96..5a25f13 100644
--- a/projects/openvswitch/project.yaml
+++ b/projects/openvswitch/project.yaml
@@ -11,6 +11,7 @@
   - "ilya.maximets@gmail.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/openvswitch/ovs.git'
+main_repo: 'https://github.com/openvswitch/ovs.git'
\ No newline at end of file
diff --git a/projects/openweave/Dockerfile b/projects/openweave/Dockerfile
new file mode 100644
index 0000000..2c940a4
--- /dev/null
+++ b/projects/openweave/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y python3-pip python-setuptools bridge-utils \
+  libglib2.0-dev libdbus-1-dev libudev-dev \
+  libical-dev libreadline-dev udev \
+  libtool autoconf automake systemd
+RUN pip3 install --user google-cloud googleapis-common-protos grpcio protobuf pycryptodomex
+RUN cpan -i Text::Template
+RUN git clone --depth 1 https://github.com/openweave/openweave-core
+WORKDIR $SRC/openweave-core
+COPY build.sh $SRC/
+COPY patch.diff $SRC/
diff --git a/projects/openweave/build.sh b/projects/openweave/build.sh
new file mode 100755
index 0000000..9b366d2
--- /dev/null
+++ b/projects/openweave/build.sh
@@ -0,0 +1,66 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+git apply  --ignore-space-change --ignore-whitespace $SRC/patch.diff
+
+function copy_lib
+    {
+    local fuzzer_path=$1
+    local lib=$2
+    cp $(ldd ${fuzzer_path} | grep "${lib}" | awk '{ print $3 }') ${OUT}/lib
+    }
+
+mkdir -p $OUT/lib
+
+if [ "$SANITIZER" = "coverage" ]
+then
+    # so that we do not get openssl
+    export CXXFLAGS="$CXXFLAGS -fsanitize=fuzzer-no-link,address"
+    export CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link,address"
+fi
+
+# build project
+./bootstrap
+# java fails with Source option 6 is no longer supported. Use 7 or later.
+./configure --disable-java --enable-fuzzing --disable-shared
+
+# patch bluez
+sed -i 's/sys\/socket.h>/sys\/socket.h>\n#include <linux\/sockios.h>/g' ./third_party/bluez/repo/tools/l2test.c
+sed -i 's/sys\/stat.h>/sys\/stat.h>\n#include <linux\/sockios.h>/g' ./third_party/bluez/repo/tools/rctest.c
+
+# OpenSSL now declares RAND_bytes so we must patch
+find ./src/test-apps/fuzz/ -name "FuzzP*.cpp" -exec sed -i 's/RAND_bytes/RAND_bytes2/g' {} \;
+
+make -j$(nproc)
+
+find src/test-apps/fuzz/ -type f -executable -name "Fuzz*" | while read i; do
+    patchelf --set-rpath '$ORIGIN/lib' ${i}
+    copy_lib ${i} libglib
+    copy_lib ${i} libdbus
+    cp ${i} $OUT/
+done
+
+# build corpus
+ls $SRC/openweave-core/src/test-apps/fuzz/corpus/ | while read f; do
+    zip -j $OUT/${f}_seed_corpus.zip $SRC/openweave-core/src/test-apps/fuzz/corpus/${f}/*;
+done
+
+cd $OUT/
+ls *_seed_corpus.zip | grep PASE | while read c; do
+    cp $c Fuzz$c;
+done
+
diff --git a/projects/openweave/patch.diff b/projects/openweave/patch.diff
new file mode 100644
index 0000000..c1ce520
--- /dev/null
+++ b/projects/openweave/patch.diff
@@ -0,0 +1,48 @@
+diff --git a/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp b/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp
+index 7a6cb42..c05caae 100644
+--- a/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp
++++ b/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp
+@@ -53,8 +53,9 @@ WEAVE_ERROR InitSecureRandomDataSource(nl::Weave::Crypto::EntropyFunct entropyFu
+ 
+ WEAVE_ERROR GetSecureRandomData(uint8_t *buf, uint16_t len)
+ {
+-    if (RAND_bytes((unsigned char *)buf, (int)len) != 1)
+-        return WEAVE_ERROR_RANDOM_DATA_UNAVAILABLE;
++    //if (RAND_bytes((unsigned char *)buf, (int)len) != 1)
++    //    return WEAVE_ERROR_RANDOM_DATA_UNAVAILABLE;
++    memset((unsigned char *)buf, 'A', (int)len);
+ 
+     return WEAVE_NO_ERROR;
+ }
+diff --git a/src/tools/weave/CertUtils.cpp b/src/tools/weave/CertUtils.cpp
+index 2bd8097..a1dce36 100644
+--- a/src/tools/weave/CertUtils.cpp
++++ b/src/tools/weave/CertUtils.cpp
+@@ -695,8 +695,9 @@ bool SetCertSerialNumber(X509 *cert)
+     ASN1_INTEGER *snInt = X509_get_serialNumber(cert);
+ 
+     // Generate a random value to be used as the serial number.
+-    if (!RAND_bytes(reinterpret_cast<uint8_t *>(&rnd), sizeof(rnd)))
+-        ReportOpenSSLErrorAndExit("RAND_bytes", res = false);
++    //if (!RAND_bytes(reinterpret_cast<uint8_t *>(&rnd), sizeof(rnd)))
++    //    ReportOpenSSLErrorAndExit("RAND_bytes", res = false);
++    memset(reinterpret_cast<uint8_t *>(&rnd), 'A', sizeof(rnd));
+ 
+     // Avoid negative numbers.
+     rnd &= 0x7FFFFFFFFFFFFFFF;
+diff --git a/src/tools/weave/Cmd_GenProvisioningData.cpp b/src/tools/weave/Cmd_GenProvisioningData.cpp
+index 85ca2e2..bd5c18b 100644
+--- a/src/tools/weave/Cmd_GenProvisioningData.cpp
++++ b/src/tools/weave/Cmd_GenProvisioningData.cpp
+@@ -543,8 +543,9 @@ char *GeneratePairingCode(uint32_t pairingCodeLen)
+     }
+ 
+     // Generate random data for the pairing code, excluding the check digit at the end.
+-    if (!RAND_bytes((uint8_t *)pairingCode, pairingCodeLen - 1))
+-        ReportOpenSSLErrorAndExit("Failed to get random data", pairingCode = NULL);
++    //if (!RAND_bytes((uint8_t *)pairingCode, pairingCodeLen - 1))
++    //    ReportOpenSSLErrorAndExit("Failed to get random data", pairingCode = NULL);
++    memset((uint8_t *)pairingCode, 'A', pairingCodeLen - 1);
+ 
+     // Convert the random data to characters in the range 0-9, A-H, J-N, P, R-Y (base-32 alphanumeric, excluding I, O, Q and Z).
+     for (uint32_t i = 0; i < pairingCodeLen - 1; i++)
diff --git a/projects/openweave/project.yaml b/projects/openweave/project.yaml
new file mode 100644
index 0000000..93a53b0
--- /dev/null
+++ b/projects/openweave/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://openweave.io"
+language: c++
+primary_contact: "szewczyk@google.com"
+auto_ccs:
+  - "p.antoine@catenacyber.fr"
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: 'https://github.com/openweave/openweave-core'
diff --git a/projects/osquery/Dockerfile b/projects/osquery/Dockerfile
index c1c8ff5..dc8a715 100755
--- a/projects/osquery/Dockerfile
+++ b/projects/osquery/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update
-RUN apt-get install -y --no-install-recommends python python3 bison flex make wget xz-utils libunwind-dev
+RUN apt-get install -y --no-install-recommends python python3 bison flex make wget xz-utils libunwind-dev lsb-release build-essential libssl-dev
 
 RUN git clone --depth 1 https://github.com/osquery/osquery osquery
 
diff --git a/projects/osquery/build.sh b/projects/osquery/build.sh
index 6b4ae9b..9363011 100755
--- a/projects/osquery/build.sh
+++ b/projects/osquery/build.sh
@@ -17,6 +17,9 @@
 
 PROJECT=osquery
 
+# Ensure xlocale.h is found.
+ln -s /usr/include/locale.h /usr/include/xlocale.h
+
 # Move the project content into the current overlay.
 # CMake builtin 'rename' will attempt a hardlink.
 ( cd / &&\
@@ -39,6 +42,10 @@
   "-DCMAKE_EXE_LINKER_FLAGS=${LIB_FUZZING_ENGINE} -Wl,-rpath,'\$ORIGIN/lib'" \
   ..
 
+# Fix circular definitions
+# See: https://github.com/osquery/osquery/issues/6551
+sed -i 's/AUDIT_FILTER_EXCLUDE/AUDIT_FILTER_EXCLUDE1/g' /src/osquery/libraries/cmake/source/libaudit/src/lib/libaudit.h
+
 # Build harnesses
 cmake --build . -j$(nproc) --target osqueryfuzz-config
 cmake --build . -j$(nproc) --target osqueryfuzz-sqlquery
diff --git a/projects/ots/project.yaml b/projects/ots/project.yaml
index 559eed3..b2d1d76 100644
--- a/projects/ots/project.yaml
+++ b/projects/ots/project.yaml
@@ -12,7 +12,6 @@
   - libfuzzer
   - afl
   - honggfuzz
-  - dataflow
 sanitizers:
   - address
   - undefined
diff --git a/projects/p11-kit/Dockerfile b/projects/p11-kit/Dockerfile
index 5ae7858..d3636ec 100644
--- a/projects/p11-kit/Dockerfile
+++ b/projects/p11-kit/Dockerfile
@@ -15,9 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libtasn1-6-dev libffi-dev
-RUN echo deb http://archive.ubuntu.com/ubuntu/ bionic main >> /etc/apt/sources.list
-RUN apt-get update && apt-get install -y -t bionic gettext autopoint
+RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libtasn1-6-dev libffi-dev gettext autopoint
 RUN git clone --depth 1 https://github.com/p11-glue/p11-kit.git p11-kit
 WORKDIR p11-kit
 COPY build.sh $SRC/
diff --git a/projects/p9/Dockerfile b/projects/p9/Dockerfile
index fbbe65a..0516326 100644
--- a/projects/p9/Dockerfile
+++ b/projects/p9/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 MAINTAINER s@sevki.org
 
 RUN go get -v -u github.com/hugelgupf/p9/...
diff --git a/projects/perfetto/project.yaml b/projects/perfetto/project.yaml
index 8984193..97c5175 100644
--- a/projects/perfetto/project.yaml
+++ b/projects/perfetto/project.yaml
@@ -1,21 +1,26 @@
 homepage: "https://perfetto.dev"
 language: c++
-primary_contact: "fmayer@google.com"
+primary_contact: "hjd@google.com"
 auto_ccs:
   - "hjd@google.com"
   - "lalitm@google.com"
+  - "octaviant@google.com"
   - "perfetto-oss-fuzz@google.com"
   - "primiano@google.com"
   - "rsavitski@google.com"
   - "eseckler@google.com"
+  - "altimin@google.com"
+  - "ddiproietto@google.com"
 vendor_ccs:
   - bcreasey@google.com
   - hamzeh@google.com
   - geuteneier@google.com
-  - hollyhall@google.com
-  - mikelogan@google.com
   - maverickm@google.com
   - warrenwright@google.com
+  - ailport@google.com
+  - kimtony@google.com
+  - faerber@google.com
+  - greendonald@google.com
 fuzzing_engines:
   - libfuzzer
   - honggfuzz
diff --git a/projects/pffft/Dockerfile b/projects/pffft/Dockerfile
index 9442459..f0faf12 100644
--- a/projects/pffft/Dockerfile
+++ b/projects/pffft/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y mercurial python-numpy
+RUN apt-get update && apt-get install -y mercurial python-numpy python
 RUN git clone https://bitbucket.org/jpommier/pffft $SRC/pffft
 WORKDIR pffft
 COPY build.sh $SRC
diff --git a/projects/phmap/Dockerfile b/projects/phmap/Dockerfile
new file mode 100755
index 0000000..e32199a
--- /dev/null
+++ b/projects/phmap/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN git clone https://github.com/greg7mdp/parallel-hashmap
+
+WORKDIR $SRC/parallel-hashmap
+COPY build.sh $SRC/
+COPY phashmap_fuzz.cc $SRC/
diff --git a/projects/phmap/build.sh b/projects/phmap/build.sh
new file mode 100755
index 0000000..ac7cb32
--- /dev/null
+++ b/projects/phmap/build.sh
@@ -0,0 +1,19 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/phashmap_fuzz.cc -I./ -o $OUT/phashmap_fuzz
diff --git a/projects/phmap/phashmap_fuzz.cc b/projects/phmap/phashmap_fuzz.cc
new file mode 100644
index 0000000..d7530d4
--- /dev/null
+++ b/projects/phmap/phashmap_fuzz.cc
@@ -0,0 +1,66 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <iostream>
+#include <bitset>
+#include <cinttypes>
+#include <unistd.h>
+#include "parallel_hashmap/phmap_dump.h"
+#include <fuzzer/FuzzedDataProvider.h>
+
+using phmap::flat_hash_map;
+using namespace std;
+
+void serialise_test(const uint8_t *data, size_t size) {
+    phmap::flat_hash_map<unsigned int, int> table;
+    FuzzedDataProvider fuzzed_data(data, size);
+    const int num_items = fuzzed_data.ConsumeIntegral<int16_t>();
+
+    for (int i=0; i < num_items; ++i)  {
+        table.insert(typename phmap::flat_hash_map<unsigned int, int>::value_type(
+                    fuzzed_data.ConsumeIntegral<uint32_t>(), 
+                    fuzzed_data.ConsumeIntegral<int32_t>()));
+    }
+
+    phmap::BinaryOutputArchive ar_out("/dump.data");
+    table.dump(ar_out);
+
+    //MapType table_in;
+    phmap::flat_hash_map<unsigned int, int> table_in;
+    phmap::BinaryInputArchive ar_in("/dump.data");
+    table_in.load(ar_in);
+
+    if(table == table_in) {
+        unlink("/dump.data");
+        return;
+    }
+    unlink("/dump.data");
+}
+
+void
+test_assignments(const uint8_t *data, size_t size) {
+    phmap::flat_hash_map<std::string, std::string> email;
+    FuzzedDataProvider fuzzed_data(data, size);
+    const int num_items = fuzzed_data.ConsumeIntegral<int16_t>();
+    for (int i=0; i < num_items; ++i) {
+            phmap::flat_hash_map<std::string, std::string>::value_type(
+                    fuzzed_data.ConsumeRandomLengthString(), 
+                    fuzzed_data.ConsumeRandomLengthString());
+    }
+    // Iterate through all of the items.
+    for (const auto& n: email) {}
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    serialise_test(data, size);
+    test_assignments(data, size);
+    return 0;
+}
diff --git a/projects/phmap/project.yaml b/projects/phmap/project.yaml
new file mode 100755
index 0000000..614a5cf
--- /dev/null
+++ b/projects/phmap/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://github.com/greg7mdp/parallel-hashmap"
+main_repo: 'https://github.com/greg7mdp/parallel-hashmap'
+primary_contact: "greg7mdp@gmail.com"
+language: c++
+auto_ccs :
+  - "david@adalogics.com"
diff --git a/projects/php/Dockerfile b/projects/php/Dockerfile
index a2cb115..eaae4fd 100644
--- a/projects/php/Dockerfile
+++ b/projects/php/Dockerfile
@@ -18,6 +18,5 @@
 RUN apt-get update && \
     apt-get install -y autoconf automake libtool bison re2c pkg-config
 RUN git clone --depth 1 --branch master https://github.com/php/php-src.git php-src
-RUN git clone https://github.com/kkos/oniguruma.git php-src/oniguruma
 WORKDIR php-src
 COPY build.sh *.options $SRC/
diff --git a/projects/php/build.sh b/projects/php/build.sh
index fbef489..18a861f 100755
--- a/projects/php/build.sh
+++ b/projects/php/build.sh
@@ -15,28 +15,28 @@
 #
 ################################################################################
 
-# build oniguruma and link statically
-pushd oniguruma
-autoreconf -vfi
-./configure
-make -j$(nproc)
-popd
-export ONIG_CFLAGS="-I$PWD/oniguruma/src"
-export ONIG_LIBS="-L$PWD/oniguruma/src/.libs -l:libonig.a"
-
 # PHP's zend_function union is incompatible with the object-size sanitizer
 export CFLAGS="$CFLAGS -fno-sanitize=object-size"
 export CXXFLAGS="$CXXFLAGS -fno-sanitize=object-size"
 
+# Disable JIT profitability checks.
+export CFLAGS="$CFLAGS -DPROFITABILITY_CHECKS=0"
+
+# Make sure the right assembly files are picked
+BUILD_FLAG=""
+if [ "$ARCHITECTURE" = "i386" ]; then
+    BUILD_FLAG="--build=i686-pc-linux-gnu"
+fi
+
 # build project
 ./buildconf
-./configure \
+./configure $BUILD_FLAG \
     --disable-all \
     --enable-debug-assertions \
     --enable-option-checking=fatal \
     --enable-fuzzer \
     --enable-exif \
-    --enable-mbstring \
+    --enable-opcache \
     --without-pcre-jit \
     --disable-phpdbg \
     --disable-cgi \
@@ -53,7 +53,6 @@
 
 FUZZERS="php-fuzz-json
 php-fuzz-exif
-php-fuzz-mbstring
 php-fuzz-unserialize
 php-fuzz-unserializehash
 php-fuzz-parser
@@ -61,6 +60,19 @@
 for fuzzerName in $FUZZERS; do
 	cp sapi/fuzzer/$fuzzerName $OUT/
 done
+
+# The JIT fuzzer is fundamentally incompatible with memory sanitizer,
+# as that would require the JIT to emit msan instrumentation itself.
+# In practice it is currently also incompatible with ubsan.
+if [ "$SANITIZER" != "memory" ] && [ "$SANITIZER" != "undefined" ]; then
+    cp sapi/fuzzer/php-fuzz-function-jit $OUT/
+    cp sapi/fuzzer/php-fuzz-tracing-jit $OUT/
+
+    # Copy opcache.so extension, which does not support static linking.
+    mkdir -p $OUT/modules
+    cp modules/opcache.so $OUT/modules
+fi
+
 # copy corpora from source
 for fuzzerName in `ls sapi/fuzzer/corpus`; do
 	zip -j $OUT/php-fuzz-${fuzzerName}_seed_corpus.zip sapi/fuzzer/corpus/${fuzzerName}/*
diff --git a/projects/pidgin/Dockerfile b/projects/pidgin/Dockerfile
new file mode 100644
index 0000000..aa93e96
--- /dev/null
+++ b/projects/pidgin/Dockerfile
@@ -0,0 +1,38 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+        make autoconf automake libtool pkg-config \
+        zlib1g-dev zlib1g-dev:i386 liblzma-dev liblzma-dev:i386 \
+        wget intltool  sasl2-bin python3-pip
+RUN pip3 install -U meson ninja
+
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/glib
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
+RUN wget https://sourceforge.net/projects/pidgin/files/Pidgin/2.14.5/pidgin-2.14.5.tar.bz2
+RUN wget ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz
+
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus
+RUN git clone --depth 1 https://github.com/google/fuzzing
+
+WORKDIR $SRC
+
+COPY build.sh \	
+     pidgin_xml_fuzzer.c \
+     pidgin_utils_fuzzer.c \
+     $SRC/
diff --git a/projects/pidgin/build.sh b/projects/pidgin/build.sh
new file mode 100644
index 0000000..33bcf36
--- /dev/null
+++ b/projects/pidgin/build.sh
@@ -0,0 +1,127 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Place to keep dependencies for static linking
+DEPS=/deps
+mkdir ${DEPS}
+
+
+# Build libffi
+cd $SRC
+tar xvfz libffi-3.2.1.tar.gz
+cd libffi-3.2.1
+./configure --disable-shared
+make -j$(nproc)
+export LIBFFI_LIBS="-L/src/libffi-3.2.1 libraries/ -lffi"
+cp ./x86_64-unknown-linux-gnu/.libs/libffi.a ${DEPS}/
+
+
+# Build libxml2
+cd $SRC/libxml2
+./autogen.sh \
+    --disable-shared \
+    --without-debug \
+    --without-ftp \
+    --without-http \
+    --without-legacy \
+    --without-python
+make -j$(nproc)
+make install
+cp .libs/libxml2.a ${DEPS}/
+
+
+# Build glib
+cd $SRC/glib
+GLIB_BUILD=$WORK/meson
+rm -rf $GLIB_BUILD
+mkdir $GLIB_BUILD
+meson $GLIB_BUILD \
+  -Db_lundef=false \
+  -Ddefault_library=static \
+  -Dlibmount=disabled
+ninja -C $GLIB_BUILD
+ninja -C $GLIB_BUILD install
+
+cp ${GLIB_BUILD}/gobject/libgobject-2.0.a ${DEPS}/
+cp ${GLIB_BUILD}/gmodule/libgmodule-2.0.a ${DEPS}/
+cp ${GLIB_BUILD}/glib/libglib-2.0.a ${DEPS}/
+
+
+# Build Pidgin
+cd $SRC 
+tar -xf pidgin-2.14.5.tar.bz2
+mv pidgin-2.14.5 pidgin
+cd pidgin
+./configure --disable-consoleui \
+            --disable-shared \
+            --disable-screensaver \
+            --disable-sm \
+            --disable-gtkspell \
+            --disable-gevolution \
+            --enable-gnutls=no \
+            --disable-gstreamer \
+            --disable-vv \
+            --disable-idn \
+            --disable-meanwhile \
+            --disable-avahi \
+            --disable-dbus \
+            --disable-perl \
+            --disable-tcl \
+            --disable-cyrus-sasl \
+            --disable-gtkui \
+            --enable-nss=no
+make -j$(nproc)
+
+
+# Build fuzzers
+readonly FUZZERS=( \
+  pidgin_xml_fuzzer
+  pidgin_utils_fuzzer
+)
+
+cd libpurple
+cp $SRC/*fuzzer.c .
+
+for fuzzer in "${FUZZERS[@]}"; do
+  $CC $CFLAGS -DHAVE_CONFIG_H \
+    -I. \
+    -I.. \
+    -I${SRC}/glib \
+    -I${SRC}/glib/glib \
+    -I${SRC}/glib/gmodule \
+    -I${GLIB_BUILD} \
+    -I${GLIB_BUILD}/glib \
+    -I/usr/lib/x86_64-linux-gnu/glib-2.0/include \
+    -I/src/pidgin/libpurple/protocols/jabber \
+    -I/usr/local/include/libxml2 \
+    -c $fuzzer.c \
+    -o $fuzzer.o
+
+  $CC $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.o \
+    -o $OUT/$fuzzer \
+    /src/pidgin/libpurple/protocols/jabber/.libs/libjabber.a \
+    ./.libs/libpurple.a \
+    ${DEPS}/libxml2.a \
+    ${DEPS}/libgobject-2.0.a \
+    ${DEPS}/libgmodule-2.0.a \
+    ${DEPS}/libglib-2.0.a \
+    ${DEPS}/libffi.a \
+    -lresolv -lz -llzma
+done
+
+zip $OUT/pidgin_xml_fuzzer_seed_corpus.zip $SRC/go-fuzz-corpus/xml/corpus/*
+cp $SRC/fuzzing/dictionaries/xml.dict $OUT/pidgin_xml_fuzzer.dict
diff --git a/projects/pidgin/pidgin_utils_fuzzer.c b/projects/pidgin/pidgin_utils_fuzzer.c
new file mode 100644
index 0000000..ce386bb
--- /dev/null
+++ b/projects/pidgin/pidgin_utils_fuzzer.c
@@ -0,0 +1,78 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  char *nstr = (char *)malloc(size + 1);
+  if (nstr == NULL) {
+    return 0;
+  }
+  memcpy(nstr, data, size);
+  nstr[size] = '\0';
+
+  guchar *tmp = NULL;
+  gsize retlen;
+
+  if (size % 2 == 0 && strlen(nstr) > 0) {
+    tmp = purple_base16_decode(nstr, &retlen);
+    if (tmp != NULL) {
+      g_free(tmp);
+    }
+  }
+
+  tmp = NULL;
+  tmp = purple_quotedp_decode(nstr, &retlen);
+  if (tmp != NULL) {
+    g_free(tmp);
+  }
+
+  char *tmp2 = NULL;
+  tmp2 = purple_mime_decode_field(nstr);
+  if (tmp2 != NULL) {
+    free(tmp2);
+  }
+
+  purple_str_to_time(nstr, TRUE, NULL, NULL, NULL);
+
+  gchar *xhtml = NULL;
+  gchar *plaintext = NULL;
+  purple_markup_html_to_xhtml(nstr, &xhtml, &plaintext);
+
+  if (xhtml != NULL) {
+    g_free(xhtml);
+  }
+
+  if (plaintext != NULL) {
+    g_free(plaintext);
+  }
+
+  char *tmp3 = purple_markup_strip_html(nstr);
+  if (tmp3 != NULL) {
+    free(tmp3);
+  }
+
+  purple_markup_is_rtl(nstr);
+
+  free(nstr);
+  return 0;
+}
diff --git a/projects/pidgin/pidgin_xml_fuzzer.c b/projects/pidgin/pidgin_xml_fuzzer.c
new file mode 100644
index 0000000..a91034a
--- /dev/null
+++ b/projects/pidgin/pidgin_xml_fuzzer.c
@@ -0,0 +1,55 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmlnode.h"
+#include "caps.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  char *malicious_xml = (char *)malloc(size + 1);
+  if (malicious_xml == NULL) {
+    return 0;
+  }
+  memcpy(malicious_xml, data, size);
+  malicious_xml[size] = '\0';
+
+  xmlnode *isc = xmlnode_from_str(malicious_xml, size+1);
+  if (isc != NULL) {    
+    xmlnode_set_attrib(isc, "name", "query");
+    
+    // Parse Jabber caps
+    JabberCapsClientInfo *info = jabber_caps_parse_client_info(isc);
+    gchar *got_hash = jabber_caps_calculate_hash(info, ("sha1"));
+
+    // Insert a child
+    xmlnode *child = xmlnode_new_child(isc, "query");
+    xmlnode_insert_child(isc, child);
+
+    // Get data
+    char *retrieved_data = xmlnode_get_data(isc);
+    char *retrieved_data_unescaped = xmlnode_get_data_unescaped(isc);
+
+    xmlnode_free(isc);
+  }
+
+  free(malicious_xml);
+  return 0;
+}
\ No newline at end of file
diff --git a/projects/pidgin/project.yaml b/projects/pidgin/project.yaml
index d94a268..6756a8c 100644
--- a/projects/pidgin/project.yaml
+++ b/projects/pidgin/project.yaml
@@ -1,2 +1,7 @@
 homepage: "https://www.pidgin.im/"
 primary_contact: "gary.kramlich@gmail.com"
+language: c
+auto_ccs:
+  - "quantum.analyst@gmail.com"
+  - "rekkanoryo.guifications@gmail.com"
+main_repo: 'https://sourceforge.net/projects/pidgin/files/Pidgin/2.14.4/pidgin-2.14.4.tar.bz2'
diff --git a/projects/pillow/Dockerfile b/projects/pillow/Dockerfile
index ab90895..fc4b306 100644
--- a/projects/pillow/Dockerfile
+++ b/projects/pillow/Dockerfile
@@ -14,32 +14,20 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN git clone --depth 1 https://github.com/google/fuzzing
-RUN cat fuzzing/dictionaries/bmp.dict \
-        fuzzing/dictionaries/dds.dict \
-        fuzzing/dictionaries/gif.dict \
-        fuzzing/dictionaries/icns.dict \
-        fuzzing/dictionaries/jpeg.dict \
-        fuzzing/dictionaries/jpeg2000.dict \
-        fuzzing/dictionaries/pbm.dict \
-        fuzzing/dictionaries/png.dict \
-        fuzzing/dictionaries/psd.dict \
-        fuzzing/dictionaries/tiff.dict \
-        fuzzing/dictionaries/webp.dict \
-      > $OUT/fuzz_pillow.dict
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
 # library build dependencies
 RUN apt-get update && \
     apt-get install -y \
       libxau-dev \
       pkg-config \
-      rsync \
-      zlib1g-dev 
+      rsync
 
 RUN git clone --depth 1 https://github.com/python-pillow/Pillow
 RUN git clone --depth 1 https://github.com/python-pillow/pillow-wheels
 
+RUN $SRC/Pillow/Tests/oss-fuzz/build_dictionaries.sh
+
 COPY build_depends.sh $SRC
 
 RUN ln -s /usr/local/bin/python3 /usr/local/bin/python \
@@ -58,6 +46,6 @@
 RUN apt-get install -y \
      python3-tk \
      tcl8.6-dev \
-     tk8.6-dev 
+     tk8.6-dev
 
 WORKDIR $SRC/Pillow
diff --git a/projects/pillow/build.sh b/projects/pillow/build.sh
index e7dac34..4656c7c 100644
--- a/projects/pillow/build.sh
+++ b/projects/pillow/build.sh
@@ -15,33 +15,4 @@
 #
 ################################################################################
 
-python3 setup.py build --build-base=/tmp/build install
-
-# Build fuzzers in $OUT.
-for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
-  fuzzer_basename=$(basename -s .py $fuzzer)
-  fuzzer_package=${fuzzer_basename}.pkg
-  pyinstaller \
-      --add-binary /usr/local/lib/libjpeg.so.9:. \
-      --add-binary /usr/local/lib/libfreetype.so.6:. \
-      --add-binary /usr/local/lib/liblcms2.so.2:. \
-      --add-binary /usr/local/lib/libopenjp2.so.7:. \
-      --add-binary /usr/local/lib/libpng16.so.16:. \
-      --add-binary /usr/local/lib/libtiff.so.5:. \
-      --add-binary /usr/local/lib/libwebp.so.7:. \
-      --add-binary /usr/local/lib/libwebpdemux.so.2:. \
-      --add-binary /usr/local/lib/libwebpmux.so.3:. \
-      --add-binary /usr/local/lib/libxcb.so.1:. \
-      --distpath $OUT --onefile --name $fuzzer_package $fuzzer
-
-  # Create execution wrapper.
-  echo "#!/bin/sh
-# LLVMFuzzerTestOneInput for fuzzer detection.
-this_dir=\$(dirname \"\$0\")
-LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
-ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
-\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
-done
-
-find Tests/images Tests/icc Tests/fonts -print | zip -q $OUT/fuzz_pillow_seed_corpus.zip -@
+./Tests/oss-fuzz/build.sh
diff --git a/projects/pistache/Dockerfile b/projects/pistache/Dockerfile
new file mode 100644
index 0000000..7071af9
--- /dev/null
+++ b/projects/pistache/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool
+RUN pip3 install meson==0.53.0 ninja
+RUN git clone --depth 1 https://github.com/pistacheio/pistache pistache
+WORKDIR pistache
+COPY build.sh $SRC/
diff --git a/projects/pistache/build.sh b/projects/pistache/build.sh
new file mode 100755
index 0000000..ea8fd17
--- /dev/null
+++ b/projects/pistache/build.sh
@@ -0,0 +1,22 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir build && cd build
+meson --default-library=static ../
+ninja
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzz_parsers \
+    -std=c++17 -I../include/ ../tests/fuzzers/fuzz_parser.cpp ./src/libpistache.a
diff --git a/projects/pistache/project.yaml b/projects/pistache/project.yaml
new file mode 100644
index 0000000..8da315c
--- /dev/null
+++ b/projects/pistache/project.yaml
@@ -0,0 +1,10 @@
+homepage: "http://pistache.io"
+language: c++
+primary_contact: "kip@thevertigo.com"
+main_repo: "https://github.com/pistacheio/pistache"
+auto_ccs:
+ - "dennis.jenkins.75@gmail.com"
+ - "andrea@pappacoda.it"
+ - "hyperxor@protonmail.com"
+ - "auquetal@gmail.com"
+ - "david@adalogics.com"
diff --git a/projects/poco/Dockerfile b/projects/poco/Dockerfile
new file mode 100644
index 0000000..c9f0b2f
--- /dev/null
+++ b/projects/poco/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y openssl libssl-dev git make cmake libssl-dev 
+RUN git clone --depth 1 -b poco-1.11.0 https://github.com/pocoproject/poco
+WORKDIR $SRC/poco
+COPY build.sh \
+     json_parse_fuzzer.cc \
+     $SRC/
diff --git a/projects/poco/build.sh b/projects/poco/build.sh
new file mode 100755
index 0000000..6d0d792
--- /dev/null
+++ b/projects/poco/build.sh
@@ -0,0 +1,37 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir cmake-build
+cd cmake-build
+cmake -DBUILD_SHARED_LIBS=OFF \
+      -DENABLE_TESTS=OFF \
+      ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DPOCO_ENABLE_CPP11 -DPOCO_ENABLE_CPP14 \
+    -DPOCO_HAVE_FD_EPOLL -DPOCO_OS_FAMILY_UNIX \
+    -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \
+    -D_REENTRANT -D_THREAD_SAFE -D_XOPEN_SOURCE=500 \
+    -I/src/poco/JSON/include \
+    -I/src/poco/Foundation/include \
+    -O2 -g -DNDEBUG -std=gnu++14 \
+    -o json_fuzzer.o -c $SRC/json_parse_fuzzer.cc
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE json_fuzzer.o \
+    ./lib/libPocoJSON.a \
+    ./lib/libPocoFoundation.a \
+    -o $OUT/json_parser_fuzzer -lpthread -ldl -lrt
diff --git a/projects/poco/json_parse_fuzzer.cc b/projects/poco/json_parse_fuzzer.cc
new file mode 100644
index 0000000..e03ff2f
--- /dev/null
+++ b/projects/poco/json_parse_fuzzer.cc
@@ -0,0 +1,30 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Parser.h"
+#include "Poco/JSON/ParserImpl.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  std::string json(reinterpret_cast<const char *>(data), size);
+  Poco::JSON::Parser parser;
+
+  Poco::Dynamic::Var result;
+  try {
+    result = parser.parse(json);
+  } catch (Poco::Exception &e) {
+    return 0;
+  } catch (const std::exception &e) {
+    return 0;
+  }
+  return 0;
+}
diff --git a/projects/poco/project.yaml b/projects/poco/project.yaml
new file mode 100644
index 0000000..79e07d7
--- /dev/null
+++ b/projects/poco/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/pocoproject/poco"
+main_repo: "https://github.com/pocoproject/poco"
+language: c++
+primary_contact: "guenter@pocoproject.org"
+auto_ccs:
+  - "Adam@adalogics.com"
+  - "alex@pocoproject.org"
+sanitizers:
+  - address
+  - undefined
+  - memory
diff --git a/projects/poppler/Dockerfile b/projects/poppler/Dockerfile
index c1b0355..dd7160d 100644
--- a/projects/poppler/Dockerfile
+++ b/projects/poppler/Dockerfile
@@ -26,10 +26,10 @@
 RUN git clone --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig.git
 RUN git clone --depth 1 https://gitlab.freedesktop.org/cairo/cairo.git
 RUN git clone --depth 1 --branch=5.15 git://code.qt.io/qt/qtbase.git
-ADD http://ftp.gnome.org/pub/gnome/sources/pango/1.48/pango-1.48.0.tar.xz $SRC
-RUN tar xvJf $SRC/pango-1.48.0.tar.xz
-ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.64/glib-2.64.2.tar.xz $SRC
-RUN tar xvJf $SRC/glib-2.64.2.tar.xz
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/pango.git
+ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.70/glib-2.70.0.tar.xz $SRC
+RUN tar xvJf $SRC/glib-2.70.0.tar.xz
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2
 RUN git clone --depth 1 --single-branch https://gitlab.freedesktop.org/poppler/poppler.git
 
 RUN git clone --depth 1 https://github.com/mozilla/pdf.js pdf.js && \
diff --git a/projects/poppler/build.sh b/projects/poppler/build.sh
index 23692dd..02915b7 100755
--- a/projects/poppler/build.sh
+++ b/projects/poppler/build.sh
@@ -27,6 +27,14 @@
 rm -rf $BUILD
 mkdir -p $BUILD
 
+# Install Boost headers
+cd $SRC/
+tar jxf boost_1_76_0.tar.bz2
+cd boost_1_76_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+cp -R boost/ /usr/include/
+
 pushd $SRC/zlib
 CFLAGS=-fPIC ./configure --static --prefix=$PREFIX
 make install -j$(nproc)
@@ -38,7 +46,7 @@
 make install
 
 pushd $SRC/Little-CMS
-./configure --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+./autogen.sh --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
 make -j$(nproc)
 make install
 
@@ -59,7 +67,7 @@
     ninja -C _builddir install
     popd
 
-    pushd $SRC/glib-2.64.2
+    pushd $SRC/glib-2.70.0
     meson \
         --prefix=$PREFIX \
         --libdir=lib \
@@ -89,7 +97,7 @@
     ninja -C _builddir install
     popd
 
-    pushd $SRC/pango-1.48.0
+    pushd $SRC/pango
     meson \
         -Ddefault_library=static \
         --prefix=$PREFIX \
diff --git a/projects/poppler/project.yaml b/projects/poppler/project.yaml
index c123796..bb1ae17 100644
--- a/projects/poppler/project.yaml
+++ b/projects/poppler/project.yaml
@@ -3,9 +3,10 @@
 primary_contact: tsdgeos@gmail.com
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 auto_ccs:
   - jonathan@titanous.com
   - adam.reichold@t-online.de
-main_repo: 'https://anongit.freedesktop.org/git/poppler/poppler.git'
+main_repo: 'https://anongit.freedesktop.org/git/poppler/poppler.git'
\ No newline at end of file
diff --git a/projects/postgis/Dockerfile b/projects/postgis/Dockerfile
index 67b7a69..2c55c54 100644
--- a/projects/postgis/Dockerfile
+++ b/projects/postgis/Dockerfile
@@ -15,8 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN echo deb http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse >> /etc/apt/sources.list
-RUN apt-get update && apt-get install -y make autoconf automake libtool g++ postgresql-server-dev-10 libgeos-dev libproj-dev libxml2-dev pkg-config libjson-c-dev
+RUN apt-get update && apt-get install -y make autoconf automake libtool g++ postgresql-server-dev-12 libgeos-dev libproj-dev libxml2-dev pkg-config libjson-c-dev
 RUN git clone --depth 1 https://git.osgeo.org/gitea/postgis/postgis.git postgis
 WORKDIR postgis
 COPY build.sh $SRC/
diff --git a/projects/postgresql/add_fuzzers.diff b/projects/postgresql/add_fuzzers.diff
index 86b106c..5674bc3 100644
--- a/projects/postgresql/add_fuzzers.diff
+++ b/projects/postgresql/add_fuzzers.diff
@@ -1,25 +1,27 @@
 diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
-index cb5a96117f..c9b4880085 100644
+index 0775abe35d..f53b3580b3 100644
 --- a/src/backend/tcop/postgres.c
 +++ b/src/backend/tcop/postgres.c
-@@ -102,6 +102,9 @@ int			max_stack_depth = 100;
- /* wait N seconds to allow attach from a debugger */
- int			PostAuthDelay = 0;
+@@ -105,6 +105,11 @@ int			PostAuthDelay = 0;
+ /* Time between checks that the client is still connected. */
+ int			client_connection_check_interval = 0;
  
 +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 +bool        fuzzer_first_run = true;
 +#endif
- 
- 
++
++
  /* ----------------
-@@ -507,10 +510,15 @@ ReadCommand(StringInfo inBuf)
+  *		private typedefs etc
+  * ----------------
+@@ -471,11 +476,14 @@ static int
+ ReadCommand(StringInfo inBuf)
  {
  	int			result;
- 
+-
 +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+    result = SocketBackend(inBuf);
++	result = SocketBackend(inBuf);
 +#else
-+
  	if (whereToSendOutput == DestRemote)
  		result = SocketBackend(inBuf);
  	else
@@ -28,19 +30,19 @@
  	return result;
  }
  
-@@ -3846,6 +3854,11 @@ PostgresMain(int argc, char *argv[],
+@@ -4021,6 +4029,11 @@ PostgresMain(const char *dbname, const char *username)
  	bool		idle_in_transaction_timeout_enabled = false;
  	bool		idle_session_timeout_enabled = false;
  
 +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+        if(fuzzer_first_run)
-+                {
++       if(fuzzer_first_run)
++       {
 +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
 +
- 	/* Initialize startup process environment if necessary. */
- 	if (!IsUnderPostmaster)
- 		InitStandaloneProcess(argv[0]);
-@@ -4207,6 +4220,11 @@ PostgresMain(int argc, char *argv[],
+ 	AssertArg(dbname != NULL);
+ 	AssertArg(username != NULL);
+ 
+@@ -4312,6 +4325,11 @@ PostgresMain(const char *dbname, const char *username)
  	if (!ignore_till_sync)
  		send_ready_for_query = true;	/* initially, or after error */
  
@@ -53,11 +55,11 @@
  	 * Non-error queries loop here.
  	 */
 diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
-index 80c2672461..c16e0423c5 100644
+index 2af87ee3bd..825bb70532 100644
 --- a/src/backend/utils/error/elog.c
 +++ b/src/backend/utils/error/elog.c
-@@ -600,7 +600,9 @@ errfinish(const char *filename, int lineno, const char *funcname)
- 		pq_endcopyout(true);
+@@ -594,7 +594,9 @@ errfinish(const char *filename, int lineno, const char *funcname)
+ 	}
  
  	/* Emit the message to the right places */
 +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
diff --git a/projects/postgresql/build.sh b/projects/postgresql/build.sh
index 12fb754..ee56ecd 100644
--- a/projects/postgresql/build.sh
+++ b/projects/postgresql/build.sh
@@ -15,7 +15,7 @@
 #
 ################################################################################
 cp -r $SRC/fuzzer src/backend/
-git apply ../add_fuzzers.diff
+git apply --ignore-space-change --ignore-whitespace  ../add_fuzzers.diff
 
 useradd fuzzuser
 chown -R fuzzuser .
@@ -35,5 +35,12 @@
 make
 cd src/backend/fuzzer
 make fuzzer
+#if [ "$FUZZING_ENGINE" = "afl" ]
+#then
+rm protocol_fuzzer
+#fi
 cp *_fuzzer $OUT/
 cp $SRC/postgresql_fuzzer_seed_corpus.zip $OUT/
+
+# Temporary fix. Todo: David fix this.
+#rm $OUT/protocol_fuzzer
diff --git a/projects/postgresql/fuzzer/fuzzer_initialize.c b/projects/postgresql/fuzzer/fuzzer_initialize.c
index 0ab9d7d..33f8278 100644
--- a/projects/postgresql/fuzzer/fuzzer_initialize.c
+++ b/projects/postgresql/fuzzer/fuzzer_initialize.c
@@ -82,8 +82,9 @@
   LocalProcessControlFile(false);
   InitializeMaxBackends();
 		 
-  BaseInit();
+  CreateSharedMemoryAndSemaphores();
   InitProcess();
+  BaseInit();
   PG_SETMASK(&UnBlockSig);
   InitPostgres("dbfuzz", InvalidOid, username, InvalidOid, NULL, false);
  
diff --git a/projects/postgresql/fuzzer/protocol_fuzzer.c b/projects/postgresql/fuzzer/protocol_fuzzer.c
index 7621644..3efe8e4 100644
--- a/projects/postgresql/fuzzer/protocol_fuzzer.c
+++ b/projects/postgresql/fuzzer/protocol_fuzzer.c
@@ -74,7 +74,7 @@
 	MemoryContextInit();
 	if(!sigsetjmp(postgre_exit, 0)){
 		postgre_started = true;
-		PostgresMain(5, av, "dbfuzz", "fuzzuser");
+		PostgresSingleUserMain(5, av, "fuzzuser");
 	}
 	pq_endmsgread();
 	return 0;
@@ -106,7 +106,7 @@
 
 	if(!sigsetjmp(postgre_exit, 0)){
 		postgre_started = true;
-		PostgresMain(5, av, "dbfuzz", "fuzzuser");
+		PostgresSingleUserMain(5, av, "fuzzuser");
 	}
 	pq_endmsgread();
 	postgre_started = false;
diff --git a/projects/powerdns/Dockerfile b/projects/powerdns/Dockerfile
index db7614c..6d02406 100644
--- a/projects/powerdns/Dockerfile
+++ b/projects/powerdns/Dockerfile
@@ -20,7 +20,7 @@
 # maintainer for this file
 
 # install required packages to build your project
-RUN add-apt-repository -y ppa:savoury1/boost-defaults-1.71 && apt-get update && apt-get install -y autoconf automake bison dh-autoreconf flex boost1.71-dev libluajit-5.1-dev libedit-dev libprotobuf-dev libssl-dev libtool make pkg-config protobuf-compiler ragel
+RUN apt-get update && apt-get install -y autoconf automake bison dh-autoreconf flex boost1.71-all-dev libluajit-5.1-dev libedit-dev libprotobuf-dev libssl-dev libtool make pkg-config protobuf-compiler ragel
 
 # checkout all sources needed to build your project
 RUN git clone https://github.com/PowerDNS/pdns.git pdns
diff --git a/projects/powerdns/build.sh b/projects/powerdns/build.sh
index b8922c5..7da909a 100644
--- a/projects/powerdns/build.sh
+++ b/projects/powerdns/build.sh
@@ -44,7 +44,21 @@
 cp ../regression-tests/zones/* ../fuzzing/corpus/zones/
 
 # generate the corpus files
-zip -j "${OUT}/fuzz_target_dnsdistcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
-zip -j "${OUT}/fuzz_target_moadnsparser_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
-zip -j "${OUT}/fuzz_target_packetcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
-zip -j "${OUT}/fuzz_target_zoneparsertng_seed_corpus.zip" ../fuzzing/corpus/zones/*
+if [ -d ../fuzzing/corpus/raw-dns-packets/ ]; then
+    zip -j "${OUT}/fuzz_target_dnsdistcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
+fi
+if [ -d ../fuzzing/corpus/txt-records/ ]; then
+    zip -j "${OUT}/fuzz_target_dnslabeltext_parseRFC1035CharString_seed_corpus.zip" ../fuzzing/corpus/txt-records/*
+fi
+if [ -d ../fuzzing/corpus/raw-dns-packets/ ]; then
+    zip -j "${OUT}/fuzz_target_moadnsparser_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
+fi
+if [ -d ../fuzzing/corpus/raw-dns-packets/ ]; then
+    zip -j "${OUT}/fuzz_target_packetcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
+fi
+if [ -d ../fuzzing/corpus/proxy-protocol-raw-packets/ ]; then
+    zip -j "${OUT}/fuzz_target_proxyprotocol_seed_corpus.zip" ../fuzzing/corpus/proxy-protocol-raw-packets/*
+fi
+if [ -d ../fuzzing/corpus/zones/ ]; then
+    zip -j "${OUT}/fuzz_target_zoneparsertng_seed_corpus.zip" ../fuzzing/corpus/zones/*
+fi
diff --git a/projects/proftpd/Dockerfile b/projects/proftpd/Dockerfile
new file mode 100644
index 0000000..fe6b37f
--- /dev/null
+++ b/projects/proftpd/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool \
+  pkg-config cmake check
+RUN git clone --depth 1 https://github.com/proftpd/proftpd
+WORKDIR proftpd
+COPY build.sh fuzzer.c $SRC/
diff --git a/projects/proftpd/build.sh b/projects/proftpd/build.sh
new file mode 100755
index 0000000..2ec6ddc
--- /dev/null
+++ b/projects/proftpd/build.sh
@@ -0,0 +1,46 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+export LDFLAGS="${CFLAGS}"
+./configure --enable-ctrls
+make -j$(nproc)
+
+# We need a few declarations from main.c
+# so we rename main() to main2()
+sed 's/int main(/int main2(/g' -i $SRC/proftpd/src/main.c
+
+# Compile main.c again
+export NEW_CC_FLAG="${CC} ${CFLAGS} -DHAVE_CONFIG_H -DLINUX  -I. -I./include"
+$NEW_CC_FLAG -c src/main.c -o src/main.o
+rm src/ftpdctl.o
+
+find . -name "*.o" -exec ar rcs fuzz_lib.a {} \;
+
+# Build fuzzer(s)
+$NEW_CC_FLAG -c $SRC/fuzzer.c -o fuzzer.o
+$CC $CXXFLAGS $LIB_FUZZING_ENGINE fuzzer.o -o $OUT/fuzzer \
+	src/scoreboard.o \
+	lib/prbase.a \
+	fuzz_lib.a \
+	-L/src/proftpd/lib \
+	-lcrypt -pthread
+
+# Build seed corpus
+cd $SRC
+git clone https://github.com/dvyukov/go-fuzz-corpus
+zip $OUT/fuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/*
+
diff --git a/projects/proftpd/fuzzer.c b/projects/proftpd/fuzzer.c
new file mode 100644
index 0000000..ef86068
--- /dev/null
+++ b/projects/proftpd/fuzzer.c
@@ -0,0 +1,43 @@
+/*
+# Copyright 2021 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "json.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){        
+    char *new_str = (char *)malloc(size+1);
+    if (new_str == NULL) {
+        return 0;
+    }
+    memcpy(new_str, data, size);
+    new_str[size] = '\0';
+
+    pool *p = make_sub_pool(NULL);
+    if (p != NULL) {
+        init_json();        
+        pr_json_object_t *json = pr_json_object_from_text(p, new_str);
+        pr_json_object_free(json);
+        finish_json();
+        destroy_pool(p);
+    }
+
+    free(new_str);
+    return 0;
+}
diff --git a/projects/proftpd/project.yaml b/projects/proftpd/project.yaml
new file mode 100644
index 0000000..f3b5317
--- /dev/null
+++ b/projects/proftpd/project.yaml
@@ -0,0 +1,9 @@
+homepage: "http://www.proftpd.org/"
+main_repo: "https://github.com/proftpd/proftpd"
+language: c
+primary_contact: "castaglian@gmail.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
diff --git a/projects/prometheus/Dockerfile b/projects/prometheus/Dockerfile
index 7e22750..eb9d3bc 100644
--- a/projects/prometheus/Dockerfile
+++ b/projects/prometheus/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 ENV GO111MODULE=on
 RUN git clone https://github.com/prometheus/prometheus $GOPATH/src/github.com/prometheus/prometheus
 COPY build.sh $SRC/
diff --git a/projects/prost/Dockerfile b/projects/prost/Dockerfile
new file mode 100644
index 0000000..d340fe5
--- /dev/null
+++ b/projects/prost/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LL
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+RUN apt-get update && apt-get install -y pkg-config libssl-dev curl libcurl4-openssl-dev ninja-build
+RUN git clone --depth 1 https://github.com/danburkert/prost
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/prost/build.sh b/projects/prost/build.sh
new file mode 100755
index 0000000..4b9c382
--- /dev/null
+++ b/projects/prost/build.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd $SRC/prost
+cargo fuzz build -O 
+cp fuzz/target/x86_64-unknown-linux-gnu/release/proto2 $OUT/
+cp fuzz/target/x86_64-unknown-linux-gnu/release/proto3 $OUT/
diff --git a/projects/prost/project.yaml b/projects/prost/project.yaml
new file mode 100644
index 0000000..49f69f2
--- /dev/null
+++ b/projects/prost/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://crates.io/crates/prost"
+main_repo: "https://github.com/danburkert/prost"
+primary_contact: "dan@danburkert.com"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "david@adalogics.com"
diff --git a/projects/protobuf-c/build.sh b/projects/protobuf-c/build.sh
index 8eda36a..c840065 100755
--- a/projects/protobuf-c/build.sh
+++ b/projects/protobuf-c/build.sh
@@ -46,6 +46,7 @@
 ./configure --enable-static=yes --enable-shared=false PKG_CONFIG_PATH=$SRC/protobuf-install/lib/pkgconfig
 
 make -j$(nproc)
+make install
 
 cd $SRC/fuzzing-headers/
 ./install.sh
@@ -53,6 +54,6 @@
 cd $SRC/protobuf-c-fuzzers/
 cp $SRC/protobuf-c/t/test-full.proto $SRC/protobuf-c-fuzzers/
 export PATH=$PATH:$SRC/protobuf-c/protoc-c
-$PROTOC --c_out=. test-full.proto
+$PROTOC --c_out=. -I. -I/usr/local/include test-full.proto
 $CC $CFLAGS test-full.pb-c.c -I $SRC/protobuf-install -I $SRC/protobuf-c -c -o test-full.pb-c.o
 $CXX $CXXFLAGS fuzzer.cpp -I $SRC/protobuf-install -I $SRC/protobuf-c test-full.pb-c.o $SRC/protobuf-c/protobuf-c/.libs/libprotobuf-c.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer
diff --git a/projects/protobuf-c/project.yaml b/projects/protobuf-c/project.yaml
index 9103f1b..54245ff 100644
--- a/projects/protobuf-c/project.yaml
+++ b/projects/protobuf-c/project.yaml
@@ -5,9 +5,10 @@
   - "ilya.lipnitskiy@gmail.com"
 sanitizers:
  - address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 architectures:
  - x86_64
  - i386
 main_repo: 'https://github.com/protobuf-c/protobuf-c.git'
-coverage_extra_args: -ignore-filename-regex=.*/protobuf-install/.*
+coverage_extra_args: -ignore-filename-regex=.*/protobuf-install/.*
\ No newline at end of file
diff --git a/projects/protobuf-java/Dockerfile b/projects/protobuf-java/Dockerfile
new file mode 100644
index 0000000..b14084f
--- /dev/null
+++ b/projects/protobuf-java/Dockerfile
@@ -0,0 +1,34 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config
+
+RUN curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+    unzip maven.zip -d $SRC/maven && \
+    rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+RUN curl -L -O https://raw.githubusercontent.com/protobuf-c/protobuf-c/39cd58f5ff06048574ed5ce17ee602dc84006162/t/test-full.proto
+
+RUN git clone --depth 1 --recursive https://github.com/protocolbuffers/protobuf.git
+
+COPY build.sh $SRC
+COPY ProtobufFuzzer.java $SRC
+
+WORKDIR $SRC
diff --git a/projects/protobuf-java/ProtobufFuzzer.java b/projects/protobuf-java/ProtobufFuzzer.java
new file mode 100644
index 0000000..3e5e09a
--- /dev/null
+++ b/projects/protobuf-java/ProtobufFuzzer.java
@@ -0,0 +1,33 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import foo.TestFull;
+
+public class ProtobufFuzzer {
+    public static void fuzzerTestOneInput(byte[] input) {
+        try {
+            TestFull.TestMessSubMess.parseFrom(input);
+        } catch (InvalidProtocolBufferException ignored) { }
+        try {
+            TestFull.TestFieldFlags.parseFrom(input);
+        } catch (InvalidProtocolBufferException ignored) { }
+        try {
+            TestFull.TestMessageCheck.parseFrom(input);
+        } catch (InvalidProtocolBufferException ignored) { }
+    }
+}
diff --git a/projects/protobuf-java/build.sh b/projects/protobuf-java/build.sh
new file mode 100755
index 0000000..e5f7363
--- /dev/null
+++ b/projects/protobuf-java/build.sh
@@ -0,0 +1,69 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Build protoc with default options.
+unset CFLAGS CXXFLAGS
+mkdir $SRC/protobuf-install/
+cd $SRC/protobuf/
+./autogen.sh
+./configure --prefix=$SRC/protobuf-install
+make -j$(nproc)
+make install
+
+export PROTOC="$SRC/protobuf-install/bin/protoc"
+
+# Build protobuf-java (requires protoc in source tree).
+cd $SRC/protobuf/java/
+cp $PROTOC $SRC/protobuf/src/
+MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15"
+$MVN package $MAVEN_ARGS
+CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+ -Dexpression=project.version -q -DforceStdout)
+cp "core/target/protobuf-java-$CURRENT_VERSION.jar" $OUT/protobuf-java.jar
+
+# Compile test protos with protoc.
+cd $SRC/
+$PROTOC --java_out=. --proto_path=. test-full.proto
+jar --create --file $OUT/test-full.jar foo/*
+
+ALL_JARS="protobuf-java.jar test-full.jar"
+
+# The classpath at build-time includes the project jars in $OUT as well as the
+# Jazzer API.
+BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
+
+# All .jar and .class files lie in the same directory as the fuzzer at runtime.
+RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
+
+for fuzzer in $(find $SRC -name '*Fuzzer.java'); do
+  fuzzer_basename=$(basename -s .java $fuzzer)
+  javac -cp $BUILD_CLASSPATH $fuzzer
+  cp $SRC/$fuzzer_basename.class $OUT/
+
+  # Create an execution wrapper that executes Jazzer with the correct arguments.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\" \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
+done
+
diff --git a/projects/protobuf-java/project.yaml b/projects/protobuf-java/project.yaml
new file mode 100644
index 0000000..afb45a2
--- /dev/null
+++ b/projects/protobuf-java/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://developers.google.com/protocol-buffers/"
+language: jvm
+primary_contact: "kfm@google.com"
+auto_ccs:
+  - "meumertzheim@code-intelligence.com"
+  - "acozzette@google.com"
+  - "elharo@google.com"
+  - "pzd@google.com"
+  - "sandyzhang@google.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://github.com/protocolbuffers/protobuf"
+sanitizers:
+  - address
diff --git a/projects/protoreflect/Dockerfile b/projects/protoreflect/Dockerfile
new file mode 100644
index 0000000..948b3a5
--- /dev/null
+++ b/projects/protoreflect/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/jhump/protoreflect
+
+COPY fuzz_protoparse.go $SRC/protoreflect/desc/protoparse/
+COPY fuzz_dynamic.go $SRC/protoreflect/proto_decoder/
+
+COPY build.sh $SRC/
+WORKDIR $SRC/protoreflect
diff --git a/projects/protoreflect/build.sh b/projects/protoreflect/build.sh
new file mode 100755
index 0000000..3511f83
--- /dev/null
+++ b/projects/protoreflect/build.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+compile_go_fuzzer github.com/jhump/protoreflect/desc/protoparse FuzzProtoParse fuzz_protoparse
+# compile_go_fuzzer github.com/jhump/protoreflect/proto_decoder Fuzz fuzz_dynamic
+
diff --git a/projects/protoreflect/fuzz_dynamic.go b/projects/protoreflect/fuzz_dynamic.go
new file mode 100644
index 0000000..ba26fe2
--- /dev/null
+++ b/projects/protoreflect/fuzz_dynamic.go
@@ -0,0 +1,33 @@
+package proto_decoder
+
+import (
+	"github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/ptypes/empty"
+	"github.com/jhump/protoreflect/desc"
+	"github.com/jhump/protoreflect/desc/builder"
+	"github.com/jhump/protoreflect/dynamic"
+)
+
+func Fuzz(data []byte) int {
+	d, err := desc.LoadMessageDescriptorForMessage(&empty.Empty{})
+	if err != nil {
+		panic(err)
+	}
+	mb, err := builder.FromMessage(d)
+	if err != nil {
+		panic(err)
+	}
+
+	msg, err := mb.Build()
+	if err != nil {
+		panic(err)
+	}
+
+	decoded := dynamic.NewMessage(msg)
+	err = proto.Unmarshal(data, decoded)
+	if err != nil {
+		return 0
+	}
+
+	return 1
+}
diff --git a/projects/protoreflect/fuzz_protoparse.go b/projects/protoreflect/fuzz_protoparse.go
new file mode 100644
index 0000000..5e5b9a9
--- /dev/null
+++ b/projects/protoreflect/fuzz_protoparse.go
@@ -0,0 +1,21 @@
+package protoparse
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+)
+
+func FuzzProtoParse(data []byte) int {
+	parser := &Parser{
+		Accessor: func(_ string) (closer io.ReadCloser, e error) {
+			return ioutil.NopCloser(bytes.NewReader(data)), nil
+		},
+	}
+
+	_, err := parser.ParseFiles("dummy")
+	if err != nil {
+		return 0
+	}
+	return 1
+}
diff --git a/projects/protoreflect/project.yaml b/projects/protoreflect/project.yaml
new file mode 100644
index 0000000..278f98a
--- /dev/null
+++ b/projects/protoreflect/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/jhump/protoreflect"
+primary_contact: "jhumphries131@gmail.com"
+auto_ccs:
+  - "p.antoine@catenacyber.fr"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: 'https://github.com/jhump/protoreflect'
diff --git a/projects/proxygen/Dockerfile b/projects/proxygen/Dockerfile
index 7899ed2..859b60c 100644
--- a/projects/proxygen/Dockerfile
+++ b/projects/proxygen/Dockerfile
@@ -28,7 +28,9 @@
     gcc \
     g++ \
     python \
-    python-dev
+    python-dev \
+    cmake \
+    ninja-build
 
 # Install and build boost from source so we can have it use libc++
 RUN wget https://sourceforge.net/projects/boost/files/boost/1.70.0/boost_1_70_0.tar.gz && \
@@ -96,6 +98,13 @@
     cd .. && \
     rm -rf zstd-1.4.2
 
+# Get double conversion
+RUN git clone --single-branch https://github.com/google/double-conversion.git double-conversion && \
+    cd double-conversion/double-conversion && \
+    cmake -GNinja ../ && \
+    ninja && \
+    ninja install
+
 # Build and install `fmt` needed by folly
 RUN wget https://github.com/fmtlib/fmt/archive/6.0.0.tar.gz && \
     tar xzf 6.0.0.tar.gz && \
@@ -149,7 +158,6 @@
     zlib1g-dev \
     binutils-dev \
     libsodium-dev \
-    libdouble-conversion-dev \
     libunwind8-dev
 
 # Install patchelf so we can fix path to libunwind
diff --git a/projects/proxygen/build.sh b/projects/proxygen/build.sh
index dd3729f..dfa5ef9 100755
--- a/projects/proxygen/build.sh
+++ b/projects/proxygen/build.sh
@@ -15,6 +15,15 @@
 #
 ################################################################################
 
+# Dont build tests we do not care about
+echo "" > ./proxygen/httpclient/samples/CMakeLists.txt
+echo "" > ./proxygen/httpserver/tests/CMakeLists.txt
+echo "" > ./proxygen/lib/http/structuredheaders/test/CMakeLists.txt
+echo "" > ./proxygen/httpserver/filters/tests/CMakeLists.txt
+echo "" > ./proxygen/lib/http/session/test/CMakeLists.txt
+echo "" > ./proxygen/lib/http/codec/compress/test/CMakeLists.txt
+echo "" > ./proxygen/lib/services/test/CMakeLists.txt
+
 cd proxygen
 
 # Link to, and copy over, libunwind
diff --git a/projects/pulumi/Dockerfile b/projects/pulumi/Dockerfile
new file mode 100644
index 0000000..3b12b3c
--- /dev/null
+++ b/projects/pulumi/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/pulumi/pulumi
+COPY build.sh \
+	 config_fuzzer.go \
+	 schema_fuzzer.go \
+	 $SRC/
+WORKDIR $SRC/pulumi
diff --git a/projects/pulumi/build.sh b/projects/pulumi/build.sh
new file mode 100644
index 0000000..9671dca
--- /dev/null
+++ b/projects/pulumi/build.sh
@@ -0,0 +1,26 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd pkg
+#go mod download
+
+cp $SRC/schema_fuzzer.go $SRC/pulumi/pkg/codegen/schema/ 
+compile_go_fuzzer github.com/pulumi/pulumi/pkg/v3/codegen/schema SchemaFuzzer schema_fuzzer
+
+cp $SRC/config_fuzzer.go $SRC/pulumi/sdk/go/common/resource/config/
+compile_go_fuzzer github.com/pulumi/pulumi/sdk/v3/go/common/resource/config FuzzConfig fuzz
+compile_go_fuzzer github.com/pulumi/pulumi/sdk/v3/go/common/resource/config FuzzParseKey fuzz_parse_key
diff --git a/projects/pulumi/config_fuzzer.go b/projects/pulumi/config_fuzzer.go
new file mode 100644
index 0000000..18c3bc0
--- /dev/null
+++ b/projects/pulumi/config_fuzzer.go
@@ -0,0 +1,51 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package config
+
+import (
+	"encoding/json"
+)
+
+func FuzzConfig(data []byte) int {
+	if len(data) != 32 {
+		return -1
+	}
+	crypter := NewSymmetricCrypter(make([]byte, 32))
+	_, _ = crypter.EncryptValue(string(data))
+	_, _ = crypter.DecryptValue(string(data))
+	return 1
+}
+
+func fuuzRoundtripKey(m Key, marshal func(v interface{}) ([]byte, error),
+	unmarshal func([]byte, interface{}) error) (Key, error) {
+	b, err := marshal(m)
+	if err != nil {
+		return Key{}, err
+	}
+
+	var newM Key
+	err = unmarshal(b, &newM)
+	return newM, err
+}
+
+func FuzzParseKey(data []byte) int {
+	k, err := ParseKey(string(data))
+	if err != nil {
+		return 0
+	}
+	fuuzRoundtripKey(k, json.Marshal, json.Unmarshal)
+	return 1
+}
diff --git a/projects/pulumi/project.yaml b/projects/pulumi/project.yaml
new file mode 100644
index 0000000..6080364
--- /dev/null
+++ b/projects/pulumi/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://www.pulumi.com/"
+main_repo: "https://github.com/pulumi/pulumi"
+primary_contact: "anton@pulumi.com"
+auto_ccs :
+  - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/pulumi/schema_fuzzer.go b/projects/pulumi/schema_fuzzer.go
new file mode 100644
index 0000000..38ac5c9
--- /dev/null
+++ b/projects/pulumi/schema_fuzzer.go
@@ -0,0 +1,31 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package schema
+
+import (
+	fuzz "github.com/AdaLogics/go-fuzz-headers"
+)
+
+func SchemaFuzzer(data []byte) int {
+	pkgSpec := PackageSpec{}
+	f := fuzz.NewConsumer(data)
+	err := f.GenerateStruct(&pkgSpec)
+	if err != nil {
+		return 0
+	}
+	_, _ = ImportSpec(pkgSpec, nil)
+	return 1
+}
diff --git a/projects/pygments/Dockerfile b/projects/pygments/Dockerfile
index b23fc1b..9b54424 100644
--- a/projects/pygments/Dockerfile
+++ b/projects/pygments/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
 RUN git clone \
 	--depth 1 \
@@ -58,4 +58,4 @@
         fuzzing/dictionaries/yara.dict \
       > $OUT/pygments_fuzzer.dict
 
-COPY build.sh pygments_fuzzer.py $SRC/
+COPY build.sh fuzz_guesser.py fuzz_lexers.py $SRC/
diff --git a/projects/pygments/build.sh b/projects/pygments/build.sh
index 01924b5..b76e29a 100644
--- a/projects/pygments/build.sh
+++ b/projects/pygments/build.sh
@@ -19,7 +19,7 @@
 pip3 install .
 
 # Build fuzzers in $OUT.
-for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
+for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
   fuzzer_basename=$(basename -s .py $fuzzer)
   fuzzer_package=${fuzzer_basename}.pkg
   pyinstaller --distpath $OUT --onefile --name $fuzzer_package $fuzzer
@@ -30,7 +30,7 @@
 this_dir=\$(dirname \"\$0\")
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
 
 zip -j $OUT/files_fuzzer_seed_corpus.zip tests/examplefiles/*
diff --git a/projects/pygments/fuzz_guesser.py b/projects/pygments/fuzz_guesser.py
new file mode 100644
index 0000000..ecc2411
--- /dev/null
+++ b/projects/pygments/fuzz_guesser.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python3
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import atheris
+with atheris.instrument_imports():
+  import sys
+  import pygments
+  import pygments.lexers
+
+@atheris.instrument_func
+def TestOneInput(data: bytes) -> int:
+  try:
+    lexer = pygments.lexers.guess_lexer(str(data))
+  except ValueError:
+    return 0
+  return 0
+
+
+def main():
+  atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+  atheris.Fuzz()
+
+
+if __name__ == "__main__":
+  main()
diff --git a/projects/pygments/fuzz_lexers.py b/projects/pygments/fuzz_lexers.py
new file mode 100644
index 0000000..0d610c1
--- /dev/null
+++ b/projects/pygments/fuzz_lexers.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python3
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import atheris
+with atheris.instrument_imports():
+  import sys
+  import pygments
+  import pygments.formatters.html
+  import pygments.lexers
+
+formatter = pygments.formatters.html.HtmlFormatter()
+# pygments.LEXERS.values() is a list of tuples like this, with some of then empty:
+# (textual class name, longname, tuple of aliases, tuple of filename patterns, tuple of mimetypes)
+LEXERS = [l[2][0] for l in pygments.lexers.LEXERS.values() if l[2]]
+
+
+def TestOneInput(data: bytes) -> int:
+  fdp = atheris.FuzzedDataProvider(data)
+  random_lexer = pygments.lexers.get_lexer_by_name(fdp.PickValueInList(LEXERS))
+  str_data = fdp.ConsumeUnicode(atheris.ALL_REMAINING)
+
+  pygments.highlight(str_data, random_lexer, formatter)
+  return 0
+
+
+atheris.Setup(sys.argv, TestOneInput)
+atheris.Fuzz()
diff --git a/projects/pygments/pygments_fuzzer.py b/projects/pygments/pygments_fuzzer.py
deleted file mode 100644
index 9d21ba3..0000000
--- a/projects/pygments/pygments_fuzzer.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/python3
-
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-import atheris
-import pygments
-import pygments.formatters
-import pygments.lexers
-
-
-def TestOneInput(input_bytes):
-  fdp = atheris.FuzzedDataProvider(input_bytes)
-  data = fdp.ConsumeUnicode(atheris.ALL_REMAINING)
-
-  try:
-    lexer = pygments.lexers.guess_lexer(data)
-  except ValueError:
-    return
-  pygments.highlight(data, lexer, pygments.formatters.HtmlFormatter())
-
-
-def main():
-  atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
-  atheris.Fuzz()
-
-
-if __name__ == "__main__":
-  main()
diff --git a/projects/python-lz4/Dockerfile b/projects/python-lz4/Dockerfile
index 8598ed3..2ce705b 100644
--- a/projects/python-lz4/Dockerfile
+++ b/projects/python-lz4/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 RUN git clone --depth 1 https://github.com/python-lz4/python-lz4
 
 COPY build.sh $SRC/
diff --git a/projects/python-lz4/build.sh b/projects/python-lz4/build.sh
index 66f6419..6eaf4d5 100644
--- a/projects/python-lz4/build.sh
+++ b/projects/python-lz4/build.sh
@@ -30,5 +30,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/python-lz4/fuzz_lz4.py b/projects/python-lz4/fuzz_lz4.py
index ff6787d..6a7e21d 100644
--- a/projects/python-lz4/fuzz_lz4.py
+++ b/projects/python-lz4/fuzz_lz4.py
@@ -15,7 +15,8 @@
 
 import sys
 import atheris
-import lz4.frame
+with atheris.instrument_imports():
+  import lz4.frame
 
 def TestOneInput(data):
     c =lz4.frame.compress(data)
diff --git a/projects/python3-libraries/Dockerfile b/projects/python3-libraries/Dockerfile
index 3da576e..37f6706 100644
--- a/projects/python3-libraries/Dockerfile
+++ b/projects/python3-libraries/Dockerfile
@@ -15,7 +15,8 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get install -y build-essential libncursesw5-dev libreadline-dev libssl-dev libgdbm-dev libc6-dev libsqlite3-dev tk-dev libbz2-dev zlib1g-dev libffi-dev
+RUN apt-get update && \
+    apt-get install -y build-essential libncursesw5-dev libreadline-dev libssl-dev libgdbm-dev libc6-dev libsqlite3-dev tk-dev libbz2-dev zlib1g-dev libffi-dev
 RUN git clone https://github.com/python/cpython.git cpython
 RUN git clone --depth 1 https://github.com/guidovranken/python-library-fuzzers.git
 COPY build.sh $SRC/
diff --git a/projects/pyyaml/Dockerfile b/projects/pyyaml/Dockerfile
index 3d5bc54..d555b40 100644
--- a/projects/pyyaml/Dockerfile
+++ b/projects/pyyaml/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 RUN git clone https://github.com/yaml/pyyaml
 WORKDIR $SRC
 COPY build.sh $SRC/
diff --git a/projects/pyyaml/build.sh b/projects/pyyaml/build.sh
index de7d84c..504adcb 100644
--- a/projects/pyyaml/build.sh
+++ b/projects/pyyaml/build.sh
@@ -30,5 +30,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/pyyaml/fuzz_loader.py b/projects/pyyaml/fuzz_loader.py
index 6600d84..40c9fcc 100644
--- a/projects/pyyaml/fuzz_loader.py
+++ b/projects/pyyaml/fuzz_loader.py
@@ -14,11 +14,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import sys
+
 import atheris
 
-import yaml
+with atheris.instrument_imports():
+  import yaml
 
 
+@atheris.instrument_func
 def TestOneInput(input_bytes):
   try:
     context = yaml.load(input_bytes, Loader=yaml.FullLoader)
diff --git a/projects/pyyaml/fuzz_reader.py b/projects/pyyaml/fuzz_reader.py
index d7a0e2c..5cd0d1e 100644
--- a/projects/pyyaml/fuzz_reader.py
+++ b/projects/pyyaml/fuzz_reader.py
@@ -15,8 +15,10 @@
 # limitations under the License.
 import sys
 import atheris
-import yaml.reader
+with atheris.instrument_imports():
+  import yaml.reader
 
+@atheris.instrument_func
 def TestOneInput(data):
     if len(data) < 1:
         return 
@@ -30,7 +32,7 @@
     return 
 
 def main():
-    atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+    atheris.Setup(sys.argv, TestOneInput)
     atheris.Fuzz()
 
 if __name__ == "__main__":
diff --git a/projects/qcms/Dockerfile b/projects/qcms/Dockerfile
index c124a14..922eac6 100644
--- a/projects/qcms/Dockerfile
+++ b/projects/qcms/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 RUN apt-get update && apt-get install -y mercurial
 RUN hg clone --uncompressed https://hg.mozilla.org/mozilla-central/
 COPY build.sh $SRC/
diff --git a/projects/qemu/Dockerfile b/projects/qemu/Dockerfile
index 779fc39..bf780b8 100644
--- a/projects/qemu/Dockerfile
+++ b/projects/qemu/Dockerfile
@@ -15,14 +15,9 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool \
-    libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev patchelf wget \
-    libattr1 libattr1-dev libcap-ng-dev
-# Ninja in the apt repos is too old. Get it directly from github
-RUN wget https://github.com/ninja-build/ninja/releases/latest/download/ninja-linux.zip \
-    && unzip ninja-linux.zip \
-    && rm ninja-linux.zip \
-    && mv ninja /usr/bin/ninja
+RUN apt-get update && apt-get install -y make autoconf automake libtool ninja-build libglib2.0-dev \
+    libfdt-dev libpixman-1-dev zlib1g-dev patchelf wget \
+    libattr1 libattr1-dev libcap-ng-dev pkg-config
 RUN git clone --depth 1 https://git.qemu.org/git/qemu.git qemu
 WORKDIR qemu
-RUN cp scripts/oss-fuzz/build.sh $SRC
+COPY build.sh $SRC/
diff --git a/projects/qemu/build.sh b/projects/qemu/build.sh
new file mode 100755
index 0000000..94c7143
--- /dev/null
+++ b/projects/qemu/build.sh
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+# Copyright 2020 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+pip3 install meson
+
+./scripts/oss-fuzz/build.sh
diff --git a/projects/qemu/default.options b/projects/qemu/default.options
new file mode 100644
index 0000000..08e7afb
--- /dev/null
+++ b/projects/qemu/default.options
@@ -0,0 +1,3 @@
+[libfuzzer]
+close_fd_mask=3
+detect_leaks=0
diff --git a/projects/qemu/project.yaml b/projects/qemu/project.yaml
index 0974830..db9d1df 100644
--- a/projects/qemu/project.yaml
+++ b/projects/qemu/project.yaml
@@ -3,6 +3,7 @@
 primary_contact: "alxndr@bu.edu"
 auto_ccs:
   - "bsd@redhat.com"
+  - "mcascell@redhat.com"
   - "pbonzini@redhat.com"
   - "stefanha@redhat.com"
   - "darren.kenny@oracle.com"
diff --git a/projects/qpdf/project.yaml b/projects/qpdf/project.yaml
index 4415052..41a4be8 100644
--- a/projects/qpdf/project.yaml
+++ b/projects/qpdf/project.yaml
@@ -4,5 +4,6 @@
 sanitizers:
   - address
   - undefined
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 main_repo: 'https://github.com/qpdf/qpdf.git'
diff --git a/projects/qt/project.yaml b/projects/qt/project.yaml
index 9410067..6e6a844 100644
--- a/projects/qt/project.yaml
+++ b/projects/qt/project.yaml
@@ -2,8 +2,10 @@
 language: c++
 primary_contact: "rlohningqt@gmail.com"
 auto_ccs:
+ - "sgaist.qt@gmail.com"
  - "shawn.t.rutledge@gmail.com"
+main_repo: 'git://code.qt.io/qt/qt5.git'
 architectures:
  - x86_64
  - i386
-main_repo: 'git://code.qt.io/qt/qt5.git'
+help_url: "https://code.qt.io/cgit/qt/qtbase.git/plain/tests/libfuzzer/README"
diff --git a/projects/quic-go/Dockerfile b/projects/quic-go/Dockerfile
index 9ee792c..5719c0d 100644
--- a/projects/quic-go/Dockerfile
+++ b/projects/quic-go/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 RUN git clone --depth 1 https://github.com/marten-seemann/qpack/ && \
   cd qpack && \
diff --git a/projects/quick-xml/Dockerfile b/projects/quick-xml/Dockerfile
new file mode 100644
index 0000000..43995b8
--- /dev/null
+++ b/projects/quick-xml/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+
+RUN git clone --depth 1 https://github.com/tafia/quick-xml
+COPY fuzz_target_1.rs $SRC/quick-xml/fuzz/fuzz_targets/fuzz_target_1.rs
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/quick-xml/build.sh b/projects/quick-xml/build.sh
new file mode 100755
index 0000000..704c860
--- /dev/null
+++ b/projects/quick-xml/build.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd $SRC/quick-xml
+cargo fuzz build -O 
+cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 $OUT/
diff --git a/projects/quick-xml/fuzz_target_1.rs b/projects/quick-xml/fuzz_target_1.rs
new file mode 100644
index 0000000..4ce369d
--- /dev/null
+++ b/projects/quick-xml/fuzz_target_1.rs
@@ -0,0 +1,58 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+//limitations under the License.
+//
+//###################
+#![no_main]
+#[macro_use] extern crate libfuzzer_sys;
+extern crate quick_xml;
+
+use quick_xml::Reader;
+use quick_xml::events::Event;
+use std::io::Cursor;
+
+fuzz_target!(|data: &[u8]| {
+    // fuzzed code goes here
+    let cursor = Cursor::new(data);
+    let mut reader = Reader::from_reader(cursor);
+    let mut buf = vec![];
+    loop {
+        match reader.read_event(&mut buf) {
+            Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e))=> {
+                if e.unescaped().is_err() {
+                    break;
+                }
+                for a in e.attributes() {
+                    if a.ok().map_or(false, |a| a.unescaped_value().is_err()) {
+                        break;
+                    }
+                }
+            }
+            Ok(Event::Text(ref e)) | Ok(Event::Comment(ref e))
+            | Ok(Event::CData(ref e)) | Ok(Event::PI(ref e))
+            | Ok(Event::DocType(ref e)) => {
+                if e.unescaped().is_err() {
+                    break;
+                }
+            }
+            Ok(Event::Decl(ref e)) => {
+                let _ = e.version();
+                let _ = e.encoding();
+                let _ = e.standalone();
+            }
+            Ok(Event::End(_)) => (),
+            Ok(Event::Eof) | Err(..) => break,
+        }
+        buf.clear();
+    }
+});
diff --git a/projects/quick-xml/project.yaml b/projects/quick-xml/project.yaml
new file mode 100644
index 0000000..98af2f9
--- /dev/null
+++ b/projects/quick-xml/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/tafia/quick-xml"
+main_repo: "https://github.com/tafia/quick-xml"
+primary_contact: "tafia973@gmail.com"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "david@adalogics.com"
diff --git a/projects/quickjs/project.yaml b/projects/quickjs/project.yaml
index 7bc6d09..a2e3ce7 100644
--- a/projects/quickjs/project.yaml
+++ b/projects/quickjs/project.yaml
@@ -10,4 +10,4 @@
 - address
 
 blackbox: true  # also use a blackbox fuzzer for this project.
-main_repo: 'https://github.com/horhof/quickjs'
+main_repo: 'https://github.com/bellard/quickjs'
diff --git a/projects/radare2/Dockerfile b/projects/radare2/Dockerfile
index b0140e0..5b2f403 100644
--- a/projects/radare2/Dockerfile
+++ b/projects/radare2/Dockerfile
@@ -1,7 +1,7 @@
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update
-RUN git clone https://github.com/radare/radare2 radare2
-RUN git clone https://github.com/radare/radare2-regressions radare2-regressions
+RUN git clone https://github.com/radareorg/radare2 radare2
+RUN git clone https://github.com/radareorg/radare2-fuzz radare2-fuzz
 WORKDIR radare2
 COPY build.sh $SRC/
 COPY *.options $SRC/
diff --git a/projects/radare2/build.sh b/projects/radare2/build.sh
index c04240a..94f72f1 100755
--- a/projects/radare2/build.sh
+++ b/projects/radare2/build.sh
@@ -6,7 +6,7 @@
 sys/static.sh
 cp -r r2-static $OUT/
 
-cp -r ../radare2-regressions/fuzz/targets .
+cp -r ../radare2-fuzz/targets .
 export RADARE2_STATIC_BUILD=$OUT/r2-static
 
 cd targets 
diff --git a/projects/radare2/project.yaml b/projects/radare2/project.yaml
index 9434e18..f1b5ee9 100644
--- a/projects/radare2/project.yaml
+++ b/projects/radare2/project.yaml
@@ -1,4 +1,4 @@
-homepage: "https://github.com/radare/radare2"
+homepage: "https://github.com/radareorg/radare2"
 language: c++
 primary_contact: "pancake@nopcode.org"
 auto_ccs:
@@ -6,4 +6,4 @@
 sanitizers:
   - address
 run_tests: False
-main_repo: 'https://github.com/radare/radare2'
+main_repo: 'https://github.com/radareorg/radare2'
diff --git a/projects/radon/Dockerfile b/projects/radon/Dockerfile
index fe4c6ca..0c6ac1b 100644
--- a/projects/radon/Dockerfile
+++ b/projects/radon/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/radondb/radon
 COPY build.sh $SRC/
 WORKDIR $SRC/radon
diff --git a/projects/rdkit/Dockerfile b/projects/rdkit/Dockerfile
index 1dad793..e072c2d 100644
--- a/projects/rdkit/Dockerfile
+++ b/projects/rdkit/Dockerfile
@@ -15,7 +15,13 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y wget libeigen3-dev
+RUN apt-get update && apt-get install -y wget
+
+RUN git clone https://gitlab.com/libeigen/eigen && \
+    mkdir eigen_build && \
+    cd eigen_build && \
+    cmake ../eigen && \
+    make install
 
 RUN git clone --depth 1 https://github.com/rdkit/rdkit.git $SRC/rdkit
 WORKDIR $SRC/rdkit
diff --git a/projects/re2/project.yaml b/projects/re2/project.yaml
index 0fc1f83..28f9c4b 100644
--- a/projects/re2/project.yaml
+++ b/projects/re2/project.yaml
@@ -3,9 +3,10 @@
 primary_contact: "junyer@google.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 architectures:
   - x86_64
   - i386
-main_repo: 'https://code.googlesource.com/re2'
+main_repo: 'https://code.googlesource.com/re2'
\ No newline at end of file
diff --git a/projects/relic/Dockerfile b/projects/relic/Dockerfile
index 23b426b..2021317 100644
--- a/projects/relic/Dockerfile
+++ b/projects/relic/Dockerfile
@@ -19,5 +19,5 @@
 RUN git clone --depth 1 https://github.com/relic-toolkit/relic.git
 RUN git clone --depth 1 https://github.com/randombit/botan.git
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
 COPY build.sh $SRC/
diff --git a/projects/relic/build.sh b/projects/relic/build.sh
index 552b14f..d2c31dd 100755
--- a/projects/relic/build.sh
+++ b/projects/relic/build.sh
@@ -26,9 +26,6 @@
 CFLAGS="" CXXFLAGS="" ./b2 headers
 cp -R boost/ /usr/include/
 
-# Prevent Boost compilation error with -std=c++17
-export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR"
-
 # Build Relic
 cd $SRC/relic/
 mkdir build/
@@ -65,9 +62,10 @@
 rm extra_options.h
 echo -n '"' >>extra_options.h
 echo -n '--force-module=relic ' >>extra_options.h
-echo -n '--operations=BignumCalc,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Sign,ECDSA_Verify,Digest,HMAC,KDF_X963 ' >>extra_options.h
+echo -n '--operations=BignumCalc,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Sign,ECDSA_Verify,Digest,HMAC,KDF_X963,SymmetricEncrypt,SymmetricDecrypt,ECC_Point_Add,ECC_Point_Mul ' >>extra_options.h
 echo -n '--curves=secp256k1,secp256r1 ' >>extra_options.h
 echo -n '--digests=NULL,SHA224,SHA256,SHA384,SHA512,BLAKE2S160,BLAKE2S256 ' >>extra_options.h
+echo -n '--ciphers=AES_128_CBC,AES_192_CBC,AES_256_CBC ' >>extra_options.h
 echo -n '--calcops=Abs,Add,Bit,ClearBit,Cmp,CmpAbs,Div,ExpMod,GCD,InvMod,IsEven,IsOdd,IsZero,Jacobi,LCM,LShift1,Mod,Mul,Neg,NumBits,RShift,SetBit,Sqr,Sqrt,Sub ' >>extra_options.h
 echo -n '"' >>extra_options.h
 cd modules/relic/
diff --git a/projects/relic/project.yaml b/projects/relic/project.yaml
index 98fb04f..c3d3016 100644
--- a/projects/relic/project.yaml
+++ b/projects/relic/project.yaml
@@ -7,7 +7,8 @@
 sanitizers:
  - address
  - undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 architectures:
  - x86_64
  - i386
diff --git a/projects/resiprocate/Dockerfile b/projects/resiprocate/Dockerfile
index 58f7a92..c1abd02 100644
--- a/projects/resiprocate/Dockerfile
+++ b/projects/resiprocate/Dockerfile
@@ -16,6 +16,13 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config
+RUN git clone https://github.com/fmtlib/fmt && \
+    cd fmt && \
+    mkdir build && \
+    cd build && \
+    cmake .. && \
+    make && \
+    make install
 RUN git clone --depth 1 https://github.com/resiprocate/resiprocate.git resiprocate
 WORKDIR resiprocate
 COPY build.sh $SRC/
diff --git a/projects/rnp/Dockerfile b/projects/rnp/Dockerfile
index c82713b..0082860 100755
--- a/projects/rnp/Dockerfile
+++ b/projects/rnp/Dockerfile
@@ -27,7 +27,7 @@
     zlib1g-dev \
     libjson-c-dev \
     build-essential \
-    python-minimal \
+    python \
     wget
 
 RUN git clone --depth 1 https://github.com/rnpgp/rnp.git rnp
diff --git a/projects/rnp/build.sh b/projects/rnp/build.sh
index 1bfd8aa..95439b6 100755
--- a/projects/rnp/build.sh
+++ b/projects/rnp/build.sh
@@ -62,4 +62,4 @@
 mkdir -p "${OUT}/lib"
 cp src/lib/librnp.so.0 "${OUT}/lib/"
 cp /usr/lib/libbotan-2.so.16 "${OUT}/lib/"
-cp /lib/x86_64-linux-gnu/libjson-c.so.2 "${OUT}/lib/"
+cp /lib/x86_64-linux-gnu/libjson-c.so.* "${OUT}/lib/"
diff --git a/projects/rocksdb/build.sh b/projects/rocksdb/build.sh
index af784a2..e336559 100755
--- a/projects/rocksdb/build.sh
+++ b/projects/rocksdb/build.sh
@@ -21,6 +21,7 @@
 cd $SRC/rocksdb
 export FUZZ_ENV=ossfuzz
 export CC=$CXX
+export DISABLE_WARNING_AS_ERROR=1
 make static_lib
 
 cd fuzz
diff --git a/projects/runc/Dockerfile b/projects/runc/Dockerfile
index 78616e9..ccef866 100644
--- a/projects/runc/Dockerfile
+++ b/projects/runc/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/opencontainers/runc
 COPY build.sh $SRC/
 WORKDIR $SRC/runc
diff --git a/projects/rust-regex/Dockerfile b/projects/rust-regex/Dockerfile
index c64a6a1..e1b5b40 100644
--- a/projects/rust-regex/Dockerfile
+++ b/projects/rust-regex/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN git clone --depth 1 https://github.com/rust-lang/regex regex
 WORKDIR $SRC
diff --git a/projects/rustls/Dockerfile b/projects/rustls/Dockerfile
index 7406a47..361e30a 100644
--- a/projects/rustls/Dockerfile
+++ b/projects/rustls/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 RUN apt-get update && apt-get install -y make autoconf automake libtool curl cmake python llvm-dev libclang-dev clang
 
 RUN git clone https://github.com/ctz/rustls
@@ -22,4 +22,3 @@
 WORKDIR $SRC
 
 COPY build.sh $SRC/
-COPY persist.rs $SRC/rustls/fuzz/fuzzers/persist.rs
diff --git a/projects/rustls/build.sh b/projects/rustls/build.sh
index d00359e..1f16177 100755
--- a/projects/rustls/build.sh
+++ b/projects/rustls/build.sh
@@ -22,4 +22,8 @@
 cp fuzz/target/x86_64-unknown-linux-gnu/release/fragment $OUT/
 cp fuzz/target/x86_64-unknown-linux-gnu/release/hsjoiner $OUT/
 cp fuzz/target/x86_64-unknown-linux-gnu/release/message $OUT/
-cp fuzz/target/x86_64-unknown-linux-gnu/release/server $OUT/
+if [ "$SANITIZER" != "coverage" ]
+then
+    cp fuzz/target/x86_64-unknown-linux-gnu/release/server $OUT/
+    cp fuzz/target/x86_64-unknown-linux-gnu/release/persist $OUT/
+fi
diff --git a/projects/rustls/persist.rs b/projects/rustls/persist.rs
deleted file mode 100644
index 186cd9a..0000000
--- a/projects/rustls/persist.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-//limitations under the License.
-//
-//################################################################################
-#![no_main]
-#[macro_use] extern crate libfuzzer_sys;
-extern crate rustls;
-
-use rustls::internal::msgs::persist;
-use rustls::internal::msgs::codec::{Reader, Codec};
-
-fn try_type<T>(data: &[u8]) where T: Codec {
-    let mut rdr = Reader::init(data);
-    T::read(&mut rdr);
-}
-
-fuzz_target!(|data: &[u8]| {
-    try_type::<persist::ServerSessionValue>(data);
-});
diff --git a/projects/rustls/project.yaml b/projects/rustls/project.yaml
index 73e4f27..d483a37 100644
--- a/projects/rustls/project.yaml
+++ b/projects/rustls/project.yaml
@@ -8,3 +8,5 @@
 language: rust
 auto_ccs:
   - "david@adalogics.com"
+  - "dirkjan@ochtman.nl"
+  - "brian@briansmith.org"
diff --git a/projects/s2geometry/Dockerfile b/projects/s2geometry/Dockerfile
new file mode 100644
index 0000000..8f58a55
--- /dev/null
+++ b/projects/s2geometry/Dockerfile
@@ -0,0 +1,43 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && \
+    apt-get -y install \
+    libgflags-dev \
+    libgoogle-glog-dev \
+    libgtest-dev libssl-dev \
+    make \
+    curl
+
+# OpenSSL
+ARG OPENSSL_VERSION=1.1.1g
+ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
+RUN set -ex \
+    && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
+    && echo "${OPENSSL_HASH}  openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
+    && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
+    && cd openssl-${OPENSSL_VERSION} \
+    && ./Configure linux-x86_64 no-shared --static "$CFLAGS" \
+    && make build_generated \
+    && make libcrypto.a \
+    && make install
+
+RUN git clone https://github.com/google/s2geometry
+WORKDIR $SRC/s2geometry
+COPY build.sh \
+     s2_fuzzer.cc \
+     $SRC/
diff --git a/projects/s2geometry/build.sh b/projects/s2geometry/build.sh
new file mode 100755
index 0000000..1b7cd97
--- /dev/null
+++ b/projects/s2geometry/build.sh
@@ -0,0 +1,34 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir build && cd build
+cmake -DBUILD_SHARED_LIBS=OFF \
+      -DABSL_MIN_LOG_LEVEL=4 \
+      -DGTEST_ROOT=/usr/src/gtest ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DABSL_MIN_LOG_LEVEL=4 \
+  -I/src/s2geometry/src \
+  -I/usr/src/gtest/include -std=c++11 \
+  -c $SRC/s2_fuzzer.cc \
+  -o s2_fuzzer.o
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+  s2_fuzzer.o -o $OUT/s2_fuzzer \
+  /src/s2geometry/build/libs2.a \
+  /src/openssl-1.1.1g/libssl.a \
+  /src/openssl-1.1.1g/libcrypto.a
diff --git a/projects/s2geometry/project.yaml b/projects/s2geometry/project.yaml
new file mode 100644
index 0000000..8f53bde
--- /dev/null
+++ b/projects/s2geometry/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/google/s2geometry"
+language: c++
+primary_contact: "jmr@google.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+main_repo: "https://github.com/google/s2geometry"
diff --git a/projects/s2geometry/s2_fuzzer.cc b/projects/s2geometry/s2_fuzzer.cc
new file mode 100644
index 0000000..62050a0
--- /dev/null
+++ b/projects/s2geometry/s2_fuzzer.cc
@@ -0,0 +1,99 @@
+/*
+# Copyright 2020 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "s2/s2shapeutil_range_iterator.h"
+#include "s2/third_party/absl/strings/str_split.h"
+#include "s2/third_party/absl/strings/string_view.h"
+
+#include "s2/mutable_s2shape_index.h"
+#include "s2/s2text_format.h"
+
+// A string-splitter used to help validate the string
+// passed to s2
+static std::vector<absl::string_view> SplitString(absl::string_view str,
+                                                  char separator) {
+  std::vector<absl::string_view> result =
+      absl::StrSplit(str, separator, absl::SkipWhitespace());
+  for (auto &e : result) {
+    e = absl::StripAsciiWhitespace(e);
+  }
+  return result;
+}
+
+// Null-terminates the fuzzers input test case
+char *null_terminated(const uint8_t *data, size_t size) {
+  char *new_str = (char *)malloc(size + 1);
+  if (new_str == NULL) {
+    return 0;
+  }
+  memcpy(new_str, data, size);
+  new_str[size] = '\0';
+  return new_str;
+}
+
+// Do a bit of validation that is also done by s2
+// We do them here since s2 would terminate if they
+// would return false inside s2.
+bool isValidFormat(char *nt_string, size_t size) {
+  int hash_count = 0;
+  for (int i = 0; i < size; i++) {
+    if (nt_string[i] == 35) {
+      hash_count++;
+    }
+  }
+  if (hash_count != 2) {
+    return false;
+  }
+
+  std::vector<absl::string_view> strs = SplitString(nt_string, '#');
+  size_t strs_size = strs.size();
+  if (strs.size() != 3) {
+    return false;
+  }
+
+  auto index1 = absl::make_unique<MutableS2ShapeIndex>();
+  if (s2textformat::MakeIndex(nt_string, &index1) == false) {
+    return false;
+  }
+  return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+  if (size < 5) {
+    return 0;
+  }
+
+  char *nt_string = null_terminated(data, size);
+  if (nt_string == NULL) {
+    return 0;
+  }
+  if (isValidFormat(nt_string, size)) {
+    auto index = s2textformat::MakeIndex(nt_string);
+    s2shapeutil::RangeIterator it(*index);
+    if (!it.done()) {
+      it.Next();
+    }
+  }
+  free(nt_string);
+  return 0;
+}
diff --git a/projects/samba/project.yaml b/projects/samba/project.yaml
index 6f7ea35..7e7cdc5 100644
--- a/projects/samba/project.yaml
+++ b/projects/samba/project.yaml
@@ -1,4 +1,5 @@
 homepage: "https://samba.org"
+main_repo: "https://git.samba.org/samba.git"
 language: c
 primary_contact: "douglas.bagnall@catalyst.net.nz"
 auto_ccs:
@@ -9,6 +10,7 @@
   - "sloowfranklin@gmail.com"
   - "gdeschner@gmail.com"
   - "volker.lendecke@gmail.com"
+  - "davidmmulder@gmail.com"
 fuzzing_engines:
   - libfuzzer
   - honggfuzz
diff --git a/projects/scapy/Dockerfile b/projects/scapy/Dockerfile
index 6631b32..08806d9 100644
--- a/projects/scapy/Dockerfile
+++ b/projects/scapy/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
 RUN git clone \
 	--depth 1 \
diff --git a/projects/scapy/build.sh b/projects/scapy/build.sh
index b3270da..223ffa3 100644
--- a/projects/scapy/build.sh
+++ b/projects/scapy/build.sh
@@ -30,7 +30,7 @@
 this_dir=\$(dirname \"\$0\")
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
 
 zip -j $OUT/pcap_fuzzer_seed_corpus.zip test/pcaps/*
diff --git a/projects/scapy/pcap_fuzzer.py b/projects/scapy/pcap_fuzzer.py
index aaf1f5f..0b72f0a 100644
--- a/projects/scapy/pcap_fuzzer.py
+++ b/projects/scapy/pcap_fuzzer.py
@@ -14,13 +14,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import io
 import sys
 import atheris
 
-import scapy
-import scapy.error
-import scapy.utils
+with atheris.instrument_imports():
+  import io
+  import scapy
+  import scapy.error
+  import scapy.utils
 
 
 def TestOneInput(input_bytes):
@@ -31,7 +32,7 @@
 
 
 def main():
-  atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+  atheris.Setup(sys.argv, TestOneInput)
   atheris.Fuzz()
 
 
diff --git a/projects/selinux/Dockerfile b/projects/selinux/Dockerfile
index b62b4ae..1c278d7 100644
--- a/projects/selinux/Dockerfile
+++ b/projects/selinux/Dockerfile
@@ -30,4 +30,4 @@
 	xmlto
 RUN git clone --depth 1 https://github.com/SELinuxProject/selinux
 WORKDIR selinux
-COPY build.sh *.c $SRC/
+COPY build.sh $SRC/
diff --git a/projects/selinux/build.sh b/projects/selinux/build.sh
index e2979ad..0661536 100755
--- a/projects/selinux/build.sh
+++ b/projects/selinux/build.sh
@@ -14,13 +14,4 @@
 # limitations under the License.
 #
 ################################################################################
-
-export DESTDIR=$(pwd)/DESTDIR
-export LDFLAGS="${LDFLAGS:-} $CFLAGS"
-
-find -name Makefile | xargs sed -i 's/,-z,defs//'
-make V=1 -j$(nproc) install
-
-$CC $CFLAGS -I$DESTDIR/usr/include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o $SRC/secilc-fuzzer.c
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o $DESTDIR/usr/lib/libsepol.a -o $OUT/secilc-fuzzer
-zip -r $OUT/secilc-fuzzer_seed_corpus.zip secilc/test
+./scripts/oss-fuzz.sh
diff --git a/projects/selinux/secilc-fuzzer.c b/projects/selinux/secilc-fuzzer.c
deleted file mode 100644
index c99df95..0000000
--- a/projects/selinux/secilc-fuzzer.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-# Copyright 2020 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-################################################################################
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <getopt.h>
-#include <sys/stat.h>
-
-#include <sepol/cil/cil.h>
-#include <sepol/policydb.h>
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-	enum cil_log_level log_level = CIL_ERR;
-	struct sepol_policy_file *pf = NULL;
-	FILE *dev_null = NULL;
-	int target = SEPOL_TARGET_SELINUX;
-	int disable_dontaudit = 0;
-	int multiple_decls = 0;
-	int disable_neverallow = 0;
-	int preserve_tunables = 0;
-	int policyvers = POLICYDB_VERSION_MAX;
-	int mls = -1;
-	int attrs_expand_generated = 0;
-	struct cil_db *db = NULL;
-	sepol_policydb_t *pdb = NULL;
-
-	cil_set_log_level(log_level);
-
-	cil_db_init(&db);
-	cil_set_disable_dontaudit(db, disable_dontaudit);
-	cil_set_multiple_decls(db, multiple_decls);
-	cil_set_disable_neverallow(db, disable_neverallow);
-	cil_set_preserve_tunables(db, preserve_tunables);
-	cil_set_mls(db, mls);
-	cil_set_target_platform(db, target);
-	cil_set_policy_version(db, policyvers);
-	cil_set_attrs_expand_generated(db, attrs_expand_generated);
-
-	if (cil_add_file(db, "fuzz", data, size) != SEPOL_OK)
-		goto exit;
-
-	if (cil_compile(db) != SEPOL_OK)
-		goto exit;
-
-	if (cil_build_policydb(db, &pdb) != SEPOL_OK)
-		goto exit;
-
-	if (sepol_policydb_optimize(pdb) != SEPOL_OK)
-		goto exit;
-
-	dev_null = fopen("/dev/null", "w");
-	if (dev_null == NULL)
-		goto exit;
-
-	if (sepol_policy_file_create(&pf) != 0)
-		goto exit;
-
-	sepol_policy_file_set_fp(pf, dev_null);
-
-	if (sepol_policydb_write(pdb, pf) != 0)
-		goto exit;
-exit:
-	if (dev_null != NULL)
-		fclose(dev_null);
-
-	cil_db_destroy(&db);
-	sepol_policydb_free(pdb);
-	sepol_policy_file_free(pf);
-	return 0;
-}
diff --git a/projects/sentencepiece/project.yaml b/projects/sentencepiece/project.yaml
index 579c703..2668dd0 100644
--- a/projects/sentencepiece/project.yaml
+++ b/projects/sentencepiece/project.yaml
@@ -3,8 +3,9 @@
 primary_contact: "taku@google.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 architectures:
   - x86_64
-main_repo: 'https://github.com/google/sentencepiece.git'
+main_repo: 'https://github.com/google/sentencepiece.git'
\ No newline at end of file
diff --git a/projects/serde-yaml/Dockerfile b/projects/serde-yaml/Dockerfile
index 42b1ce3..216394c 100644
--- a/projects/serde-yaml/Dockerfile
+++ b/projects/serde-yaml/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN git clone --depth 1 https://github.com/dtolnay/serde-yaml serde-yaml
 WORKDIR $SRC
diff --git a/projects/serde_json/Dockerfile b/projects/serde_json/Dockerfile
index d27ebda..395b897 100644
--- a/projects/serde_json/Dockerfile
+++ b/projects/serde_json/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 RUN apt-get update && apt-get install -y make autoconf automake libtool curl cmake python llvm-dev libclang-dev clang
 
 RUN git clone --depth 1 https://github.com/serde-rs/json json
diff --git a/projects/servo/Dockerfile b/projects/servo/Dockerfile
index a0e081d..6fbeef8 100644
--- a/projects/servo/Dockerfile
+++ b/projects/servo/Dockerfile
@@ -13,7 +13,7 @@
 # limitations under the License.
 #
 ################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 
 RUN git clone --depth 1 https://github.com/servo/html5ever
 RUN git clone --depth 1 https://github.com/servo/rust-url
diff --git a/projects/simd/Dockerfile b/projects/simd/Dockerfile
new file mode 100644
index 0000000..5c030e0
--- /dev/null
+++ b/projects/simd/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make
+RUN git clone --depth 1 https://github.com/ermig1979/Simd
+WORKDIR Simd
+COPY build.sh simd_load_fuzzer.cpp $SRC/
diff --git a/projects/simd/build.sh b/projects/simd/build.sh
new file mode 100755
index 0000000..8f0c3e7
--- /dev/null
+++ b/projects/simd/build.sh
@@ -0,0 +1,30 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+mkdir build && cd build
+cmake ../prj/cmake \
+	-DCMAKE_BUILD_TYPE="Release"
+make -j$(nproc)
+
+$CXX $CXXFLAGS -I/src/Simd/src -O3 -DNDEBUG -fPIC \
+        -c $SRC/simd_load_fuzzer.cpp -o simd_load_fuzzer.o \
+        -std=c++11 -ferror-limit=5 -m64  -mtune=native
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE simd_load_fuzzer.o \
+        -o $OUT/simd_load_fuzzer \
+        $(find $SRC -name "libSimd.a")
diff --git a/projects/simd/project.yaml b/projects/simd/project.yaml
new file mode 100644
index 0000000..07eaebd
--- /dev/null
+++ b/projects/simd/project.yaml
@@ -0,0 +1,10 @@
+homepage: "http://ermig1979.github.io/Simd"
+language: c++
+primary_contact: "ermig@tut.by"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+main_repo: 'https://github.com/ermig1979/Simd'
diff --git a/projects/simd/simd_load_fuzzer.cpp b/projects/simd/simd_load_fuzzer.cpp
new file mode 100644
index 0000000..e93d1b8
--- /dev/null
+++ b/projects/simd/simd_load_fuzzer.cpp
@@ -0,0 +1,32 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "Test/TestUtils.h"
+
+extern "C"
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+  if (size<5) {
+    return 0;
+  }
+  Test::View::Format formats[4] = {Test::View::Gray8,
+                                   Test::View::Bgr24,
+                                   Test::View::Bgra32,
+                                   Test::View::Rgb24};
+  for(int i=0; i<4; i++) {
+    Test::View dst1;
+    dst1.Load(data, size, formats[i]);
+  }
+  return 0;
+}
diff --git a/projects/simdjson/project.yaml b/projects/simdjson/project.yaml
index 33b298a..538892d 100644
--- a/projects/simdjson/project.yaml
+++ b/projects/simdjson/project.yaml
@@ -1,7 +1,10 @@
-homepage: "https://github.com/simdjson/simdjson"
+homepage: "https://simdjson.org/"
 language: c++
 primary_contact: "pauldreikossfuzz@gmail.com"
 auto_ccs:
  - "lemire@gmail.com"
-
+sanitizers:
+- address
+- undefined
+- memory
 main_repo: 'https://github.com/simdjson/simdjson.git'
diff --git a/projects/skia/Dockerfile b/projects/skia/Dockerfile
index e429088..4af5722 100644
--- a/projects/skia/Dockerfile
+++ b/projects/skia/Dockerfile
@@ -17,7 +17,7 @@
 FROM gcr.io/oss-fuzz-base/base-builder
 
 # Mesa and libz/zlib needed to build swiftshader
-RUN apt-get update && apt-get install -y python wget libglu1-mesa-dev cmake lib32z1-dev zlib1g-dev
+RUN apt-get update && apt-get install -y python wget libglu1-mesa-dev cmake lib32z1-dev zlib1g-dev libxext-dev
 
 RUN git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' --depth 1
 ENV PATH="${SRC}/depot_tools:${PATH}"
diff --git a/projects/skia/build.sh b/projects/skia/build.sh
index 0f6d73f..d4a2b6a 100644
--- a/projects/skia/build.sh
+++ b/projects/skia/build.sh
@@ -43,10 +43,17 @@
 else
   exit 1
 fi
-CFLAGS= CXXFLAGS="-stdlib=libc++" cmake .. -GNinja -DCMAKE_MAKE_PROGRAM="$SRC/depot_tools/ninja" -D$CMAKE_SANITIZER=1
+# These deprecated warnings get quite noisy and mask other issues.
+CFLAGS= CXXFLAGS="-stdlib=libc++ -Wno-deprecated-declarations" cmake .. -GNinja \
+  -DCMAKE_MAKE_PROGRAM="$SRC/depot_tools/ninja" -D$CMAKE_SANITIZER=1
 
-$SRC/depot_tools/ninja libGLESv2 libEGL
-mv libGLESv2.so libEGL.so $OUT
+$SRC/depot_tools/ninja libGLESv2_deprecated libEGL_deprecated
+# Skia is looking for the names w/o the _deprecated tag. The libraries themselves
+# are looking for the _deprecated suffix, so we copy them both ways into the out
+# directory.
+cp libEGL_deprecated.so $OUT/libEGL.so
+cp libGLESv2_deprecated.so $OUT/libGLESv2.so
+mv libGLESv2_deprecated.so libEGL_deprecated.so $OUT
 export SWIFTSHADER_LIB_PATH=$OUT
 
 popd
@@ -54,8 +61,10 @@
 DISABLE="-Wno-zero-as-null-pointer-constant -Wno-unused-template
          -Wno-cast-qual"
 # Disable UBSan vptr since target built with -fno-rtti.
-export CFLAGS="$CFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2 -fno-sanitize=vptr"
-export CXXFLAGS="$CXXFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2 -fno-sanitize=vptr"
+export CFLAGS="$CFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2\
+ -fno-sanitize=vptr -DSK_BUILD_FOR_LIBFUZZER"
+export CXXFLAGS="$CXXFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2\
+ -fno-sanitize=vptr -DSK_BUILD_FOR_LIBFUZZER"
 export LDFLAGS="$LIB_FUZZING_ENGINE $CXXFLAGS -L$SWIFTSHADER_LIB_PATH"
 
 # This splits a space separated list into a quoted, comma separated list for gn.
@@ -73,28 +82,43 @@
 fi
 set -u
 
+SKIA_ARGS="skia_build_fuzzers=true
+           skia_enable_fontmgr_custom_directory=false
+           skia_enable_fontmgr_custom_embedded=false
+           skia_enable_fontmgr_custom_empty=true
+           skia_enable_gpu=true
+           skia_enable_skottie=true
+           skia_use_egl=true
+           skia_use_fontconfig=false
+           skia_use_freetype=true
+           skia_use_system_freetype2=false
+           skia_use_wuffs=true
+           skia_use_libfuzzer_defaults=false"
+
 # Even though GPU is "enabled" for all these builds, none really
-# uses the gpu except for api_mock_gpu_canvas
+# uses the gpu except for api_mock_gpu_canvas.
 $SRC/skia/bin/gn gen out/Fuzz\
     --args='cc="'$CC'"
       cxx="'$CXX'"
-      '$LIMITED_LINK_POOL'
+      '"$LIMITED_LINK_POOL"'
+      '"${SKIA_ARGS[*]}"'
       is_debug=false
       extra_cflags_c=["'"$CFLAGS_ARR"'"]
       extra_cflags_cc=["'"$CXXFLAGS_ARR"'"]
-      extra_ldflags=["'"$LDFLAGS_ARR"'"]
-      skia_build_fuzzers=true
-      skia_enable_fontmgr_custom_directory=false
-      skia_enable_fontmgr_custom_embedded=false
-      skia_enable_fontmgr_custom_empty=true
-      skia_enable_gpu=true
-      skia_enable_skottie=true
-      skia_use_egl=true
-      skia_use_fontconfig=false
-      skia_use_freetype=true
-      skia_use_system_freetype2=false
-      skia_use_wuffs=true
-      skia_use_libfuzzer_defaults=false'
+      extra_ldflags=["'"$LDFLAGS_ARR"'"]'
+
+# Some fuzz targets benefit from assertions so we enable SK_DEBUG to allow SkASSERT
+# and SkDEBUGCODE to run. We still enable optimization (via is_debug=false) because
+# faster code means more fuzz tests and deeper coverage.
+$SRC/skia/bin/gn gen out/FuzzDebug\
+    --args='cc="'$CC'"
+      cxx="'$CXX'"
+      '"$LIMITED_LINK_POOL"'
+      '"${SKIA_ARGS[*]}"'
+      is_debug=false
+      extra_cflags_c=["-DSK_DEBUG","'"$CFLAGS_ARR"'"]
+      extra_cflags_cc=["-DSK_DEBUG","'"$CXXFLAGS_ARR"'"]
+      extra_ldflags=["'"$LDFLAGS_ARR"'"]'
 
 $SRC/depot_tools/ninja -C out/Fuzz \
   android_codec \
@@ -113,6 +137,7 @@
   api_regionop \
   api_skparagraph \
   api_svg_canvas \
+  api_triangulation \
   image_decode \
   image_decode_incremental \
   image_filter_deserialize \
@@ -125,14 +150,16 @@
   skjson \
   skottie_json \
   skp \
+  svg_dom \
+  textblob_deserialize \
+  webp_encoder
+
+$SRC/depot_tools/ninja -C out/FuzzDebug \
   skruntimeeffect \
   sksl2glsl \
   sksl2metal \
   sksl2pipeline \
   sksl2spirv \
-  svg_dom \
-  textblob_deserialize \
-  webp_encoder
 
 rm -rf $OUT/data
 mkdir $OUT/data
@@ -224,16 +251,16 @@
 mv ../skia_data/image_decode_seed_corpus.zip $OUT/image_decode_incremental_seed_corpus.zip
 
 # These 4 use the same sksl_seed_corpus.
-mv out/Fuzz/sksl2glsl $OUT/sksl2glsl
+mv out/FuzzDebug/sksl2glsl $OUT/sksl2glsl
 cp ../skia_data/sksl_seed_corpus.zip $OUT/sksl2glsl_seed_corpus.zip
 
-mv out/Fuzz/sksl2spirv $OUT/sksl2spirv
+mv out/FuzzDebug/sksl2spirv $OUT/sksl2spirv
 cp ../skia_data/sksl_seed_corpus.zip $OUT/sksl2spirv_seed_corpus.zip
 
-mv out/Fuzz/sksl2metal $OUT/sksl2metal
+mv out/FuzzDebug/sksl2metal $OUT/sksl2metal
 cp ../skia_data/sksl_seed_corpus.zip $OUT/sksl2metal_seed_corpus.zip
 
-mv out/Fuzz/sksl2pipeline $OUT/sksl2pipeline
+mv out/FuzzDebug/sksl2pipeline $OUT/sksl2pipeline
 mv ../skia_data/sksl_seed_corpus.zip $OUT/sksl2pipeline_seed_corpus.zip
 
 mv out/Fuzz/skdescriptor_deserialize $OUT/skdescriptor_deserialize
@@ -242,7 +269,7 @@
 mv ../skia_data/svg_dom_seed_corpus.zip $OUT/svg_dom_seed_corpus.zip
 
 
-mv out/Fuzz/skruntimeeffect $OUT/skruntimeeffect
+mv out/FuzzDebug/skruntimeeffect $OUT/skruntimeeffect
 mv ../skia_data/sksl_with_256_padding_seed_corpus.zip $OUT/skruntimeeffect_seed_corpus.zip
 
 mv out/Fuzz/api_create_ddl $OUT/api_create_ddl
@@ -255,3 +282,5 @@
 mv out/Fuzz/api_skparagraph $OUT/api_skparagraph
 
 mv out/Fuzz/api_regionop $OUT/api_regionop
+
+mv out/Fuzz/api_triangulation $OUT/api_triangulation
diff --git a/projects/skia/project.yaml b/projects/skia/project.yaml
index 824ac21..4cbfa2c 100644
--- a/projects/skia/project.yaml
+++ b/projects/skia/project.yaml
@@ -3,20 +3,19 @@
 primary_contact: "kjlubick@chromium.org"
 auto_ccs:
   - "hcm@google.com"
-  - "mtklein@google.com"
   - "reed@google.com"
   - "bsalomon@google.com"
   - "brianosman@google.com"
   - "johnstiles@google.com"
   - "ethannicholas@google.com"
-  - "westont@google.com"
 vendor_ccs:
   - "lsalzman@mozilla.com"
   - "twsmith@mozilla.com"
 sanitizers:
  - address
  - undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
 help_url: "https://skia.org/dev/testing/fuzz"
 builds_per_day: 4
 main_repo: 'https://skia.googlesource.com/skia.git'
diff --git a/projects/sleuthkit/Dockerfile b/projects/sleuthkit/Dockerfile
index cf04b56..a13087f 100644
--- a/projects/sleuthkit/Dockerfile
+++ b/projects/sleuthkit/Dockerfile
@@ -18,4 +18,4 @@
 RUN apt-get update && apt-get install -y make autoconf automake libtool
 RUN git clone --depth 1 https://github.com/sleuthkit/sleuthkit sleuthkit
 WORKDIR sleuthkit
-COPY build.sh sleuthkit_mem_img.h *_fuzzer.cc $SRC/
+COPY build.sh buildcorpus.sh sleuthkit_mem_img.h *_fuzzer.cc $SRC/
diff --git a/projects/sleuthkit/build.sh b/projects/sleuthkit/build.sh
index 7ed222a..2443ffa 100755
--- a/projects/sleuthkit/build.sh
+++ b/projects/sleuthkit/build.sh
@@ -18,8 +18,10 @@
 export CFLAGS="$CFLAGS -Wno-error=non-c-typedef-for-linkage"
 export CXXFLAGS="$CXXFLAGS -Wno-error=non-c-typedef-for-linkage"
 
+${SRC}/buildcorpus.sh
+
 ./bootstrap
-./configure --enable-static --disable-shared --disable-java
+./configure --enable-static --disable-shared --disable-java --without-afflib --without-libewf --without-libvhdi --without-libvmdk
 make -j$(nproc)
 
 declare -A TSK_FS_TYPES=(
@@ -37,14 +39,20 @@
   ["sun"]="TSK_VS_TYPE_SUN"
 )
 
+# The fls APFS fuzz target has a seperate source file since it uses the libtsk
+# pool layer.
+$CXX $CXXFLAGS -std=c++14 -I.. -I. -Itsk \
+    $SRC/sleuthkit_fls_apfs_fuzzer.cc -o $OUT/sleuthkit_fls_apfs_fuzzer \
+    $LIB_FUZZING_ENGINE $SRC/sleuthkit/tsk/.libs/libtsk.a
+
 for type in ${!TSK_FS_TYPES[@]}; do
-  $CXX $CXXFLAGS -std=c++11 -I.. -I. -Itsk -DFSTYPE=${TSK_FS_TYPES[$type]} \
+  $CXX $CXXFLAGS -std=c++14 -I.. -I. -Itsk -DFSTYPE=${TSK_FS_TYPES[$type]} \
       $SRC/sleuthkit_fls_fuzzer.cc -o $OUT/sleuthkit_fls_${type}_fuzzer \
       $LIB_FUZZING_ENGINE $SRC/sleuthkit/tsk/.libs/libtsk.a
 done
 
 for type in ${!TSK_VS_TYPES[@]}; do
-  $CXX $CXXFLAGS -std=c++11 -I.. -I. -Itsk -DVSTYPE=${TSK_VS_TYPES[$type]} \
+  $CXX $CXXFLAGS -std=c++14 -I.. -I. -Itsk -DVSTYPE=${TSK_VS_TYPES[$type]} \
       $SRC/sleuthkit_mmls_fuzzer.cc -o $OUT/sleuthkit_mmls_${type}_fuzzer \
       $LIB_FUZZING_ENGINE $SRC/sleuthkit/tsk/.libs/libtsk.a
 done
diff --git a/projects/sleuthkit/buildcorpus.sh b/projects/sleuthkit/buildcorpus.sh
new file mode 100755
index 0000000..435f475
--- /dev/null
+++ b/projects/sleuthkit/buildcorpus.sh
@@ -0,0 +1,77 @@
+#!/bin/bash -eu
+#
+# Script to downloads test data and build the corpus
+#
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Test data provided by:
+#
+# The Fuzzing Project: https://fuzzing-project.org/resources.html
+#   As CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
+#   https://creativecommons.org/publicdomain/zero/1.0/
+#
+# The dfVFS project: https://github.com/log2timeline/dfvfs
+#   As Apache 2 https://github.com/log2timeline/dfvfs/blob/main/LICENSE
+
+# Files to use for fls fuzz targets
+declare -A FLS_TEST_FILES=(
+  ["apfs"]="https://github.com/log2timeline/dfvfs/blob/main/test_data/apfs.raw?raw=true"
+  ["ext"]="https://files.fuzzing-project.org/filesystems/ext2.img"
+  ["fat"]="https://files.fuzzing-project.org/filesystems/exfat.img https://files.fuzzing-project.org/filesystems/fat12.img https://files.fuzzing-project.org/filesystems/fat16.img https://files.fuzzing-project.org/filesystems/fat32.img"
+  ["hfs"]="https://files.fuzzing-project.org/filesystems/hfsplus.img"
+  ["iso9660"]="https://files.fuzzing-project.org/discimages/iso9660.iso"
+  ["ntfs"]="https://files.fuzzing-project.org/filesystems/ntfs.img"
+)
+
+# Files to use for mmls fuzz targets
+declare -A MMLS_TEST_FILES=(
+  ["dos"]="https://files.fuzzing-project.org/discimages/partition-dos"
+  ["gpt"]="https://files.fuzzing-project.org/discimages/partition-gpt"
+  ["mac"]="https://files.fuzzing-project.org/discimages/partition-mac"
+)
+
+
+for type in ${!FLS_TEST_FILES[@]}; do
+  fuzz_target="sleuthkit_fls_${type}_fuzzer"
+
+  mkdir -p "test_data/${fuzz_target}"
+
+  IFS=" "; for url in ${FLS_TEST_FILES[$type]}; do
+    filename=$( echo ${url} | sed 's/?[^?]*$//' )
+    filename=$( basename ${filename} )
+
+    curl -L -o "test_data/${fuzz_target}/${filename}" "${url}"
+  done
+
+  (cd "test_data/${fuzz_target}" && zip ${OUT}/${fuzz_target}_seed_corpus.zip *)
+done
+
+
+for type in ${!MMLS_TEST_FILES[@]}; do
+  fuzz_target="sleuthkit_mmls_${type}_fuzzer"
+
+  mkdir -p "test_data/${fuzz_target}"
+
+  IFS=" "; for url in ${MMLS_TEST_FILES[$type]}; do
+    filename=$( echo ${url} | sed 's/?[^?]*$//' )
+    filename=$( basename ${filename} )
+
+    curl -L -o "test_data/${fuzz_target}/${filename}" "${url}"
+  done
+
+  (cd "test_data/${fuzz_target}" && zip ${OUT}/${fuzz_target}_seed_corpus.zip *)
+done
diff --git a/projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc b/projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc
new file mode 100644
index 0000000..5c0f402
--- /dev/null
+++ b/projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc
@@ -0,0 +1,60 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "sleuthkit/tsk/tsk_tools_i.h"
+#include "sleuthkit/tsk/fs/tsk_fs.h"
+#include "sleuthkit/tsk/pool/tsk_pool.h"
+#include "sleuthkit_mem_img.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  TSK_IMG_INFO* img;
+  TSK_IMG_INFO* pool_img;
+  TSK_FS_INFO* fs;
+  const TSK_POOL_INFO* pool;
+
+  img = mem_open(data, size);
+  if (img == nullptr) {
+    return 0;
+  }
+  pool = tsk_pool_open_img_sing(img, 0, TSK_POOL_TYPE_APFS);
+
+  if (pool == nullptr) {
+    goto out_img;
+  }
+  // Pool start block is APFS container specific and is hard coded for now
+  pool_img = pool->get_img_info(pool, (TSK_DADDR_T) 106);
+
+  if (pool_img == nullptr) {
+    goto out_pool;
+  }
+  fs = tsk_fs_open_img_decrypt(pool_img, 0, TSK_FS_TYPE_APFS_DETECT, "");
+
+  if (fs != nullptr) {
+    tsk_fs_fls(fs, TSK_FS_FLS_FULL, fs->root_inum, TSK_FS_DIR_WALK_FLAG_RECURSE, nullptr, 0);
+
+    fs->close(fs);
+  }
+  tsk_img_close(pool_img);
+
+out_pool:
+  tsk_pool_close(pool);
+
+out_img:
+  tsk_img_close(img);
+
+  return 0;
+}
diff --git a/projects/smt/Dockerfile b/projects/smt/Dockerfile
new file mode 100644
index 0000000..536986d
--- /dev/null
+++ b/projects/smt/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone https://github.com/celestiaorg/smt
+
+COPY build.sh $SRC
+WORKDIR $SRC/smt
diff --git a/projects/smt/build.sh b/projects/smt/build.sh
new file mode 100755
index 0000000..4854749
--- /dev/null
+++ b/projects/smt/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+bash -x ./oss-fuzz-build.sh
diff --git a/projects/smt/project.yaml b/projects/smt/project.yaml
new file mode 100644
index 0000000..471479e
--- /dev/null
+++ b/projects/smt/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://github.com/celestiaorg/smt"
+primary_contact: "ismail@celestia.org"
+auto_ccs:
+  - fuzzing@orijtech.com
+  - emmanuel@orijtech.com
+  - cuong@orijtech.com
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: "https://github.com/celestiaorg/smt"
diff --git a/projects/solidity/Dockerfile b/projects/solidity/Dockerfile
index c59136c..4272be5 100644
--- a/projects/solidity/Dockerfile
+++ b/projects/solidity/Dockerfile
@@ -19,16 +19,17 @@
     build-essential libbz2-dev ninja-build zlib1g-dev wget python python-dev \
     liblzma-dev uuid-dev pkg-config openjdk-8-jdk unzip mlton
 
-RUN git clone --recursive -b breaking https://github.com/ethereum/solidity.git solidity
+RUN git clone --recursive -b develop https://github.com/ethereum/solidity.git solidity
 RUN git clone --depth 1 https://github.com/ethereum/solidity-fuzzing-corpus.git
 RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git
-RUN git clone --branch="v0.4.0" --recurse-submodules \
+# evmone v0.8.2 fixes: https://github.com/ethereum/evmone/issues/373
+RUN git clone --branch="v0.8.2" --recurse-submodules \
     https://github.com/ethereum/evmone.git
 
 # Install statically built dependencies in "/usr" directory
 # Install boost
 RUN cd $SRC; \
-    wget -q 'https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.bz2' -O boost.tar.bz2; \
+    wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2' -O boost.tar.bz2; \
     test "$(sha256sum boost.tar.bz2)" = "4eb3b8d442b426dc35346235c8733b5ae35ba431690e38c6a8263dce9fcbb402  boost.tar.bz2"; \
     tar -xf boost.tar.bz2; \
     rm boost.tar.bz2; \
diff --git a/projects/solidity/build.sh b/projects/solidity/build.sh
index ae5844c..9f9668b 100755
--- a/projects/solidity/build.sh
+++ b/projects/solidity/build.sh
@@ -20,18 +20,7 @@
 
 ROOTDIR="${SRC}/solidity"
 BUILDDIR="${ROOTDIR}/build"
-mkdir -p "${BUILDDIR}" && mkdir -p "$BUILDDIR/deps"
-
-ANTLRJAR="${BUILDDIR}/deps/antlr4.8.jar"
-ANTLRJAR_URI="https://www.antlr.org/download/antlr-4.8-complete.jar"
-
-download_antlr4()
-{
-  if [[ ! -e "${ANTLRJAR}" ]]
-  then
-    wget -O "${ANTLRJAR}" "${ANTLRJAR_URI}"
-  fi
-}
+mkdir -p "${BUILDDIR}"
 
 generate_protobuf_bindings()
 {
@@ -43,21 +32,6 @@
   done
 }
 
-generate_antlr4_bindings()
-{
-  cd "${ROOTDIR}"
-  # Replace boolean with bool to suit c++ syntax
-  sed -i 's/boolean /bool /g' docs/grammar/Solidity.g4
-  # Generate antlr4 visitor/parser/lexer c++ bindings
-  java -jar "${ANTLRJAR}" -Dlanguage=Cpp \
-    -Xexact-output-dir -package solidity::test::fuzzer -o test/tools/ossfuzz \
-    -no-listener -visitor docs/grammar/SolidityLexer.g4 docs/grammar/Solidity.g4
-  # Delete unnecessary autogen files
-  rm -f "${ROOTDIR}"/test/tools/ossfuzz/Solidity*Visitor.cpp \
-    "${ROOTDIR}"/test/tools/ossfuzz/Solidity*.interp \
-    "${ROOTDIR}"/test/tools/ossfuzz/Solidity*.tokens
-}
-
 build_fuzzers()
 {
   cd "${BUILDDIR}"
@@ -87,9 +61,7 @@
   done
 }
 
-download_antlr4
 generate_protobuf_bindings
-generate_antlr4_bindings
 build_fuzzers
 copy_fuzzers_and_config
-update_corpus
\ No newline at end of file
+update_corpus
diff --git a/projects/sound-open-firmware/project.yaml b/projects/sound-open-firmware/project.yaml
index 4065def..5f8f889 100644
--- a/projects/sound-open-firmware/project.yaml
+++ b/projects/sound-open-firmware/project.yaml
@@ -3,4 +3,9 @@
 language: c
 auto_ccs:
   - "ranjani.sridharan@intel.corp-partner.google.com"
+  - "lgirdwood@gmail.com"
+  - "harsha.p.n@intel.corp-partner.google.com"
+  - "sathyanarayana.nujella@intel.corp-partner.google.com"
+  - "adrian.bonislawski@intel.com"
+  - "michal.wasko@intel.com"
 main_repo: "https://github.com/thesofproject/sof"
diff --git a/projects/spdk/Dockerfile b/projects/spdk/Dockerfile
new file mode 100644
index 0000000..9ac8574
--- /dev/null
+++ b/projects/spdk/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make curl yasm autoconf libtool meson nasm
+RUN git clone --depth 1 https://github.com/spdk/spdk && \
+    cd spdk && \
+    git submodule update --init
+WORKDIR $SRC/spdk
+COPY build.sh parse_json_fuzzer.cc $SRC/
diff --git a/projects/spdk/build.sh b/projects/spdk/build.sh
new file mode 100755
index 0000000..8cf7d6f
--- /dev/null
+++ b/projects/spdk/build.sh
@@ -0,0 +1,32 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Build spdk
+export LDFLAGS="${CFLAGS}"
+./scripts/pkgdep.sh
+./configure --without-shared --without-isal
+make -j$(nproc)
+
+# Build fuzzers
+$CXX $CXXFLAGS -I/src/spdk -I/src/spdk/include \
+        -fPIC -c $SRC/parse_json_fuzzer.cc \
+        -o parse_json_fuzzer.o
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+        parse_json_fuzzer.o -o $OUT/parse_json_fuzzer \
+        /src/spdk/build/lib/libspdk_env_dpdk.a \
+        /src/spdk/build/lib/libspdk_json.a 
diff --git a/projects/spdk/parse_json_fuzzer.cc b/projects/spdk/parse_json_fuzzer.cc
new file mode 100644
index 0000000..94304ba
--- /dev/null
+++ b/projects/spdk/parse_json_fuzzer.cc
@@ -0,0 +1,34 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdlib.h>
+#include "spdk/json.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+	char *buf = (char *)malloc(size);
+	if (buf == NULL) {
+		return 0;
+	}
+	memcpy(buf, data, size);
+	ssize_t rc = spdk_json_parse(buf, size, NULL, 0, NULL, 0);
+
+	free(buf);
+	return 0;
+}
+
diff --git a/projects/spdk/project.yaml b/projects/spdk/project.yaml
new file mode 100644
index 0000000..d326726
--- /dev/null
+++ b/projects/spdk/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/spdk/spdk"
+main_repo: "https://github.com/spdk/spdk"
+language: c
+primary_contact: "james.r.harris@intel.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
diff --git a/projects/spdlog/project.yaml b/projects/spdlog/project.yaml
index b2a7b59..afea591 100644
--- a/projects/spdlog/project.yaml
+++ b/projects/spdlog/project.yaml
@@ -1,10 +1,9 @@
 homepage: "https://github.com/gabime/spdlog"
 language: c++
 primary_contact: "gmelman1@gmail.com"
-auto_ccs:
-  - "ouyangyunshu@google.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
   - undefined
 main_repo: 'https://github.com/gabime/spdlog.git'
diff --git a/projects/spice-usbredir/Dockerfile b/projects/spice-usbredir/Dockerfile
new file mode 100644
index 0000000..6a1059f
--- /dev/null
+++ b/projects/spice-usbredir/Dockerfile
@@ -0,0 +1,31 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN \
+  apt-get update && \
+  apt-get install -y libtool libusb-1.0-0-dev pkg-config libglib2.0-dev && \
+  apt-get clean
+
+# Ubuntu 16.04 ships Meson 0.29 which doesn't support the "feature" option type.
+#
+# https://mesonbuild.com/Build-options.html#features
+RUN python3 -m pip install --no-user --no-cache meson ninja
+
+RUN git clone --depth 1 https://gitlab.freedesktop.org/spice/usbredir.git $SRC/spice-usbredir
+
+WORKDIR $SRC/spice-usbredir
+COPY build.sh $SRC/
diff --git a/projects/spice-usbredir/build.sh b/projects/spice-usbredir/build.sh
new file mode 100755
index 0000000..ffe02a7
--- /dev/null
+++ b/projects/spice-usbredir/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+exec ./build-aux/oss-fuzz.sh
diff --git a/projects/spice-usbredir/project.yaml b/projects/spice-usbredir/project.yaml
new file mode 100644
index 0000000..391eea3
--- /dev/null
+++ b/projects/spice-usbredir/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://www.spice-space.org/usbredir.html"
+language: c++
+primary_contact: "freddy77@gmail.com"
+auto_ccs:
+  - "imsnah@gmail.com"
+sanitizers:
+  - address
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+  - undefined
+main_repo: "https://gitlab.freedesktop.org/spice/usbredir.git"
\ No newline at end of file
diff --git a/projects/spidermonkey/Dockerfile b/projects/spidermonkey/Dockerfile
index 9c74dce..226091b 100644
--- a/projects/spidermonkey/Dockerfile
+++ b/projects/spidermonkey/Dockerfile
@@ -21,7 +21,8 @@
   libc++abi1 \
   m4 \
   yasm \
-  python
+  python \
+  patchelf
 
 # This wrapper of cargo seems to interfere with our build system.
 RUN rm -f /usr/local/bin/cargo
diff --git a/projects/spidermonkey/build.sh b/projects/spidermonkey/build.sh
index bf2e03b..ddee98d 100755
--- a/projects/spidermonkey/build.sh
+++ b/projects/spidermonkey/build.sh
@@ -41,3 +41,6 @@
 mkdir -p $OUT/lib
 cp -L /usr/lib/x86_64-linux-gnu/libc++.so.1 $OUT/lib
 cp -L /usr/lib/x86_64-linux-gnu/libc++abi.so.1 $OUT/lib
+
+# Make sure libs are resolved properly
+patchelf --set-rpath '$ORIGIN/lib'  $OUT/js
diff --git a/projects/spirv-tools/Dockerfile b/projects/spirv-tools/Dockerfile
new file mode 100644
index 0000000..9ef1e80
--- /dev/null
+++ b/projects/spirv-tools/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool ninja-build
+RUN git clone --depth 1 https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools
+WORKDIR spirv-tools
+COPY build.sh $SRC/
diff --git a/projects/spirv-tools/build.sh b/projects/spirv-tools/build.sh
new file mode 100755
index 0000000..707c9d6
--- /dev/null
+++ b/projects/spirv-tools/build.sh
@@ -0,0 +1,107 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+git clone https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers --depth=1
+git clone https://github.com/protocolbuffers/protobuf   external/protobuf      --branch v3.13.0.1
+git clone https://dawn.googlesource.com/tint --depth=1
+
+mkdir build
+pushd build
+
+CMAKE_ARGS="-DSPIRV_BUILD_LIBFUZZER_TARGETS=ON -DSPIRV_LIB_FUZZING_ENGINE_LINK_OPTIONS=$LIB_FUZZING_ENGINE"
+
+# With ubsan, RTTI must be enabled due to certain checks (vptr) requiring it.
+if [ $SANITIZER == "undefined" ];
+then
+  CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_RTTI=ON"
+fi
+cmake -G Ninja .. ${CMAKE_ARGS}
+ninja
+
+SPIRV_BINARY_FUZZERS="spvtools_binary_parser_fuzzer\
+ spvtools_dis_fuzzer\
+ spvtools_opt_legalization_fuzzer\
+ spvtools_opt_performance_fuzzer\
+ spvtools_opt_size_fuzzer\
+ spvtools_val_fuzzer"
+
+SPIRV_ASSEMBLY_FUZZERS="spvtools_as_fuzzer"
+
+for fuzzer in $SPIRV_BINARY_FUZZERS $SPIRV_ASSEMBLY_FUZZERS
+do
+  cp test/fuzzers/$fuzzer $OUT
+done
+
+popd
+
+# An un-instrumented build of spirv-as is used to generate a corpus of SPIR-V binaries.
+mkdir standard-build
+pushd standard-build
+
+# Back-up instrumentation options
+CFLAGS_SAVE="$CFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS"
+unset CFLAGS
+unset CXXFLAGS
+export AFL_NOOPT=1
+
+cmake -G Ninja .. ${CMAKE_ARGS}
+ninja spirv-as
+
+# Restore instrumentation options
+export CFLAGS="${CFLAGS_SAVE}"
+export CXXFLAGS="${CXXFLAGS_SAVE}"
+unset AFL_NOOPT
+
+popd
+
+
+# Generate a corpus of SPIR-V binaries from the SPIR-V assembly files in the
+# SPIRV-Tools and tint repositories.
+mkdir $WORK/tint-binary-corpus
+python3 tint/fuzzers/generate_spirv_corpus.py tint/test $WORK/tint-binary-corpus standard-build/tools/spirv-as
+mkdir $WORK/spirv-binary-corpus-hashed-names
+tint_test_cases=`ls $WORK/tint-binary-corpus/*.spv`
+spirv_tools_test_cases=`find test/fuzzers/corpora -name "*.spv"`
+for f in $tint_test_cases $spirv_tools_test_cases
+do
+  hashed_name=$(sha1sum "$f" | awk '{print $1}')
+  cp $f $WORK/spirv-binary-corpus-hashed-names/$hashed_name
+done
+zip -j "$WORK/spirv_binary_seed_corpus.zip" "$WORK/spirv-binary-corpus-hashed-names"/*
+
+# Supply each of the binary fuzzers with this seed corpus.
+for fuzzer in $SPIRV_BINARY_FUZZERS
+do
+  cp "$WORK/spirv_binary_seed_corpus.zip" "$OUT/${fuzzer}_seed_corpus.zip"
+done
+
+# Generate a corpus of SPIR-V assembly files from the tint repository.
+mkdir $WORK/spirv-assembly-corpus-hashed-names
+for f in `find tint/test -name "*.spvasm"`
+do
+  hashed_name=$(sha1sum "$f" | awk '{print $1}')
+  cp $f $WORK/spirv-assembly-corpus-hashed-names/$hashed_name
+done
+
+zip -j "$WORK/spirv_assembly_seed_corpus.zip" "$WORK/spirv-assembly-corpus-hashed-names"/*
+
+# Supply each of the assembly fuzzers with this seed corpus.
+for fuzzer in $SPIRV_ASSEMBLY_FUZZERS
+do
+  cp "$WORK/spirv_assembly_seed_corpus.zip" "$OUT/${fuzzer}_seed_corpus.zip"
+done
diff --git a/projects/spirv-tools/project.yaml b/projects/spirv-tools/project.yaml
new file mode 100644
index 0000000..2f02d02
--- /dev/null
+++ b/projects/spirv-tools/project.yaml
@@ -0,0 +1,15 @@
+homepage: https://github.com/KhronosGroup/SPIRV-Tools
+language: c++
+primary_contact: rharrison@google.com 
+auto_ccs:
+  - "afdx@google.com"
+  - "alanbaker@google.com"
+  - "stevenperron@google.com"
+sanitizers:
+  - address
+  - memory
+  - undefined
+main_repo: 'https://github.com/KhronosGroup/SPIRV-Tools.git'
+architectures:
+  - x86_64
+  - i386
diff --git a/projects/sql-parser/Dockerfile b/projects/sql-parser/Dockerfile
new file mode 100755
index 0000000..b68268b
--- /dev/null
+++ b/projects/sql-parser/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make cmake
+RUN git clone https://github.com/hyrise/sql-parser
+
+WORKDIR $SRC
+COPY build.sh $SRC/
+COPY fuzz_sql_parse.cpp $SRC/sql-parser/fuzz_sql_parse.cpp
diff --git a/projects/sql-parser/build.sh b/projects/sql-parser/build.sh
new file mode 100755
index 0000000..c795dd5
--- /dev/null
+++ b/projects/sql-parser/build.sh
@@ -0,0 +1,22 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd sql-parser
+sed 's/static ?= no/LIB_CFLAGS += ${CXXFLAGS}\nstatic ?= no/g' -i Makefile
+make static=yes
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+    fuzz_sql_parse.cpp libsqlparser.a -I./src -o $OUT/fuzz_sql_parse
diff --git a/projects/sql-parser/fuzz_sql_parse.cpp b/projects/sql-parser/fuzz_sql_parse.cpp
new file mode 100644
index 0000000..1fb59c9
--- /dev/null
+++ b/projects/sql-parser/fuzz_sql_parse.cpp
@@ -0,0 +1,26 @@
+/* Copyright 2021 Google LLC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include <string>
+#include "SQLParser.h"
+
+using namespace hsql;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    std::string input(reinterpret_cast<const char*>(data), size);
+    SQLParserResult res;
+    SQLParser::parse(input, &res);
+    return 0;
+}
diff --git a/projects/sql-parser/project.yaml b/projects/sql-parser/project.yaml
new file mode 100755
index 0000000..40a73db
--- /dev/null
+++ b/projects/sql-parser/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://github.com/hyrise/sql-parser"
+main_repo: "https://github.com/hyrise/sql-parser"
+primary_contact: "marcel.weisgut@hpi.de"
+language: c++
+auto_ccs:
+  - "klauck2@gmail.com"
+  - "david@adalogics.com"
diff --git a/projects/sqlalchemy/Dockerfile b/projects/sqlalchemy/Dockerfile
new file mode 100644
index 0000000..80c314a
--- /dev/null
+++ b/projects/sqlalchemy/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-python
+RUN git clone --depth 1 --branch rel_1_3 https://github.com/sqlalchemy/sqlalchemy
+WORKDIR $SRC/sqlalchemy
+COPY build.sh sqlalchemy_fuzzer.py $SRC/
diff --git a/projects/sqlalchemy/build.sh b/projects/sqlalchemy/build.sh
new file mode 100644
index 0000000..8f4bee4
--- /dev/null
+++ b/projects/sqlalchemy/build.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+python3 setup.py install
+for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
+  fuzzer_basename=$(basename -s .py $fuzzer)
+  fuzzer_package=${fuzzer_basename}.pkg
+  pyinstaller --distpath $OUT --onefile --name $fuzzer_package $fuzzer
+
+  # Create execution wrapper.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
+\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
+  chmod u+x $OUT/$fuzzer_basename
+done
diff --git a/projects/sqlalchemy/project.yaml b/projects/sqlalchemy/project.yaml
new file mode 100644
index 0000000..2fe9bf5
--- /dev/null
+++ b/projects/sqlalchemy/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://www.sqlalchemy.org"
+language: python
+primary_contact: "mike_mp@zzzcomputing.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+  - undefined
+main_repo: "ihttps://github.com/sqlalchemy/sqlalchemy"
diff --git a/projects/sqlalchemy/sqlalchemy_fuzzer.py b/projects/sqlalchemy/sqlalchemy_fuzzer.py
new file mode 100644
index 0000000..d3ae577
--- /dev/null
+++ b/projects/sqlalchemy/sqlalchemy_fuzzer.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python3
+
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import atheris
+
+with atheris.instrument_imports():
+  import sqlalchemy
+  from sqlalchemy import create_engine
+  from sqlalchemy import Table, Column, Integer, String, MetaData
+  from sqlalchemy.sql import text
+
+@atheris.instrument_func
+def TestOneInput(input_bytes):
+    try:
+        sql_string = input_bytes.decode("utf-8")
+        metadata = MetaData()
+        fuzz_table = Table('fuzz_table', metadata,
+          Column('id', Integer, primary_key=True),
+          Column('column1', String),
+          Column('column2', String),
+        )
+
+        engine = create_engine('sqlite:///fuzz.db')
+        metadata.create_all(engine)
+        statement = text(sql_string)
+        with engine.connect() as conn:            
+            conn.execute(statement)
+    except Exception as e:
+        pass
+
+
+def main():
+  atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+  atheris.Fuzz()
+
+
+if __name__ == "__main__":
+  main()
diff --git a/projects/stb/Dockerfile b/projects/stb/Dockerfile
index d9449ea..6b89306 100644
--- a/projects/stb/Dockerfile
+++ b/projects/stb/Dockerfile
@@ -22,12 +22,17 @@
 
 RUN git clone --depth 1 https://github.com/nothings/stb.git
 
-RUN wget -O $SRC/stb/gif.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-gif-1.00.tar.gz
-RUN wget -O $SRC/stb/jpg.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-jpg-1.00.tar.gz
-RUN wget -O $SRC/stb/bmp.zip http://entropymine.com/jason/bmpsuite/releases/bmpsuite-2.6.zip
-RUN wget -O $SRC/stb/tga.zip https://github.com/richgel999/tga_test_files/archive/master.zip
+RUN mkdir $SRC/stbi # CIFuzz workaround
 
-RUN wget -O $SRC/stb/tests/gif.dict https://raw.githubusercontent.com/mirrorer/afl/master/dictionaries/gif.dict &> /dev/null
+RUN wget -O $SRC/stbi/gif.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-gif-1.00.tar.gz
+RUN wget -O $SRC/stbi/jpg.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-jpg-1.00.tar.gz
+RUN wget -O $SRC/stbi/bmp.zip http://entropymine.com/jason/bmpsuite/releases/bmpsuite-2.6.zip
+RUN wget -O $SRC/stbi/tga.zip https://github.com/richgel999/tga_test_files/archive/master.zip
+
+RUN wget -O $SRC/stbi/gif.dict https://raw.githubusercontent.com/mirrorer/afl/master/dictionaries/gif.dict
+
+# Maintain compatibility with master branch until a new release
+RUN cp $SRC/stbi/gif.tar.gz $SRC/stbi/jpg.tar.gz $SRC/stbi/bmp.zip $SRC/stbi/gif.dict $SRC/stb
 
 WORKDIR stb
 COPY build.sh $SRC/
diff --git a/projects/sudoers/build.sh b/projects/sudoers/build.sh
index 905450c..d157c9a 100755
--- a/projects/sudoers/build.sh
+++ b/projects/sudoers/build.sh
@@ -28,7 +28,11 @@
     sanitizer_opts="$SANITIZER_FLAGS"
 fi
 # This is already added by --enable-fuzzer
-CFLAGS="`echo \"$CFLAGS\" | sed \"s/ -fsanitize=fuzzer-no-link//\"`"
+CFLAGS="`echo \"$CFLAGS\" | sed 's/ -fsanitize=fuzzer-no-link//'`"
+
+# Copy optimization flag to LDFLAGS for UBSan object-size check.
+OPTFLAG="`echo \"$CFLAGS\" | sed 's/^.*\(-O[^ ]\).*$/\1/'`"
+export LDFLAGS="${LDFLAGS:-}${LDFLAGS:+ }$OPTFLAG"
 
 # Build sudo with static libs and enable fuzzing targets.
 # All fuzz targets are integrated into the build process.
diff --git a/projects/sudoers/project.yaml b/projects/sudoers/project.yaml
index 309a3eb..3b3a660 100755
--- a/projects/sudoers/project.yaml
+++ b/projects/sudoers/project.yaml
@@ -4,7 +4,6 @@
 fuzzing_engines:
   - libfuzzer
   - honggfuzz
-  - dataflow
-auto_ccs :
+auto_ccs:
   - "david@adalogics.com"
 main_repo: 'https://github.com/sudo-project/sudo'
diff --git a/projects/suricata/Dockerfile b/projects/suricata/Dockerfile
index 257e7fb..964c394 100644
--- a/projects/suricata/Dockerfile
+++ b/projects/suricata/Dockerfile
@@ -14,10 +14,11 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y build-essential autoconf automake libtool make pkg-config  python flex bison zlib1g-dev libpcre3-dev libpcre2-dev cmake tshark
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+RUN apt-get update && apt-get install -y build-essential autoconf automake libtool make pkg-config  python flex bison zlib1g-dev libpcre3-dev cmake tshark
 
-#TODO libmagic, liblzma, pcre and other optional libraries
+# TODO libmagic, liblzma and other optional libraries
+ADD https://ftp.pcre.org/pub/pcre/pcre2-10.36.tar.gz pcre2-10.36.tar.gz
 ADD https://www.tcpdump.org/release/libpcap-1.9.1.tar.gz libpcap-1.9.1.tar.gz
 ADD http://www.digip.org/jansson/releases/jansson-2.12.tar.gz jansson-2.12.tar.gz
 RUN git clone --depth=1 https://github.com/yaml/libyaml
diff --git a/projects/suricata/build.sh b/projects/suricata/build.sh
index 18f2280..d825b9e 100755
--- a/projects/suricata/build.sh
+++ b/projects/suricata/build.sh
@@ -16,6 +16,15 @@
 ################################################################################
 
 # build dependencies statically
+(
+tar -xvzf pcre2-10.36.tar.gz
+cd pcre2-10.36
+./configure --disable-shared
+make -j$(nproc) clean
+make -j$(nproc) all
+make -j$(nproc) install
+)
+
 tar -xvzf lz4-1.9.2.tar.gz
 cd lz4-1.9.2
 make liblz4.a
@@ -52,6 +61,8 @@
 cd ..
 
 export CARGO_BUILD_TARGET="x86_64-unknown-linux-gnu"
+# cf https://github.com/google/sanitizers/issues/1389
+export MSAN_OPTIONS=strict_memcmp=false
 
 #we did not put libhtp there before so that cifuzz does not remove it
 mv libhtp suricata/
@@ -61,22 +72,27 @@
 #run configure with right options
 if [ "$SANITIZER" = "address" ]
 then
-    export RUSTFLAGS="$RUSTFLAGS -Cpasses=sancov -Cllvm-args=-sanitizer-coverage-level=4 -Cllvm-args=-sanitizer-coverage-trace-compares -Cllvm-args=-sanitizer-coverage-inline-8bit-counters -Cllvm-args=-sanitizer-coverage-trace-geps -Cllvm-args=-sanitizer-coverage-prune-blocks=0 -Cllvm-args=-sanitizer-coverage-pc-table -Clink-dead-code -Cllvm-args=-sanitizer-coverage-stack-depth"
+    export RUSTFLAGS="$RUSTFLAGS -Cpasses=sancov-module -Cllvm-args=-sanitizer-coverage-level=4 -Cllvm-args=-sanitizer-coverage-trace-compares -Cllvm-args=-sanitizer-coverage-inline-8bit-counters -Cllvm-args=-sanitizer-coverage-pc-table -Clink-dead-code -Cllvm-args=-sanitizer-coverage-stack-depth -Ccodegen-units=1"
 fi
 ./src/tests/fuzz/oss-fuzz-configure.sh
 make -j$(nproc)
 
+./src/suricata --list-app-layer-protos | tail -n +2 | while read i; do cp src/fuzz_applayerparserparse $OUT/fuzz_applayerparserparse_$i; done
+
 cp src/fuzz_* $OUT/
 
 # dictionaries
 ./src/suricata --list-keywords | grep "\- " | sed 's/- //' | awk '{print "\""$0"\""}' > $OUT/fuzz_siginit.dict
 
+echo \"SMB\" > $OUT/fuzz_applayerparserparse_smb.dict
+
 # build corpuses
 # default configuration file
 zip -r $OUT/fuzz_confyamlloadstring_seed_corpus.zip suricata.yaml
 # rebuilds rules corpus with only one rule by file
 unzip ../emerging.rules.zip
 cd rules
+cat *.rules > $OUT/fuzz.rules
 i=0
 mkdir corpus
 # quiet output for commands
@@ -105,9 +121,19 @@
 mkdir corpus
 set +x
 ls | grep -v corpus | while read t; do
-cat $t/*.rules > corpus/$i || true; echo -ne '\0' >> corpus/$i; fpc_bin $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
+grep -v "#" $t/*.rules | head -1 | cut -d "(" -f2 | cut -d ")" -f1 > corpus/$i || true; echo -ne '\0' >> corpus/$i; fpc_bin $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
 echo -ne '\0' >> corpus/$i; python3 $SRC/fuzzpcap/tcptofpc.py $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
 done
 set -x
 zip -q -r $OUT/fuzz_sigpcap_aware_seed_corpus.zip corpus
 echo "\"FPC0\"" > $OUT/fuzz_sigpcap_aware.dict
+rm -Rf corpus
+mkdir corpus
+set +x
+ls | grep -v corpus | while read t; do
+fpc_bin $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
+python3 $SRC/fuzzpcap/tcptofpc.py $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
+done
+set -x
+zip -q -r $OUT/fuzz_predefpcap_aware_seed_corpus.zip corpus
+echo "\"FPC0\"" > $OUT/fuzz_predefpcap_aware.dict
diff --git a/projects/suricata/project.yaml b/projects/suricata/project.yaml
index 3babd8f..1db82df 100644
--- a/projects/suricata/project.yaml
+++ b/projects/suricata/project.yaml
@@ -1,11 +1,12 @@
 homepage: "https://suricata-ids.org"
-language: c++
+language: rust
 primary_contact: "vjulien@openinfosecfoundation.org"
 auto_ccs:
 - "jish@openinfosecfoundation.org"
 - "p.antoine@catenacyber.fr"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
 main_repo: 'https://github.com/OISF/suricata.git'
diff --git a/projects/swift-nio/Dockerfile b/projects/swift-nio/Dockerfile
new file mode 100644
index 0000000..1e47174
--- /dev/null
+++ b/projects/swift-nio/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-swift
+
+# specific swift-nio
+RUN git clone --depth 1 https://github.com/google/fuzzing
+RUN git clone --depth 1 https://github.com/apple/swift-nio.git
+COPY build.sh $SRC
+COPY *.swift $SRC/
+WORKDIR $SRC/swift-nio
diff --git a/projects/swift-nio/Package.swift b/projects/swift-nio/Package.swift
new file mode 100644
index 0000000..98ab5dc
--- /dev/null
+++ b/projects/swift-nio/Package.swift
@@ -0,0 +1,19 @@
+// swift-tools-version:5.3
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+    name: "swift-nio-fuzz",
+    dependencies: [
+        // Dependencies declare other packages that this package depends on.
+        .package(name: "swift-nio", path: ".."),
+    ],
+    targets: [
+        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+        // Targets can depend on other targets in this package, and on products in packages this package depends on.
+        .target(
+            name: "swift-nio-http1-fuzz",
+            dependencies: [.product(name: "NIOHTTP1", package: "swift-nio")]),
+    ]
+)
diff --git a/projects/swift-nio/build.sh b/projects/swift-nio/build.sh
new file mode 100755
index 0000000..1544e2b
--- /dev/null
+++ b/projects/swift-nio/build.sh
@@ -0,0 +1,40 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# build project
+mkdir swift-nio-fuzz
+cd swift-nio-fuzz
+swift package init --type=executable
+rm -Rf Sources/swift-nio-fuzz
+mkdir Sources/swift-nio-http1-fuzz
+cp $SRC/fuzz_http1.swift Sources/swift-nio-http1-fuzz/main.swift
+cp $SRC/Package.swift Package.swift
+
+. precompile_swift
+swift build -c debug $SWIFTFLAGS
+(
+cd .build/debug/
+find . -maxdepth 1 -type f -name "*fuzz" -executable | while read i; do cp $i $OUT/"$i"-debug; done
+)
+swift build -c release $SWIFTFLAGS
+(
+cd .build/release/
+find . -maxdepth 1 -type f -name "*fuzz" -executable | while read i; do cp $i $OUT/"$i"-release; done
+)
+
+cp $SRC/fuzzing/dictionaries/http.dict $OUT/swift-nio-http1-fuzz-debug.dict
+cp $SRC/fuzzing/dictionaries/http.dict $OUT/swift-nio-http1-fuzz-release.dict
diff --git a/projects/swift-nio/fuzz_http1.swift b/projects/swift-nio/fuzz_http1.swift
new file mode 100644
index 0000000..065471a
--- /dev/null
+++ b/projects/swift-nio/fuzz_http1.swift
@@ -0,0 +1,21 @@
+import NIOHTTP1
+import NIO
+
+@_cdecl("LLVMFuzzerTestOneInput")
+public func test(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
+    let bytes = UnsafeRawBufferPointer(start: start, count: count)
+    let channel = EmbeddedChannel()
+    var buffer = channel.allocator.buffer(capacity: count)
+    buffer.writeBytes(bytes)
+    do {
+        try channel.pipeline.addHandler(ByteToMessageHandler(HTTPRequestDecoder())).wait()
+        try channel.writeInbound(buffer)
+        channel.embeddedEventLoop.run()
+    } catch {
+    }
+    do {
+        try channel.finish(acceptAlreadyClosed: true)
+    } catch {
+    }
+    return 0
+}
diff --git a/projects/swift-nio/project.yaml b/projects/swift-nio/project.yaml
new file mode 100644
index 0000000..6c9a01d
--- /dev/null
+++ b/projects/swift-nio/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://github.com/apple/swift-nio"
+language: swift
+primary_contact: "lukasa@apple.com"
+auto_ccs :
+- "johannesweiss@apple.com"
+- "pp_adams@apple.com"
+- "p.antoine@catenacyber.fr"
+
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
+- thread
+main_repo: 'https://github.com/apple/swift-nio.git'
diff --git a/projects/swift-protobuf/Dockerfile b/projects/swift-protobuf/Dockerfile
new file mode 100644
index 0000000..d8be913
--- /dev/null
+++ b/projects/swift-protobuf/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-swift
+
+RUN git clone --depth 1 https://github.com/apple/swift-protobuf.git
+COPY build.sh $SRC
+WORKDIR $SRC/swift-protobuf
diff --git a/projects/swift-protobuf/build.sh b/projects/swift-protobuf/build.sh
new file mode 100755
index 0000000..4c30102
--- /dev/null
+++ b/projects/swift-protobuf/build.sh
@@ -0,0 +1,41 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+. precompile_swift
+cd FuzzTesting
+
+# debug build
+swift build -c debug $SWIFTFLAGS
+(
+cd .build/debug/
+find . -maxdepth 1 -type f -name "Fuzz*" -executable | while read i; do cp $i $OUT/"$i"_debug; done
+)
+
+# release build
+swift build -c release $SWIFTFLAGS
+(
+cd .build/release/
+find . -maxdepth 1 -type f -name "Fuzz*" -executable | while read i; do cp $i $OUT/"$i"_release; done
+)
+
+# Copy any dictionaries over.
+for fuzz_dict in Fuzz*.dict ; do
+  fuzzer_name=$(basename $fuzz_dict .dict)
+  cp $fuzz_dict $OUT/${fuzzer_name}_debug.dict
+  cp $fuzz_dict $OUT/${fuzzer_name}_release.dict
+done
diff --git a/projects/swift-protobuf/project.yaml b/projects/swift-protobuf/project.yaml
new file mode 100644
index 0000000..002ee87
--- /dev/null
+++ b/projects/swift-protobuf/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/apple/swift-protobuf"
+language: swift
+primary_contact: "tkientzle@apple.com"
+auto_ccs :
+- "p.antoine@catenacyber.fr"
+- "thomasvl@google.com"
+
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
+- thread
+main_repo: 'https://github.com/apple/swift-protobuf.git'
diff --git a/projects/systemd/Dockerfile b/projects/systemd/Dockerfile
index 0705c56..09369d2 100644
--- a/projects/systemd/Dockerfile
+++ b/projects/systemd/Dockerfile
@@ -19,7 +19,7 @@
     apt-get install -y gperf m4 gettext python3-pip \
         libcap-dev libmount-dev libkmod-dev \
         pkg-config wget &&\
-    pip3 install meson==0.56.2 ninja
+    pip3 install meson ninja jinja2
 RUN git clone --depth 1 https://github.com/systemd/systemd systemd
 WORKDIR systemd
 COPY build.sh $SRC/
diff --git a/projects/syzkaller/Dockerfile b/projects/syzkaller/Dockerfile
index fdef5b4..a5803a8 100644
--- a/projects/syzkaller/Dockerfile
+++ b/projects/syzkaller/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 
 RUN git clone --depth 1 https://github.com/google/syzkaller/
 
diff --git a/projects/syzkaller/project.yaml b/projects/syzkaller/project.yaml
index 1442c04..ed2b5b6 100644
--- a/projects/syzkaller/project.yaml
+++ b/projects/syzkaller/project.yaml
@@ -2,7 +2,6 @@
 primary_contact: "dvyukov@google.com"
 auto_ccs:
   - "andreyknvl@google.com"
-  - "mmoroz@chromium.org"
   - "syzkaller@googlegroups.com"
 language: go
 fuzzing_engines:
diff --git a/projects/tailscale/Dockerfile b/projects/tailscale/Dockerfile
new file mode 100644
index 0000000..9aaaba5
--- /dev/null
+++ b/projects/tailscale/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone --depth 1 https://github.com/tailscale/tailscale
+COPY build.sh $SRC/
+WORKDIR $SRC/tailscale
diff --git a/projects/tailscale/build.sh b/projects/tailscale/build.sh
new file mode 100644
index 0000000..47f281a
--- /dev/null
+++ b/projects/tailscale/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+compile_go_fuzzer tailscale.com/net/stun FuzzStunParser stun_parser_fuzzer
diff --git a/projects/tailscale/project.yaml b/projects/tailscale/project.yaml
new file mode 100644
index 0000000..06698fd
--- /dev/null
+++ b/projects/tailscale/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://tailscale.com/"
+main_repo: "https://github.com/tailscale/tailscale"
+primary_contact: "Adam@adalogics.com"
+auto_ccs :
+  - "josh@tailscale.com"
+  - "danderson@tailscale.com"
+  - "bradfitz@tailscale.com"
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
diff --git a/projects/tcmalloc/Dockerfile b/projects/tcmalloc/Dockerfile
new file mode 100644
index 0000000..18b8abd
--- /dev/null
+++ b/projects/tcmalloc/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool python
+RUN git clone --depth 1 https://github.com/google/tcmalloc tcmalloc
+WORKDIR tcmalloc
+COPY build.sh $SRC/
diff --git a/projects/tcmalloc/build.sh b/projects/tcmalloc/build.sh
new file mode 100755
index 0000000..b204d1c
--- /dev/null
+++ b/projects/tcmalloc/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+bazel_build_fuzz_tests
diff --git a/projects/tcmalloc/project.yaml b/projects/tcmalloc/project.yaml
new file mode 100644
index 0000000..19ce8c0
--- /dev/null
+++ b/projects/tcmalloc/project.yaml
@@ -0,0 +1,10 @@
+homepage: "tcmalloc"
+language: c++
+primary_contact: "ckennelly@google.com"
+main_repo: "https://github.com/google/tcmalloc"
+auto_ccs:
+ - "david@adalogics.com"
+sanitizers:
+ - address
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
diff --git a/projects/tdengine/Dockerfile b/projects/tdengine/Dockerfile
new file mode 100644
index 0000000..aa78f11
--- /dev/null
+++ b/projects/tdengine/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y  libtool build-essential
+RUN git clone --depth 1 https://github.com/taosdata/TDengine tdengine
+WORKDIR tdengine
+COPY build.sh $SRC/
+COPY *.options $SRC/
diff --git a/projects/tdengine/build.sh b/projects/tdengine/build.sh
new file mode 100755
index 0000000..539915c
--- /dev/null
+++ b/projects/tdengine/build.sh
@@ -0,0 +1,47 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+sed -i 's/git@/https:\/\//g' .gitmodules
+sed -i 's/:taos/\/taos/g' .gitmodules
+sed -i 's/\.git//g' .gitmodules
+
+git submodule update --init --recursive
+sed -i 's/-Werror//g' ./cmake/define.inc
+mkdir debug && cd debug
+cmake .. && cmake --build .
+
+cd build/bin
+
+# Now let's build the fuzzer.
+$CC $CFLAGS -DLINUX -DUSE_LIBICONV -D_LINUX -D_M_X64 \
+     -D_TD_LINUX  -D_TD_LINUX_64 \
+     -I/src/tdengine/src/inc -I/src/tdengine/src/os/inc \
+     -I/src/tdengine/src/util/inc -I/src/tdengine/src/common/inc \
+     -I/src/tdengine/src/tsdb/inc -I/src/tdengine/src/query/inc \
+     -o sql-fuzzer.o -c $SRC/tdengine/tests/fuzz//sql-fuzzer.c
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE sql-fuzzer.o -o $OUT/sql-fuzzer \
+      ../../../debug/src/common/CMakeFiles/common.dir/src/tglobal.c.o  \
+      -Wl,--start-group \
+      ../lib/libtaos_static.a  ../lib/libtrpc.a ../lib/libtutil.a \
+      ../lib/libquery.a  ../lib/libtsdb.a ../lib/libcommon.a \
+       ../lib/libtfs.a ../lib/liblz4.a ../lib/libos.a \
+       ../lib/liboslinux.a ../lib/libz.a ../lib/librmonotonic.a \
+       ../lib/liblua.a \
+       -Wl,--end-group -lpthread -ldl
+
+cp $SRC/*.options $OUT/
diff --git a/projects/tdengine/project.yaml b/projects/tdengine/project.yaml
new file mode 100644
index 0000000..63236ee
--- /dev/null
+++ b/projects/tdengine/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://www.taosdata.com/en/documentation/"
+language: c
+primary_contact: "sangshuduo@gmail.com"
+main_repo: "https://github.com/taosdata/TDengine"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/tdengine/sql-fuzzer.options b/projects/tdengine/sql-fuzzer.options
new file mode 100644
index 0000000..f9d0965
--- /dev/null
+++ b/projects/tdengine/sql-fuzzer.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+detect_leaks=0
diff --git a/projects/teleport/Dockerfile b/projects/teleport/Dockerfile
index 8ffafb3..c3e3beb 100644
--- a/projects/teleport/Dockerfile
+++ b/projects/teleport/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/gravitational/teleport.git
 COPY build.sh $SRC/
 WORKDIR $SRC/teleport
diff --git a/projects/tendermint/Dockerfile b/projects/tendermint/Dockerfile
new file mode 100644
index 0000000..58899ef
--- /dev/null
+++ b/projects/tendermint/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-go
+RUN git clone https://github.com/tendermint/tendermint
+
+COPY build.sh $SRC
+WORKDIR $SRC/tendermint
diff --git a/projects/tendermint/build.sh b/projects/tendermint/build.sh
new file mode 100755
index 0000000..8981352
--- /dev/null
+++ b/projects/tendermint/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+bash -x ./test/fuzz/oss-fuzz-build.sh
diff --git a/projects/tendermint/project.yaml b/projects/tendermint/project.yaml
new file mode 100644
index 0000000..67d02d5
--- /dev/null
+++ b/projects/tendermint/project.yaml
@@ -0,0 +1,15 @@
+homepage: "https://github.com/tendermint/tendermint"
+primary_contact: "security@interchain.io"
+auto_ccs:
+  - fuzzing@orijtech.com
+  - emmanuel@orijtech.com
+  - cuong@orijtech.com
+  - callum@interchain.io
+  - tychoish@interchain.io
+  - william@interchain.io
+language: go
+fuzzing_engines:
+  - libfuzzer
+sanitizers:
+  - address
+main_repo: "https://github.com/tendermint/tendermint"
diff --git a/projects/tensorflow-py/Dockerfile b/projects/tensorflow-py/Dockerfile
index dea03cb..e5e2a66 100644
--- a/projects/tensorflow-py/Dockerfile
+++ b/projects/tensorflow-py/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
         curl \
diff --git a/projects/tensorflow-py/build.sh b/projects/tensorflow-py/build.sh
index afd501b..8e12b3d 100644
--- a/projects/tensorflow-py/build.sh
+++ b/projects/tensorflow-py/build.sh
@@ -39,7 +39,7 @@
 LD_PRELOAD=\"\$this_dir/sanitizer_with_fuzzer.so \$this_dir/libz-eb09ad1d.so.1.2.3 \$this_dir/libquadmath-2d0c479f.so.0.0.0 \$this_dir/libgfortran-2e0d59d6.so.5.0.0 \$this_dir/libopenblasp-r0-09e95953.3.13.so\" \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
 
 mv $SRC/tensorflow/tensorflow_src $SRC/tensorflow/tensorflow
diff --git a/projects/tensorflow-py/project.yaml b/projects/tensorflow-py/project.yaml
index 64c5eba..cac4a1a 100644
--- a/projects/tensorflow-py/project.yaml
+++ b/projects/tensorflow-py/project.yaml
@@ -3,6 +3,7 @@
 primary_contact: "amitpatankar@google.com"
 auto_ccs:
  - "mihaimaruseac@google.com"
+ - "lpak@google.com"
 fuzzing_engines:
   - libfuzzer
 sanitizers:
diff --git a/projects/tesseract-ocr/Dockerfile b/projects/tesseract-ocr/Dockerfile
index 20094e7..3e02c5e 100644
--- a/projects/tesseract-ocr/Dockerfile
+++ b/projects/tesseract-ocr/Dockerfile
@@ -15,8 +15,24 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y autoconf automake libtool pkg-config libpng-dev libjpeg8-dev libtiff5-dev zlib1g-dev
+RUN apt-get update && apt-get install -y autoconf automake libtool pkg-config libpng-dev libjpeg8-dev liblzma-dev
+
+RUN git clone https://www.cl.cam.ac.uk/~mgk25/git/jbigkit jbigkit && \
+    cd jbigkit && \
+    make clean && \
+    make -j$(nproc) lib && \
+    cp libjbig/libjbig.a /usr/lib/x86_64-linux-gnu/libjbig.a
+
+RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff libtiff && \
+  cd libtiff && \
+  cmake . -DBUILD_SHARED_LIBS=off && \
+  make clean && \
+  make -j$(nproc) && \
+  make install && \
+  cp libtiff/libtiff.a /usr/lib/x86_64-linux-gnu/libtiff.a
+
 RUN git clone --depth 1 https://github.com/danbloomberg/leptonica
 RUN git clone --depth 1 https://github.com/tesseract-ocr/tesseract
 RUN git clone --depth 1 https://github.com/tesseract-ocr/tessdata
+
 COPY build.sh $SRC/
diff --git a/projects/thrift/Dockerfile b/projects/thrift/Dockerfile
index 0401883..f669417 100644
--- a/projects/thrift/Dockerfile
+++ b/projects/thrift/Dockerfile
@@ -15,7 +15,30 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y libssl-dev pkg-config autoconf automake libtool bison flex libboost-all-dev
+
+# We use compile_go_fuzzer in this set up and also go itself
+FROM gcr.io/oss-fuzz-base/base-builder-go
+
+RUN apt-get update && apt-get install -y libssl-dev pkg-config autoconf automake libtool bison flex wget make \
+    autoconf \
+    automake \
+    sudo \
+    gcc \
+    g++ \
+    python-dev \
+    cmake \
+    ninja-build
+
+RUN wget https://sourceforge.net/projects/boost/files/boost/1.70.0/boost_1_70_0.tar.gz && \
+    tar xzf boost_1_70_0.tar.gz && \
+    cd boost_1_70_0 && \
+    ./bootstrap.sh --with-toolset=clang && \
+    ./b2 clean && \
+    ./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" -j$(nproc) install && \
+    cd .. && \
+    rm -rf boost_1_70_0
+
+#libboost-all-dev
 RUN git clone --depth 1 https://github.com/apache/thrift
 WORKDIR $SRC/thrift
 COPY build.sh $SRC/
diff --git a/projects/thrift/build.sh b/projects/thrift/build.sh
index 8194063..ffbd115 100755
--- a/projects/thrift/build.sh
+++ b/projects/thrift/build.sh
@@ -18,6 +18,10 @@
 # build project
 export ASAN_OPTIONS=detect_leaks=0
 
+if [ "$SANITIZER" = "coverage" ]
+then
+    cp /usr/bin/ld.gold /usr/bin/ld
+fi
 ./bootstrap.sh
 # rust fails compilation with clippy warnings
 ./configure --with-rs=no
diff --git a/projects/tidb/Dockerfile b/projects/tidb/Dockerfile
index 5c7d0fd..17091a6 100644
--- a/projects/tidb/Dockerfile
+++ b/projects/tidb/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/pingcap/tidb
 COPY build.sh $SRC/
 WORKDIR $SRC/tidb
diff --git a/projects/tidb/build.sh b/projects/tidb/build.sh
index c11028f..da5fd1c 100755
--- a/projects/tidb/build.sh
+++ b/projects/tidb/build.sh
@@ -15,10 +15,6 @@
 #
 ################################################################################
 
-# Insert empty main function
-sed -i '23 i\func main(){}'\\n $SRC/tidb/plugin/conn_ip_example/conn_ip_example.go
-
-go get ./...
 
 compile_go_fuzzer github.com/pingcap/tidb/types FuzzMarshalJSON fuzzMarshalJSON
 compile_go_fuzzer github.com/pingcap/tidb/types FuzzNewBitLiteral fuzzNewBitLiteral
diff --git a/projects/tidy-html5/build.sh b/projects/tidy-html5/build.sh
index d10c505..7b75ab6 100644
--- a/projects/tidy-html5/build.sh
+++ b/projects/tidy-html5/build.sh
@@ -22,12 +22,12 @@
 cmake -GNinja ${SRC}/tidy-html5/
 ninja
 
-for fuzzer in tidy_config_fuzzer tidy_fuzzer; do
+for fuzzer in tidy_config_fuzzer tidy_fuzzer tidy_xml_fuzzer tidy_parse_string_fuzzer tidy_parse_file_fuzzer tidy_general_fuzzer; do
     ${CC} ${CFLAGS} -c -I${SRC}/tidy-html5/include \
         $SRC/${fuzzer}.c -o ${fuzzer}.o
     ${CXX} ${CXXFLAGS} -std=c++11 ${fuzzer}.o \
         -o $OUT/${fuzzer} \
-        $LIB_FUZZING_ENGINE libtidys.a
+        $LIB_FUZZING_ENGINE libtidy.a
 done
 
 cp ${SRC}/*.options ${OUT}/
diff --git a/projects/tidy-html5/project.yaml b/projects/tidy-html5/project.yaml
index d62facb..086f83b 100644
--- a/projects/tidy-html5/project.yaml
+++ b/projects/tidy-html5/project.yaml
@@ -1,6 +1,6 @@
 homepage: "http://www.html-tidy.org/"
 language: c++
-primary_contact: "sbucur@google.com"
+primary_contact: "balthisar@gmail.com"
 auto_ccs:
   - "nmarrow@google.com"
   - "pmokati@google.com"
diff --git a/projects/tidy-html5/tidy_general_fuzzer.c b/projects/tidy-html5/tidy_general_fuzzer.c
new file mode 100644
index 0000000..67a064c
--- /dev/null
+++ b/projects/tidy-html5/tidy_general_fuzzer.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "tidybuffio.h"
+#include "tidy.h"
+
+// All boolean options. These will be set randomly
+// based on the fuzzer data.
+TidyOptionId bool_options[] = {
+  TidyJoinClasses, 
+  TidyJoinStyles, 
+  TidyKeepFileTimes, 
+  TidyKeepTabs, 
+  TidyLiteralAttribs, 
+  TidyLogicalEmphasis, 
+  TidyLowerLiterals, 
+  TidyMakeBare, 
+  TidyFixUri, 
+  TidyForceOutput, 
+  TidyGDocClean, 
+  TidyHideComments,
+  TidyMark, 
+  TidyXmlTags, 
+  TidyMakeClean,
+  TidyAnchorAsName, 
+  TidyMergeEmphasis, 
+  TidyMakeBare, 
+  TidyMetaCharset, 
+  TidyMuteShow, 
+  TidyNCR, 
+  TidyNumEntities, 
+  TidyOmitOptionalTags, 
+  TidyPunctWrap, 
+  TidyQuiet,
+  TidyQuoteAmpersand,  
+  TidyQuoteMarks, 
+  TidyQuoteNbsp, 
+  TidyReplaceColor, 
+  TidyShowFilename, 
+  TidyShowInfo, 
+  TidyShowMarkup, 
+  TidyShowMetaChange, 
+  TidyShowWarnings, 
+  TidySkipNested, 
+  TidyUpperCaseTags, 
+  TidyWarnPropAttrs, 
+  TidyWord2000, 
+  TidyWrapAsp, 
+  TidyWrapAttVals, 
+  TidyWrapJste, 
+  TidyWrapPhp, 
+  TidyWrapScriptlets, 
+  TidyWrapSection, 
+  TidyWriteBack,
+};
+
+void set_option(const uint8_t** data, size_t *size, TidyDoc *tdoc, TidyOptionId tboolID) {
+  uint8_t decider;
+  decider = **data;
+  *data += 1; 
+  *size -= 1;
+  if (decider % 2 == 0) tidyOptSetBool( *tdoc, tboolID, yes );
+  else { tidyOptSetBool( *tdoc, tboolID, no ); }
+}
+
+int TidyXhtml(const uint8_t* data, size_t size, TidyBuffer* output, TidyBuffer* errbuf) {
+  uint8_t decider;
+
+  // We need enough data for picking all of the options. One byte per option.
+  if (size < 5+(sizeof(bool_options)/sizeof(bool_options[0]))) {
+    return 0;
+  }
+
+  TidyDoc tdoc = tidyCreate();
+
+  // Decide output format
+  decider = *data;
+  data++; size--;
+  if (decider % 3 == 0) tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
+  else { tidyOptSetBool( tdoc, TidyXhtmlOut, no ); }
+
+  if (decider % 3 == 1) tidyOptSetBool( tdoc, TidyHtmlOut, yes );
+  else { tidyOptSetBool( tdoc, TidyHtmlOut, no ); }
+
+  if (decider % 3 == 2) tidyOptSetBool( tdoc, TidyXmlOut, yes );
+  else { tidyOptSetBool( tdoc, TidyXmlOut, no ); }
+
+  // Set options 
+  for (int i=0; i < sizeof(bool_options)/sizeof(TidyOptionId); i++) {
+    set_option(&data, &size, &tdoc, bool_options[i]);
+  }
+
+  // Set an error buffer.
+  tidySetErrorBuffer(tdoc, errbuf);
+
+  // Parse the data
+  decider = *data;
+  data++; size--;
+  switch (decider % 2) {
+    case 0: {
+      char filename[256];
+      sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+
+      FILE *fp = fopen(filename, "wb");
+      if (!fp) {
+          return 0;
+      }
+      fwrite(data, size, 1, fp);
+      fclose(fp);
+
+      tidyParseFile(tdoc, filename);
+      unlink(filename);
+    }
+    break;
+    case 1: {
+      char *inp = malloc(size+1);
+      inp[size] = '\0';
+      memcpy(inp, data, size);
+      tidyParseString(tdoc, inp);
+      free(inp);
+    }
+  }
+
+  // Cleanup
+  tidyRelease( tdoc );
+
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  TidyBuffer fuzz_toutput;
+  TidyBuffer fuzz_terror;
+
+  tidyBufInit(&fuzz_toutput);
+  tidyBufInit(&fuzz_terror);
+
+  TidyXhtml(data, size, &fuzz_toutput, &fuzz_terror);
+
+  tidyBufFree(&fuzz_toutput);
+  tidyBufFree(&fuzz_terror);
+
+  return 0;
+}
diff --git a/projects/tidy-html5/tidy_parse_file_fuzzer.c b/projects/tidy-html5/tidy_parse_file_fuzzer.c
new file mode 100644
index 0000000..febeaa6
--- /dev/null
+++ b/projects/tidy-html5/tidy_parse_file_fuzzer.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "tidybuffio.h"
+#include "tidy.h"
+
+
+int TidyXhtml(const uint8_t* data, size_t size, TidyBuffer* output, TidyBuffer* errbuf) {
+  Bool ok;
+
+  TidyDoc tdoc = tidyCreate();
+
+  ok = tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
+  if (ok) tidySetErrorBuffer(tdoc, errbuf);
+ 
+  char filename[256];
+  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+
+  FILE *fp = fopen(filename, "wb");
+  if (!fp) {
+    return 0;
+  }
+  fwrite(data, size, 1, fp);
+  fclose(fp);
+
+  tidyParseFile(tdoc, filename);
+
+  tidyRelease( tdoc );
+  unlink(filename);
+
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  TidyBuffer fuzz_toutput;
+  TidyBuffer fuzz_terror;
+
+  tidyBufInit(&fuzz_toutput);
+  tidyBufInit(&fuzz_terror);
+
+  TidyXhtml(data, size, &fuzz_toutput, &fuzz_terror);
+
+  tidyBufFree(&fuzz_toutput);
+  tidyBufFree(&fuzz_terror);
+  return 0;
+}
+
diff --git a/projects/tidy-html5/tidy_parse_string_fuzzer.c b/projects/tidy-html5/tidy_parse_string_fuzzer.c
new file mode 100644
index 0000000..3d1f7e2
--- /dev/null
+++ b/projects/tidy-html5/tidy_parse_string_fuzzer.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "tidybuffio.h"
+#include "tidy.h"
+
+
+int TidyXhtml(const char* input, TidyBuffer* output, TidyBuffer* errbuf) {
+  TidyDoc tdoc = tidyCreate();
+  tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
+  tidySetErrorBuffer(tdoc, errbuf);
+
+  tidyParseString(tdoc, input);
+
+  tidyCleanAndRepair(tdoc);
+  tidyRunDiagnostics(tdoc);
+  tidyOptSetBool(tdoc, TidyForceOutput, yes);
+  tidySaveBuffer(tdoc, output);
+  tidyRelease( tdoc );
+  return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  char *fuzz_inp = malloc(size+1);
+  memcpy(fuzz_inp, data, size);
+  fuzz_inp[size] = '\0';
+
+  TidyBuffer fuzz_toutput;
+  TidyBuffer fuzz_terror;
+
+  tidyBufInit(&fuzz_toutput);
+  tidyBufInit(&fuzz_terror);
+
+  TidyXhtml(fuzz_inp, &fuzz_toutput, &fuzz_terror);
+
+  tidyBufFree(&fuzz_toutput);
+  tidyBufFree(&fuzz_terror);
+  free(fuzz_inp);
+  return 0;
+}
+
diff --git a/projects/tidy-html5/tidy_xml_fuzzer.c b/projects/tidy-html5/tidy_xml_fuzzer.c
new file mode 100644
index 0000000..c405511
--- /dev/null
+++ b/projects/tidy-html5/tidy_xml_fuzzer.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "tidy.h"
+#include "tidybuffio.h"
+#include "tidyenum.h"
+#include "tidyplatform.h"
+
+void TidyXml(char *fuzz_inp, TidyBuffer *toutput,
+             TidyBuffer *terror) {
+  TidyDoc tdoc = tidyCreate();
+  tidyBufClear(toutput);
+  tidyBufClear(terror);
+  if (tidyOptSetBool(tdoc, TidyXmlOut, yes)) {
+    tidySetCharEncoding(tdoc, "utf8");
+    tidySetErrorBuffer(tdoc, terror);
+    tidyOptSetInt(tdoc, TidyWrapLen, 0);
+    tidyOptSetBool(tdoc, TidyXmlTags, yes);
+    tidyOptSetBool(tdoc, TidyQuoteNbsp, no);
+    tidyOptSetBool(tdoc, TidyNumEntities, yes);
+    tidyOptSetBool(tdoc, TidyQuiet, yes);
+    tidyOptSetBool(tdoc, TidyMark, no);
+    tidyOptSetBool(tdoc, TidyShowWarnings, no);
+    tidyParseString(tdoc, fuzz_inp);
+    tidyCleanAndRepair(tdoc);
+    tidyRunDiagnostics(tdoc);
+    tidySaveBuffer(tdoc, toutput);
+  }
+
+  tidyRelease(tdoc);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  char *fuzz_inp = malloc(size+1);
+  memcpy(fuzz_inp, data, size);
+  fuzz_inp[size] = '\0';
+
+  TidyBuffer fuzz_toutput;
+  TidyBuffer fuzz_terror;
+
+  tidyBufInit(&fuzz_toutput);
+  tidyBufInit(&fuzz_terror);
+
+  TidyXml(fuzz_inp, &fuzz_toutput, &fuzz_terror);
+
+  free(fuzz_inp);
+  tidyBufFree(&fuzz_toutput);
+  tidyBufFree(&fuzz_terror);
+  return 0;
+}
diff --git a/projects/tint/Dockerfile b/projects/tint/Dockerfile
new file mode 100644
index 0000000..dc293e9
--- /dev/null
+++ b/projects/tint/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool ninja-build
+RUN git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' --depth 1
+ENV PATH="${SRC}/depot_tools:${PATH}"
+RUN git clone --depth 1 https://dawn.googlesource.com/tint tint
+WORKDIR tint
+COPY build.sh $SRC/
diff --git a/projects/tint/build.sh b/projects/tint/build.sh
new file mode 100755
index 0000000..68b682b
--- /dev/null
+++ b/projects/tint/build.sh
@@ -0,0 +1,106 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cp standalone.gclient .gclient
+gclient sync
+
+mkdir -p out/Debug
+pushd out/Debug
+
+# ubsan's vptr sanitization is desabled as it requires RTTI, which is disabled
+# when building tint.
+CFLAGS="$CFLAGS -fno-sanitize=vptr" \
+CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" \
+cmake -GNinja ../.. -DCMAKE_BUILD_TYPE=Release -DTINT_BUILD_FUZZERS=ON -DTINT_BUILD_SPIRV_TOOLS_FUZZER=ON -DTINT_BUILD_TESTS=OFF -DTINT_LIB_FUZZING_ENGINE_LINK_OPTIONS=$LIB_FUZZING_ENGINE
+
+if [ -n "${OSS_FUZZ_CI-}" ]
+then
+  # When running in the CI, restrict to a small number of fuzz targets to save
+  # time and disk space.  A SPIR-V Tools-based fuzzer that uses the HLSL
+  # back-end, and a regular fuzzer that uses the MSL back-end, are selected.
+  SPIRV_TOOLS_FUZZERS="tint_spirv_tools_hlsl_writer_fuzzer"
+  SPIRV_FUZZERS="tint_spv_reader_msl_writer_fuzzer\
+   ${SPIRV_TOOLS_FUZZERS}"
+else
+  SPIRV_TOOLS_FUZZERS="tint_spirv_tools_hlsl_writer_fuzzer\
+   tint_spirv_tools_msl_writer_fuzzer\
+   tint_spirv_tools_spv_writer_fuzzer\
+   tint_spirv_tools_wgsl_writer_fuzzer"
+  SPIRV_FUZZERS="tint_spv_reader_hlsl_writer_fuzzer\
+   tint_spv_reader_msl_writer_fuzzer\
+   tint_spv_reader_spv_writer_fuzzer\
+   tint_spv_reader_wgsl_writer_fuzzer\
+   ${SPIRV_TOOLS_FUZZERS}"
+fi
+
+# The spirv-as tool is used to build seed corpora
+ninja ${SPIRV_FUZZERS}
+
+cp ${SPIRV_FUZZERS} $OUT
+
+popd
+
+# An un-instrumented build of spirv-as is used to generate a corpus of SPIR-V binaries.
+mkdir -p out/Standard
+pushd out/Standard
+
+# Back-up instrumentation options
+CFLAGS_SAVE="$CFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS"
+unset CFLAGS
+unset CXXFLAGS
+export AFL_NOOPT=1
+
+cmake -GNinja ../.. -DCMAKE_BUILD_TYPE=Release
+ninja spirv-as
+
+# Restore instrumentation options
+export CFLAGS="${CFLAGS_SAVE}"
+export CXXFLAGS="${CXXFLAGS_SAVE}"
+unset AFL_NOOPT
+
+popd
+
+# Generate a corpus of SPIR-V binaries from the SPIR-V assembly files in the
+# tint repository.
+mkdir $WORK/spirv-corpus
+python3 fuzzers/generate_spirv_corpus.py test $WORK/spirv-corpus out/Standard/spirv-as
+
+mkdir $WORK/spirv-corpus-hashed-names
+for f in `ls $WORK/spirv-corpus/*.spv`
+do
+  hashed_name=$(sha1sum "$f" | awk '{print $1}')
+  cp $f $WORK/spirv-corpus-hashed-names/$hashed_name
+done
+
+zip -j "$WORK/seed_corpus.zip" "$WORK"/spirv-corpus-hashed-names/*
+
+for fuzzer in $SPIRV_FUZZERS
+do
+  cp "$WORK/seed_corpus.zip" "$OUT/${fuzzer}_seed_corpus.zip"
+done
+
+for fuzzer in $SPIRV_TOOLS_FUZZERS
+do
+  echo "[libfuzzer]
+max_len = 10000
+cross_over = 0
+mutate_depth = 1
+tint_enable_all_mutations = false
+tint_mutation_batch_size = 5
+" > "$OUT/${fuzzer}.options"
+done
diff --git a/projects/tint/project.yaml b/projects/tint/project.yaml
new file mode 100644
index 0000000..46fec18
--- /dev/null
+++ b/projects/tint/project.yaml
@@ -0,0 +1,13 @@
+homepage: https://dawn.googlesource.com/tint
+language: c++
+primary_contact: bclayton@google.com 
+auto_ccs:
+  - "afdx@google.com"
+sanitizers:
+  - address
+  - memory
+  - undefined
+main_repo: 'https://dawn.googlesource.com/tint.git'
+architectures:
+  - x86_64
+  - i386
diff --git a/projects/tinyobjloader/Dockerfile b/projects/tinyobjloader/Dockerfile
new file mode 100644
index 0000000..72ad9ea
--- /dev/null
+++ b/projects/tinyobjloader/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN git clone --depth 1 https://github.com/tinyobjloader/tinyobjloader
+COPY build.sh $SRC
+WORKDIR $SRC/tinyobjloader
diff --git a/projects/tinyobjloader/build.sh b/projects/tinyobjloader/build.sh
new file mode 100755
index 0000000..e80301b
--- /dev/null
+++ b/projects/tinyobjloader/build.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+# build project
+mkdir build && cd build
+cmake .. -DBUILD_SHARED_LIBS=OFF
+make -j $(nproc)
+cp fuzz* $OUT/
diff --git a/projects/tinyobjloader/project.yaml b/projects/tinyobjloader/project.yaml
new file mode 100644
index 0000000..467e889
--- /dev/null
+++ b/projects/tinyobjloader/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/tinyobjloader/tinyobjloader"
+language: c++
+primary_contact: "syoyo@lighttransport.com"
+auto_ccs :
+- "p.antoine@catenacyber.fr"
+
+sanitizers:
+- address
+- undefined
+main_repo: 'https://github.com/tinyobjloader/tinyobjloader'
diff --git a/projects/tmux/build.sh b/projects/tmux/build.sh
index 53de126..f4fe555 100644
--- a/projects/tmux/build.sh
+++ b/projects/tmux/build.sh
@@ -44,3 +44,8 @@
     split -a5 -db$MAXLEN - iterm2.
 zip -q -j -r "${OUT}/input-fuzzer_seed_corpus.zip" \
     "${WORK}/fuzzing_corpus/"
+
+# Handle libevent not existing on runner.
+mkdir $OUT/lib
+cp /lib/x86_64-linux-gnu/libevent_core* $OUT/lib
+patchelf --set-rpath '$ORIGIN/lib' $OUT/input-fuzzer
diff --git a/projects/tor/Dockerfile b/projects/tor/Dockerfile
index 37d9753..3211c40 100644
--- a/projects/tor/Dockerfile
+++ b/projects/tor/Dockerfile
@@ -15,7 +15,7 @@
 ##############################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y autoconf automake make libtool
+RUN apt-get update && apt-get install -y autoconf automake make libtool pkg-config
 RUN git clone --depth 1 https://git.torproject.org/tor.git
 RUN git clone --depth 1 https://git.torproject.org/fuzzing-corpora.git tor-fuzz-corpora
 RUN git clone --depth 1 https://github.com/madler/zlib.git
diff --git a/projects/tor/build.sh b/projects/tor/build.sh
index 1c5154a..8f4d029 100644
--- a/projects/tor/build.sh
+++ b/projects/tor/build.sh
@@ -63,13 +63,15 @@
     --with-libevent-dir=${SRC}/deps \
     --with-openssl-dir=${SRC}/deps \
     --with-zlib-dir=${SRC}/deps \
-    --disable-gcc-hardening
+    --disable-gcc-hardening \
+    LDFLAGS="-L${TOR_DEPS}/lib64"
 
 make clean
+make micro-revision.i  # Workaround from https://gitlab.torproject.org/tpo/core/tor/-/issues/29520#note_2749427
 make -j$(nproc) oss-fuzz-fuzzers
 
 TORLIBS="`make show-testing-libs`"
-TORLIBS="$TORLIBS -lm -Wl,-Bstatic -lssl -lcrypto -levent -lz -L${TOR_DEPS}/lib"
+TORLIBS="$TORLIBS -lm -Wl,-Bstatic -lssl -lcrypto -levent -lz -L${TOR_DEPS}/lib -L${TOR_DEPS}/lib64"
 TORLIBS="$TORLIBS -Wl,-Bdynamic"
 
 for fuzzer in src/test/fuzz/*.a; do
diff --git a/projects/tpm2-tss/Dockerfile b/projects/tpm2-tss/Dockerfile
index 9f74c7a..f2dbae6 100644
--- a/projects/tpm2-tss/Dockerfile
+++ b/projects/tpm2-tss/Dockerfile
@@ -68,10 +68,10 @@
         && make -j $(nproc) && make install
 RUN rm -fr $autoconf_archive.tar.xz
 
-ARG ibmtpm_name=ibmtpm1119
+ARG ibmtpm_name=ibmtpm1661
 WORKDIR /tmp
 RUN wget --quiet --show-progress --progress=dot:giga "https://downloads.sourceforge.net/project/ibmswtpm2/$ibmtpm_name.tar.gz" \
-	&& sha256sum $ibmtpm_name.tar.gz | grep ^b9eef79904e276aeaed2a6b9e4021442ef4d7dfae4adde2473bef1a6a4cd10fb \
+	&& sha256sum $ibmtpm_name.tar.gz | grep ^55145928ad2b24f34be6a0eacf9fb492e10e0ea919b8428c721fa970e85d6147 \
 	&& mkdir -p $ibmtpm_name \
 	&& tar xvf $ibmtpm_name.tar.gz -C $ibmtpm_name \
 	&& rm $ibmtpm_name.tar.gz
diff --git a/projects/tpm2-tss/project.yaml b/projects/tpm2-tss/project.yaml
index 04af6fe..7ac01a9 100644
--- a/projects/tpm2-tss/project.yaml
+++ b/projects/tpm2-tss/project.yaml
@@ -1,12 +1,12 @@
 homepage: "https://github.com/tpm2-software/tpm2-tss"
 language: c++
-primary_contact: "tadeusz.struk@intel.com"
+primary_contact: "william.c.roberts@intel.com"
 auto_ccs:
   - "andreas.fuchs@sit.fraunhofer.de"
-  - "john.s.andersen@intel.com"
-  - "william.c.roberts@intel.com"
   - "tstruk@gmail.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
+main_repo: 'https://github.com/tstruk/tpm2-tss.git'
\ No newline at end of file
diff --git a/projects/tpm2/Dockerfile b/projects/tpm2/Dockerfile
index 3cd80b8..f008ce3 100644
--- a/projects/tpm2/Dockerfile
+++ b/projects/tpm2/Dockerfile
@@ -5,7 +5,7 @@
 # Defines a docker image that can build fuzzers.
 #
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make libssl-dev binutils libgcc-5-dev
+RUN apt-get update && apt-get install -y make libssl-dev binutils libgcc-9-dev
 RUN git clone --depth 1 https://chromium.googlesource.com/chromiumos/third_party/tpm2
 WORKDIR tpm2
 RUN cp /src/tpm2/fuzz/build.sh /src/
diff --git a/projects/ujson/Dockerfile b/projects/ujson/Dockerfile
index 81550c6..9b43468 100644
--- a/projects/ujson/Dockerfile
+++ b/projects/ujson/Dockerfile
@@ -14,13 +14,13 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 
 RUN pip3 install hypothesis
 
 RUN git clone \
 	--depth 1 \
-	--branch master \
+	--branch main \
 	https://github.com/ultrajson/ultrajson.git
 
 WORKDIR ultrajson
diff --git a/projects/ujson/build.sh b/projects/ujson/build.sh
index fd339d5..094d851 100755
--- a/projects/ujson/build.sh
+++ b/projects/ujson/build.sh
@@ -31,5 +31,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/ujson/hypothesis_structured_fuzzer.py b/projects/ujson/hypothesis_structured_fuzzer.py
index c07a2cf..ef43c26 100644
--- a/projects/ujson/hypothesis_structured_fuzzer.py
+++ b/projects/ujson/hypothesis_structured_fuzzer.py
@@ -58,6 +58,7 @@
 
 
 @given(obj=JSON_OBJECTS, kwargs=st.fixed_dictionaries(UJSON_ENCODE_KWARGS))
+@atheris.instrument_func
 def test_ujson_roundtrip(obj, kwargs):
     """Check that all JSON objects round-trip regardless of other options."""
     assert obj == ujson.decode(ujson.encode(obj, **kwargs))
@@ -68,5 +69,5 @@
     # and minimize any failures discovered by earlier runs or by OSS-Fuzz, or
     # briefly search for new failures if none are known.
     # Or, when running via OSS-Fuzz, we'll execute it via the fuzzing hook:
-    atheris.Setup(sys.argv, test_ujson_roundtrip.hypothesis.fuzz_one_input)
+    atheris.Setup(sys.argv, atheris.instrument_func(test_ujson_roundtrip.hypothesis.fuzz_one_input))
     atheris.Fuzz()
diff --git a/projects/ujson/json_differential_fuzzer.py b/projects/ujson/json_differential_fuzzer.py
index fd26de1..4ab012c 100755
--- a/projects/ujson/json_differential_fuzzer.py
+++ b/projects/ujson/json_differential_fuzzer.py
@@ -37,12 +37,15 @@
 misinterpreting them is not.
 """
 
-import atheris_no_libfuzzer as atheris
-import json
-import ujson
+import atheris
 import sys
 
+with atheris.instrument_imports():
+  import json
+  import ujson
 
+
+@atheris.instrument_func
 def ClearAllIntegers(data):
   """Used to prevent known bug; sets all integers in data recursively to 0."""
   if type(data) == int:
@@ -56,6 +59,7 @@
   return data
 
 
+@atheris.instrument_func
 def TestOneInput(input_bytes):
   fdp = atheris.FuzzedDataProvider(input_bytes)
   original = fdp.ConsumeUnicode(sys.maxsize)
diff --git a/projects/ujson/ujson_fuzzer.py b/projects/ujson/ujson_fuzzer.py
index c785ec6..51b33a9 100755
--- a/projects/ujson/ujson_fuzzer.py
+++ b/projects/ujson/ujson_fuzzer.py
@@ -29,7 +29,7 @@
 """
 
 import sys
-import atheris_no_libfuzzer as atheris
+import atheris
 import ujson
 
 
diff --git a/projects/unicode-rs/Dockerfile b/projects/unicode-rs/Dockerfile
new file mode 100644
index 0000000..9d9cc47
--- /dev/null
+++ b/projects/unicode-rs/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+
+RUN git clone --depth 1 https://github.com/unicode-rs/unicode-normalization
+RUN git clone --depth 1 https://github.com/unicode-rs/unicode-segmentation
+
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/unicode-rs/build.sh b/projects/unicode-rs/build.sh
new file mode 100755
index 0000000..9db130e
--- /dev/null
+++ b/projects/unicode-rs/build.sh
@@ -0,0 +1,29 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+if [ $SANITIZER != "coverage" ]
+then
+    cd $SRC/unicode-normalization
+    cargo fuzz build -O 
+    cp fuzz/target/x86_64-unknown-linux-gnu/release/unicode-normalization $OUT/unicode-normalization-normalization
+    cp fuzz/target/x86_64-unknown-linux-gnu/release/streaming $OUT/unicode-normalization-streaming
+fi
+
+cd $SRC/unicode-segmentation/
+cargo fuzz build -O
+cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 $OUT/unicode-segmentation-fuzzer
+
diff --git a/projects/unicode-rs/project.yaml b/projects/unicode-rs/project.yaml
new file mode 100644
index 0000000..914c145
--- /dev/null
+++ b/projects/unicode-rs/project.yaml
@@ -0,0 +1,10 @@
+homepage: "http://unicode-rs.github.io/"
+main_repo: "https://github.com/unicode-rs"
+primary_contact: "manishsmail@gmail.com"
+sanitizers:
+  - address
+fuzzing_engines:
+  - libfuzzer
+language: rust
+auto_ccs:
+  - "david@adalogics.com"
diff --git a/projects/unrar/project.yaml b/projects/unrar/project.yaml
index 242c91f..2fa4c87 100644
--- a/projects/unrar/project.yaml
+++ b/projects/unrar/project.yaml
@@ -5,6 +5,7 @@
   - "vakh@chromium.org"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/aawc/unrar.git'
+main_repo: 'https://github.com/aawc/unrar.git'
\ No newline at end of file
diff --git a/projects/upb/Dockerfile b/projects/upb/Dockerfile
index 7e157a1..c97eaf0 100644
--- a/projects/upb/Dockerfile
+++ b/projects/upb/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y cmake
+RUN apt-get update && apt-get install python -y
 RUN git clone --depth 1 https://github.com/protocolbuffers/upb.git upb
-WORKDIR $SRC
+WORKDIR upb
 COPY build.sh $SRC/
diff --git a/projects/upb/build.sh b/projects/upb/build.sh
index 3f5bebf..f937795 100755
--- a/projects/upb/build.sh
+++ b/projects/upb/build.sh
@@ -15,16 +15,4 @@
 #
 ################################################################################
 
-# build project
-cd upb/cmake
-cmake .
-make -j$(nproc)
-
-# use bazel to build instead ?
-$CC $CFLAGS -I. -I.. -o descriptor.upb.o -c google/protobuf/descriptor.upb.c
-$CXX $CXXFLAGS -DHAVE_FUZZER=1 -std=c++11 -I. -I.. -o fuzz_parsenew.o -c ../tests/file_descriptor_parsenew_fuzzer.cc
-$CXX $CXXFLAGS fuzz_parsenew.o descriptor.upb.o -o $OUT/fuzz_parsenew *.a $LIB_FUZZING_ENGINE
-
-# builds corpus
-cd ..
-find . -name "*.proto" | xargs zip -r $OUT/fuzz_parsenew_seed_corpus.zip
+bazel_build_fuzz_tests
diff --git a/projects/upb/project.yaml b/projects/upb/project.yaml
index b67152d..eb3c62e 100644
--- a/projects/upb/project.yaml
+++ b/projects/upb/project.yaml
@@ -1,8 +1,6 @@
 homepage: "https://github.com/protocolbuffers/upb"
 language: c++
 primary_contact: "haberman@google.com"
-auto_ccs :
-- "p.antoine@catenacyber.fr"
 
 sanitizers:
 - address
diff --git a/projects/uriparser/project.yaml b/projects/uriparser/project.yaml
index 9ca2573..ec64c64 100644
--- a/projects/uriparser/project.yaml
+++ b/projects/uriparser/project.yaml
@@ -3,9 +3,10 @@
 primary_contact: "webmaster@hartwork.org"
 sanitizers:
  - address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
  - undefined
 architectures:
   - x86_64
   - i386
-main_repo: 'https://github.com/uriparser/uriparser'
+main_repo: 'https://github.com/uriparser/uriparser'
\ No newline at end of file
diff --git a/projects/urllib3/Dockerfile b/projects/urllib3/Dockerfile
index 799b8b9..a6cf8d6 100644
--- a/projects/urllib3/Dockerfile
+++ b/projects/urllib3/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
 RUN git clone --depth 1 https://github.com/urllib3/urllib3
 
 COPY build.sh $SRC/
diff --git a/projects/urllib3/build.sh b/projects/urllib3/build.sh
index 66f6419..6eaf4d5 100644
--- a/projects/urllib3/build.sh
+++ b/projects/urllib3/build.sh
@@ -30,5 +30,5 @@
 LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \
 ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
 \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
-  chmod u+x $OUT/$fuzzer_basename
+  chmod +x $OUT/$fuzzer_basename
 done
diff --git a/projects/urllib3/fuzz_urlparse.py b/projects/urllib3/fuzz_urlparse.py
index f2fcd9b..81c0164 100644
--- a/projects/urllib3/fuzz_urlparse.py
+++ b/projects/urllib3/fuzz_urlparse.py
@@ -33,5 +33,6 @@
     atheris.Fuzz()
 
 if __name__ == "__main__":
+    atheris.instrument_all()
     main()
 
diff --git a/projects/usbguard/build.sh b/projects/usbguard/build.sh
index 5c7daf6..1504da8 100644
--- a/projects/usbguard/build.sh
+++ b/projects/usbguard/build.sh
@@ -81,3 +81,10 @@
   cp -R "$SRC/usbguard/src/Tests/USB/data" "${corpus_dir}"
   zip -r "${zip_name}" "${corpus_dir}"
 fi
+
+# Ubuntu 20.04 doesn't have a static libqb.
+mkdir -p $OUT/lib
+cp /lib/x86_64-linux-gnu/libqb* $OUT/lib
+patchelf --set-rpath '$ORIGIN/lib' $OUT/fuzzer-uevent
+patchelf --set-rpath '$ORIGIN/lib' $OUT/fuzzer-usb-descriptor
+patchelf --set-rpath '$ORIGIN/lib' $OUT/fuzzer-rules
diff --git a/projects/usbguard/project.yaml b/projects/usbguard/project.yaml
index a372cd3..a220a65 100644
--- a/projects/usbguard/project.yaml
+++ b/projects/usbguard/project.yaml
@@ -4,7 +4,8 @@
 sanitizers:
  - address
  - undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
 auto_ccs:
  - "alakatos@redhat.com"
  - "allenwebb@google.com"
diff --git a/projects/usrsctp/project.yaml b/projects/usrsctp/project.yaml
index 54fb494..b2c310c 100644
--- a/projects/usrsctp/project.yaml
+++ b/projects/usrsctp/project.yaml
@@ -5,12 +5,12 @@
   - "t00fcxen@googlemail.com"
   - "markwo@google.com"
   - "natashenka@google.com"
-  - "yuquanw@google.com"
+  - "orphis@google.com"
+  - "mbonadei@google.com"
 fuzzing_engines:
   - libfuzzer
   - afl
   - honggfuzz
-  - dataflow
 sanitizers:
   - address
   - undefined
diff --git a/projects/uwebsockets/project.yaml b/projects/uwebsockets/project.yaml
index e46ea9a..47536fa 100644
--- a/projects/uwebsockets/project.yaml
+++ b/projects/uwebsockets/project.yaml
@@ -4,6 +4,7 @@
 builds_per_day: 4
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/uNetworking/uWebSockets.git'
+main_repo: 'https://github.com/uNetworking/uWebSockets.git'
\ No newline at end of file
diff --git a/projects/varnish/Dockerfile b/projects/varnish/Dockerfile
new file mode 100644
index 0000000..5fd0fb4
--- /dev/null
+++ b/projects/varnish/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt install -y automake autoconf libtool pkg-config python3-docutils python3-sphinx libedit-dev libpcre2-dev libncurses-dev
+RUN git clone --depth 1 https://github.com/varnishcache/varnish-cache
+COPY build.sh $SRC
+WORKDIR $SRC/varnish-cache
diff --git a/projects/varnish/build.sh b/projects/varnish/build.sh
new file mode 100755
index 0000000..3a7f248
--- /dev/null
+++ b/projects/varnish/build.sh
@@ -0,0 +1,27 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+
+# build project
+./autogen.sh
+./configure --enable-oss-fuzz PCRE2_LIBS=-l:libpcre2-8.a
+make -j2 -C include/
+make -j2 -C lib/libvarnish/
+make -j2 -C lib/libvgz/
+make -j2 -C lib/libvsc/
+make -j2 -C bin/varnishd/ esi_parse_fuzzer
+cp bin/varnishd/*_fuzzer $OUT/
diff --git a/projects/varnish/project.yaml b/projects/varnish/project.yaml
index 8361790..d251355 100644
--- a/projects/varnish/project.yaml
+++ b/projects/varnish/project.yaml
@@ -1,7 +1,8 @@
 homepage: "https://varnish-cache.org/"
-primary_contact: "federico.schwindt@gmail.com"
+language: c
+primary_contact: "phk@varnish.org"
 auto_ccs:
-  - "phk@varnish.org"
-sanitizers:
-  - address
-  - undefined
+  - "bsdphk@gmail.com"
+  - "nils.goroll@uplex.de"
+  - "martin@varnish-software.com"
+main_repo: 'https://github.com/varnishcache/varnish-cache'
diff --git a/projects/vitess/Dockerfile b/projects/vitess/Dockerfile
index 8f066c8..9eda356 100644
--- a/projects/vitess/Dockerfile
+++ b/projects/vitess/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/vitessio/vitess
 COPY build.sh $SRC/
 WORKDIR $SRC/vitess
diff --git a/projects/vlc/Dockerfile b/projects/vlc/Dockerfile
new file mode 100644
index 0000000..6d24f02
--- /dev/null
+++ b/projects/vlc/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make autoconf automake libtool \
+  pkg-config cmake flex bison gettext libglu1-mesa-dev 
+RUN git clone --depth 1 https://github.com/videolan/vlc vlc
+WORKDIR vlc
+COPY build.sh $SRC/
diff --git a/projects/vlc/build.sh b/projects/vlc/build.sh
new file mode 100755
index 0000000..8eb7053
--- /dev/null
+++ b/projects/vlc/build.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+# Use OSS-Fuzz environment rather than hardcoded setup.
+sed -i 's/-fsanitize-coverage=trace-pc-guard//g' ./configure.ac
+sed -i 's/-fsanitize-coverage=trace-cmp//g' ./configure.ac
+sed -i 's/-fsanitize-coverage=trace-pc//g' ./configure.ac
+sed -i 's/-lFuzzer//g'  ./configure.ac
+
+# In order to build statically we avoid libxml and ogg plugins.
+sed -i 's/..\/..\/lib\/libvlc_internal.h/lib\/libvlc_internal.h/g' ./test/src/input/decoder.c
+sed -i 's/..\/modules\/libxml_plugin.la//g' ./test/Makefile.am
+sed -i 's/..\/modules\/libogg_plugin.la//g' ./test/Makefile.am
+sed -i 's/f(misc_xml_xml)//g' ./test/src/input/demux-run.c
+sed -i 's/f(demux_ogg)//g' ./test/src/input/demux-run.c
+
+# Ensure that we compile with the correct link flags.
+RULE="vlc_demux_libfuzzer_LDADD"
+FUZZ_LDFLAGS="vlc_demux_libfuzzer_LDFLAGS=\${LIB_FUZZING_ENGINE}"
+sed -i "s/${RULE}/${FUZZ_LDFLAGS}\n${RULE}/g" ./test/Makefile.am
+
+RULE="vlc_demux_dec_libfuzzer_LDADD"
+FUZZ_LDFLAGS="vlc_demux_dec_libfuzzer_LDFLAGS=\${LIB_FUZZING_ENGINE}"
+sed -i "s/${RULE}/${FUZZ_LDFLAGS}\n${RULE}/g" ./test/Makefile.am
+
+./bootstrap
+./configure --disable-ogg --disable-oggspots --disable-libxml2 --disable-lua \
+            --disable-shared \
+            --enable-static \
+            --enable-vlc=no \
+            --disable-avcodec \
+            --disable-swscale \
+            --disable-a52 \
+            --disable-xcb \
+            --disable-alsa \
+            --with-libfuzzer
+make V=1 -j$(nproc)
+cp ./test/vlc-demux-dec-libfuzzer $OUT/
+cp ./test/vlc-demux-libfuzzer $OUT/
diff --git a/projects/vlc/project.yaml b/projects/vlc/project.yaml
new file mode 100644
index 0000000..1006c84
--- /dev/null
+++ b/projects/vlc/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/videolan/vlc"
+language: c
+primary_contact: "ossfuzz@videolan.org"
+auto_ccs:
+  - "adam@adalogics.com"
+  - "david@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+main_repo: 'https://github.com/videolan/vlc'
diff --git a/projects/wasm3/Dockerfile b/projects/wasm3/Dockerfile
new file mode 100644
index 0000000..1d123ad
--- /dev/null
+++ b/projects/wasm3/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make
+RUN git clone --depth 1 https://github.com/wasm3/wasm3
+WORKDIR wasm3
+COPY build.sh $SRC/
diff --git a/projects/wasm3/build.sh b/projects/wasm3/build.sh
new file mode 100755
index 0000000..1ef87c0
--- /dev/null
+++ b/projects/wasm3/build.sh
@@ -0,0 +1,21 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+mkdir build && cd build
+cmake -DBUILD_WASI=none ..
+make -j$(nproc)
+$CC $CFLAGS -c $SRC/wasm3/platforms/app_fuzz/fuzzer.c -o fuzzer.o -I/src/wasm3/source
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzzer fuzzer.o /src/wasm3/build/source/libm3.a
diff --git a/projects/wasm3/project.yaml b/projects/wasm3/project.yaml
new file mode 100644
index 0000000..41c18ca
--- /dev/null
+++ b/projects/wasm3/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://github.com/wasm3/wasm3"
+main_repo: "https://github.com/wasm3/wasm3"
+language: c
+primary_contact: "vshymanskyi@gmail.com"
+auto_ccs:
+  - "Adam@adalogics.com"
+sanitizers:
+  - address
+  - undefined
+  - memory
+fuzzing_engines:
+  - libfuzzer
+  - afl
+  - honggfuzz
diff --git a/projects/wasmtime/Dockerfile b/projects/wasmtime/Dockerfile
index e310b36..fe6c8dd 100644
--- a/projects/wasmtime/Dockerfile
+++ b/projects/wasmtime/Dockerfile
@@ -14,9 +14,15 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
 RUN apt-get update && apt-get install -y make autoconf automake libtool curl cmake python llvm-dev libclang-dev clang
 
+# Install a newer version of OCaml than provided by Ubuntu 16.04 (base version for this image)
+RUN curl -sL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh -o install.sh && \
+  echo | sh install.sh && \
+  opam init --disable-sandboxing --yes && \
+  opam install ocamlbuild --yes
+
 RUN git clone --depth 1 https://github.com/bytecodealliance/wasm-tools wasm-tools
 
 RUN git clone --depth 1 https://github.com/bytecodealliance/regalloc.rs regalloc.rs
diff --git a/projects/wasmtime/build.sh b/projects/wasmtime/build.sh
index 80423e3..b22a11b 100755
--- a/projects/wasmtime/build.sh
+++ b/projects/wasmtime/build.sh
@@ -56,6 +56,9 @@
   done
 }
 
+# Ensure OCaml environment is set up prior to Wasmtime build.
+eval $(opam env)
+
 # Build with peepmatic in order to enable the related fuzz targets.
 build wasmtime "" "" --features "peepmatic-fuzzing experimental_x64"
 
diff --git a/projects/wavpack/Dockerfile b/projects/wavpack/Dockerfile
index 2cee9fd..8c5a96a 100644
--- a/projects/wavpack/Dockerfile
+++ b/projects/wavpack/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool
+RUN apt-get update && apt-get install -y make autoconf automake libtool gettext
 RUN git clone --depth 1 https://github.com/dbry/WavPack.git wavpack
 RUN cp wavpack/fuzzing/build.sh $SRC
 WORKDIR wavpack
diff --git a/projects/wazuh/Dockerfile b/projects/wazuh/Dockerfile
new file mode 100755
index 0000000..cf23165
--- /dev/null
+++ b/projects/wazuh/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y libpcre2-dev libssl-dev libsystemd-dev autoconf libtool
+RUN git clone https://github.com/wazuh/wazuh
+
+WORKDIR $SRC/wazuh
+COPY build.sh $SRC/
+COPY fuzz_xml.c $SRC/fuzz_xml.c
diff --git a/projects/wazuh/build.sh b/projects/wazuh/build.sh
new file mode 100755
index 0000000..984da47
--- /dev/null
+++ b/projects/wazuh/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+cd src
+export LDFLAGS="$CFLAGS"
+
+make deps
+make TARGET=local
+$CC $CFLAGS $LIB_FUZZING_ENGINE $SRC/fuzz_xml.c -o $OUT/fuzz_xml -I./ -I./os_xml \
+    ./libwazuh.a ./external/sqlite/libsqlite3.a ./external/cJSON/libcjson.a \
+    ./external/zlib/libz.a ./external/bzip2/libbz2.a
diff --git a/projects/wazuh/fuzz_xml.c b/projects/wazuh/fuzz_xml.c
new file mode 100644
index 0000000..c889bcc
--- /dev/null
+++ b/projects/wazuh/fuzz_xml.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "./os_xml/os_xml.h"
+#include "./os_xml/os_xml_internal.h"
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+    char filename[256];
+    sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+
+    FILE *fp = fopen(filename, "wb");
+    if (!fp)
+        return 0;
+    fwrite(data, size, 1, fp);
+    fclose(fp);
+
+    OS_XML xml;
+    if (OS_ReadXML(filename, &xml) < 0) {
+        unlink(filename);
+        return 0;
+    }
+    XML_NODE node = NULL;
+    node = OS_GetElementsbyNode(&xml, NULL);
+    if (node == NULL) {
+        OS_ClearXML(&xml);
+        return 0;
+    }
+    int i = 0;
+
+    while (node[i]) {
+        int j = 0;
+        XML_NODE cnode;
+        cnode = OS_GetElementsbyNode(&xml, node[i]);
+        if (cnode == NULL) {
+            i++;
+            continue;
+        }
+
+        while (cnode[j]) {
+            if (cnode[j]->attributes && cnode[j]->values) {
+                int k = 0;
+                while (cnode[j]->attributes[k]) {
+                    k++;
+                }
+            }
+            j++;
+        }
+
+        OS_ClearNode(cnode);
+        i++;
+    }
+
+    OS_ClearNode(node);
+    OS_ClearXML(&xml);
+    unlink(filename);
+    return 0;
+}
+
diff --git a/projects/wazuh/fuzz_xml.options b/projects/wazuh/fuzz_xml.options
new file mode 100644
index 0000000..f9d0965
--- /dev/null
+++ b/projects/wazuh/fuzz_xml.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+detect_leaks=0
diff --git a/projects/wazuh/project.yaml b/projects/wazuh/project.yaml
new file mode 100755
index 0000000..04d791d
--- /dev/null
+++ b/projects/wazuh/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://wazuh.com/"
+main_repo: 'https://github.com/wazuh/wazuh'
+primary_contact: "devel@wazuh.com"
+language: c
+auto_ccs:
+  - "david@adalogics.com"
diff --git a/projects/wget/Dockerfile b/projects/wget/Dockerfile
index ec20c7c..2382da6 100644
--- a/projects/wget/Dockerfile
+++ b/projects/wget/Dockerfile
@@ -22,6 +22,7 @@
  autogen \
  autopoint \
  autoconf \
+ autoconf-archive \
  automake \
  libtool \
  texinfo \
diff --git a/projects/wget/build.sh b/projects/wget/build.sh
index 840977d..b525801 100755
--- a/projects/wget/build.sh
+++ b/projects/wget/build.sh
@@ -16,7 +16,7 @@
 ################################################################################
 
 export WGET_DEPS_PATH=$SRC/wget_deps
-export PKG_CONFIG_PATH=$WGET_DEPS_PATH/lib/pkgconfig
+export PKG_CONFIG_PATH=$WGET_DEPS_PATH/lib64/pkgconfig:$WGET_DEPS_PATH/lib/pkgconfig
 export CPPFLAGS="-I$WGET_DEPS_PATH/include"
 export LDFLAGS="-L$WGET_DEPS_PATH/lib"
 export GNULIB_SRCDIR=$SRC/gnulib
@@ -76,19 +76,31 @@
 # avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite)
 export ASAN_OPTIONS=detect_leaks=0
 
+# Ensure our libraries can be found
+ln -s $WGET_DEPS_PATH/lib64/libhogweed.a $WGET_DEPS_PATH/lib/libhogweed.a
+ln -s $WGET_DEPS_PATH/lib64/libnettle.a  $WGET_DEPS_PATH/lib/libnettle.a
+
 cd $SRC/wget
 ./bootstrap
+autoreconf -fi
+
+export CFLAGS="$CFLAGS -I$WGET_DEPS_PATH/include"
+export CXXFLAGS="$CXXFLAGS -I$WGET_DEPS_PATH/include"
 
 # build and run non-networking tests
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
-  ./configure -C
+GNUTLS_CFLAGS="-lgnutls" \
+GNUTLS_LIBS="-lgnutls" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
+./configure -C
 make clean
 make -j$(nproc)
 make -j$(nproc) -C fuzz check
 
 # build for fuzzing
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
-  ./configure --enable-fuzzing -C
+GNUTLS_CFLAGS="-lgnutls" \
+GNUTLS_LIBS="-lgnutls" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
+./configure --enable-fuzzing -C
 make clean
 make -j$(nproc) -C lib
 make -j$(nproc) -C src
diff --git a/projects/wget2/Dockerfile b/projects/wget2/Dockerfile
index bc2451e..8513d58 100644
--- a/projects/wget2/Dockerfile
+++ b/projects/wget2/Dockerfile
@@ -34,7 +34,8 @@
  wget \
  python \
  lzip \
- rsync
+ rsync \
+ libmicrohttpd-dev
 
 ENV GNULIB_TOOL $SRC/gnulib/gnulib-tool
 RUN git clone git://git.savannah.gnu.org/gnulib.git
diff --git a/projects/wget2/build.sh b/projects/wget2/build.sh
index 3ad4e04..866a425 100755
--- a/projects/wget2/build.sh
+++ b/projects/wget2/build.sh
@@ -16,7 +16,7 @@
 ################################################################################
 
 export WGET2_DEPS_PATH=$SRC/wget2_deps
-export PKG_CONFIG_PATH=$WGET2_DEPS_PATH/lib/pkgconfig
+export PKG_CONFIG_PATH=$WGET2_DEPS_PATH/lib64/pkgconfig:$WGET2_DEPS_PATH/lib/pkgconfig
 export CPPFLAGS="-I$WGET2_DEPS_PATH/include"
 export LDFLAGS="-L$WGET2_DEPS_PATH/lib"
 export GNULIB_SRCDIR=$SRC/gnulib
@@ -72,29 +72,20 @@
 make -j$(nproc)
 make install
 
-cd $SRC/libmicrohttpd-*
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
-./configure --prefix=$WGET2_DEPS_PATH --disable-doc --disable-examples --disable-shared --enable-static
-make -j$(nproc)
-make install
-
-
 # avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite)
 export ASAN_OPTIONS=detect_leaks=0
 
 cd $SRC/wget2
 ./bootstrap
 
-# build and run non-networking tests
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
   ./configure -C --enable-static --disable-shared --disable-doc --without-plugin-support
 make clean
 make -j$(nproc)
 make -j$(nproc) -C unit-tests check
 make -j$(nproc) -C fuzz check
 
-# build for fuzzing
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
   ./configure -C --enable-fuzzing --enable-static --disable-shared --disable-doc --without-plugin-support
 make clean
 make -j$(nproc) -C lib
@@ -102,8 +93,13 @@
 make -j$(nproc) -C libwget
 make -j$(nproc) -C src
 
+# Ensure our libraries can be found
+ln -s $WGET2_DEPS_PATH/lib64/libhogweed.a $WGET2_DEPS_PATH/lib/libhogweed.a
+ln -s $WGET2_DEPS_PATH/lib64/libnettle.a  $WGET2_DEPS_PATH/lib/libnettle.a
+
 # build fuzzers
 cd fuzz
+
 CXXFLAGS="$CXXFLAGS -L$WGET2_DEPS_PATH/lib/" make oss-fuzz
 
 find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';'
diff --git a/projects/wolfssl/Dockerfile b/projects/wolfssl/Dockerfile
index 963f5e0..83cbdf4 100644
--- a/projects/wolfssl/Dockerfile
+++ b/projects/wolfssl/Dockerfile
@@ -24,9 +24,29 @@
 RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
 RUN git clone --depth 1 https://github.com/randombit/botan.git
 RUN git clone --depth 1 https://github.com/google/wycheproof.git
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
 RUN git clone https://github.com/wolfssl/oss-fuzz-targets --depth 1 $SRC/fuzz-targets
 
+# Retrieve corpora from other projects
+RUN wget https://storage.googleapis.com/pub/gsutil.tar.gz -O $SRC/gsutil.tar.gz
+RUN tar zxf $SRC/gsutil.tar.gz
+ENV PATH="${PATH}:$SRC/gsutil"
+RUN gsutil cp gs://bearssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/bearssl_cryptofuzz-bearssl/public.zip $SRC/corpus_bearssl.zip
+RUN gsutil cp gs://nettle-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/nettle_cryptofuzz-nettle-with-mini-gmp/public.zip $SRC/corpus_nettle.zip
+RUN gsutil cp gs://libecc-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/libecc_cryptofuzz-libecc/public.zip $SRC/corpus_libecc.zip
+RUN gsutil cp gs://relic-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/relic_cryptofuzz-relic/public.zip $SRC/corpus_relic.zip
+RUN gsutil cp gs://cryptofuzz-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/cryptofuzz_cryptofuzz-openssl/public.zip $SRC/corpus_cryptofuzz.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-sp-math-all/public.zip $SRC/corpus_wolfssl_sp-math-all.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-sp-math-all-8bit/public.zip $SRC/corpus_wolfssl_sp-math-all-8bit.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-sp-math/public.zip $SRC/corpus_wolfssl_sp-math.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-disable-fastmath/public.zip $SRC/corpus_wolfssl_disable-fastmath.zip
+
+# Botan corpora, which require a special import procedure
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_p256/public.zip $SRC/corpus_botan_ecc_p256.zip
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_p384/public.zip $SRC/corpus_botan_ecc_p384.zip
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_p521/public.zip $SRC/corpus_botan_ecc_p521.zip
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_bp256/public.zip $SRC/corpus_botan_ecc_bp256.zip
+
 WORKDIR wolfssl
 
 COPY build.sh $SRC/
diff --git a/projects/wolfssl/build.sh b/projects/wolfssl/build.sh
index 70db453..2e6e5c6 100755
--- a/projects/wolfssl/build.sh
+++ b/projects/wolfssl/build.sh
@@ -17,7 +17,7 @@
 
 if [[ $CFLAGS != *sanitize=dataflow* ]]
 then
-    WOLFCRYPT_CONFIGURE_PARAMS="--enable-static --enable-md2 --enable-md4 --enable-ripemd --enable-blake2 --enable-blake2s --enable-pwdbased --enable-scrypt --enable-hkdf --enable-cmac --enable-arc4 --enable-camellia --enable-rabbit --enable-aesccm --enable-aesctr --enable-hc128 --enable-xts --enable-des3 --enable-idea --enable-x963kdf --enable-harden --enable-aescfb --enable-aesofb --enable-aeskeywrap --enable-keygen --enable-curve25519 --enable-curve448 --enable-shake256 --disable-crypttests --disable-examples --enable-compkey --enable-ed448 --enable-ed25519 --enable-ecccustcurves --enable-xchacha --enable-cryptocb --enable-eccencrypt --enable-smallstack"
+    WOLFCRYPT_CONFIGURE_PARAMS="--enable-static --enable-md2 --enable-md4 --enable-ripemd --enable-blake2 --enable-blake2s --enable-pwdbased --enable-scrypt --enable-hkdf --enable-cmac --enable-arc4 --enable-camellia --enable-rabbit --enable-aesccm --enable-aesctr --enable-hc128 --enable-xts --enable-des3 --enable-idea --enable-x963kdf --enable-harden --enable-aescfb --enable-aesofb --enable-aeskeywrap --enable-keygen --enable-curve25519 --enable-curve448 --enable-shake256 --disable-crypttests --disable-examples --enable-compkey --enable-ed448 --enable-ed25519 --enable-ecccustcurves --enable-xchacha --enable-cryptocb --enable-eccencrypt --enable-aesgcm-stream --enable-smallstack --enable-ed25519-stream --enable-ed448-stream"
     if [[ $CFLAGS = *sanitize=memory* ]]
     then
         WOLFCRYPT_CONFIGURE_PARAMS="$WOLFCRYPT_CONFIGURE_PARAMS --disable-asm"
@@ -31,10 +31,14 @@
     CFLAGS="" CXXFLAGS="" ./b2 headers
     cp -R boost/ /usr/include/
 
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
+
     OLD_CFLAGS="$CFLAGS"
     OLD_CXXFLAGS="$CXXFLAGS"
 
     # Configure Cryptofuzz
+    cd $SRC/cryptofuzz
+    sed -i 's/kNegativeIntegers = false/kNegativeIntegers = true/g' config.h
     cp -R $SRC/cryptofuzz/ $SRC/cryptofuzz-openssl-api/
     cd $SRC/cryptofuzz-openssl-api/
     python gen_repository.py
@@ -75,11 +79,23 @@
     echo -n '"' >>extra_options.h
     echo -n '--force-module=wolfCrypt ' >>extra_options.h
     echo -n '--digests=NULL ' >>extra_options.h
-    echo -n '--operations=BignumCalc,DH_GenerateKeyPair,DH_Derive,ECC_GenerateKeyPair,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Verify,ECDSA_Sign' >>extra_options.h
+    echo -n '--operations=' >>extra_options.h
+    echo -n 'BignumCalc,' >>extra_options.h
+    echo -n 'DH_GenerateKeyPair,' >>extra_options.h
+    echo -n 'DH_Derive,' >>extra_options.h
+    echo -n 'ECC_GenerateKeyPair,' >>extra_options.h
+    echo -n 'ECC_PrivateToPublic,' >>extra_options.h
+    echo -n 'ECC_ValidatePubkey,' >>extra_options.h
+    echo -n 'ECDSA_Verify,' >>extra_options.h
+    echo -n 'ECDSA_Sign,' >>extra_options.h
+    echo -n 'ECIES_Encrypt,' >>extra_options.h
+    echo -n 'ECIES_Decrypt,' >>extra_options.h
+    echo -n 'ECC_Point_Add,' >>extra_options.h
+    echo -n 'ECC_Point_Mul,' >>extra_options.h
+    echo -n 'ECDH_Derive ' >>extra_options.h
     echo -n '"' >>extra_options.h
 
     # Build Botan
-    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
     cd $SRC/botan
     if [[ $CFLAGS != *-m32* ]]
     then
@@ -91,12 +107,44 @@
     export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a"
     export BOTAN_INCLUDE_PATH="$SRC/botan/build/include"
 
+    # Build normal math fuzzer
+    cp -R $SRC/cryptofuzz/ $SRC/cryptofuzz-normal-math/
+    cp -R $SRC/wolfssl/ $SRC/wolfssl-normal-math/
+    cd $SRC/wolfssl-normal-math/
+    autoreconf -ivf
+    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP"
+    if [[ $CFLAGS != *-m32* ]]
+    then
+        ./configure $WOLFCRYPT_CONFIGURE_PARAMS
+    else
+        # Compiling instrumented 32 bit normal math with asm is currently
+        # not possible because it results in Clang error messages such as:
+        #
+        # wolfcrypt/src/tfm.c:3154:11: error: inline assembly requires more registers than available
+        ./configure $WOLFCRYPT_CONFIGURE_PARAMS --disable-asm
+    fi
+    make -j$(nproc)
+    export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_WOLFCRYPT -DCRYPTOFUZZ_BOTAN"
+    export WOLFCRYPT_LIBWOLFSSL_A_PATH="$SRC/wolfssl-normal-math/src/.libs/libwolfssl.a"
+    export WOLFCRYPT_INCLUDE_PATH="$SRC/wolfssl-normal-math/"
+    cd $SRC/cryptofuzz-normal-math/modules/wolfcrypt
+    make -j$(nproc)
+    cd $SRC/cryptofuzz-normal-math/modules/botan
+    make -j$(nproc)
+    cd $SRC/cryptofuzz-normal-math/
+    LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make -B -j$(nproc)
+    cp cryptofuzz $OUT/cryptofuzz-normal-math
+    CFLAGS="$OLD_CFLAGS"
+    CXXFLAGS="$OLD_CXXFLAGS"
+    unset WOLFCRYPT_LIBWOLFSSL_A_PATH
+    unset WOLFCRYPT_INCLUDE_PATH
+
     # Build sp-math-all fuzzer
     cp -R $SRC/cryptofuzz/ $SRC/cryptofuzz-sp-math-all/
     cp -R $SRC/wolfssl/ $SRC/wolfssl-sp-math-all/
     cd $SRC/wolfssl-sp-math-all/
     autoreconf -ivf
-    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP"
+    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP -DWOLFSSL_SP_INT_NEGATIVE"
     ./configure $WOLFCRYPT_CONFIGURE_PARAMS --enable-sp-math-all
     make -j$(nproc)
     export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_WOLFCRYPT -DCRYPTOFUZZ_BOTAN"
@@ -119,7 +167,7 @@
     cp -R $SRC/wolfssl/ $SRC/wolfssl-sp-math-all-8bit/
     cd $SRC/wolfssl-sp-math-all-8bit/
     autoreconf -ivf
-    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP -DSP_WORD_SIZE=8"
+    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP -DSP_WORD_SIZE=8 -DWOLFSSL_SP_INT_NEGATIVE"
     ./configure $WOLFCRYPT_CONFIGURE_PARAMS --enable-sp-math-all
     make -j$(nproc)
     export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_WOLFCRYPT -DCRYPTOFUZZ_BOTAN"
@@ -143,7 +191,7 @@
     cd $SRC/wolfssl-sp-math/
     autoreconf -ivf
     # -DHAVE_ECC_BRAINPOOL and -DHAVE_ECC_KOBLITZ are lacking from the CFLAGS; these are not supported by SP math
-    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP"
+    CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP -DWOLFSSL_PUBLIC_ECC_ADD_DBL"
     # SP math does not support custom curves, so remove that flag
     export WOLFCRYPT_CONFIGURE_PARAMS_SP_MATH=${WOLFCRYPT_CONFIGURE_PARAMS//"--enable-ecccustcurves"/}
     ./configure $WOLFCRYPT_CONFIGURE_PARAMS_SP_MATH --enable-sp --enable-sp-math
@@ -186,16 +234,57 @@
     unset WOLFCRYPT_LIBWOLFSSL_A_PATH
     unset WOLFCRYPT_INCLUDE_PATH
 
+    mkdir $SRC/cryptofuzz-seed-corpus/
+
     # Convert Wycheproof test vectors to Cryptofuzz corpus format
-    mkdir $SRC/corpus-cryptofuzz-wycheproof/
-    find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_*' -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-wycheproof={},$SRC/corpus-cryptofuzz-wycheproof/ \;
+    find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_*' -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-wycheproof={},$SRC/cryptofuzz-seed-corpus/ \;
+
+    # Unpack corpora from other projects
+    unzip -n $SRC/corpus_bearssl.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_nettle.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_libecc.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_relic.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_cryptofuzz.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_wolfssl_sp-math-all.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_wolfssl_sp-math-all-8bit.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_wolfssl_sp-math.zip -d $SRC/cryptofuzz_seed_corpus/
+    unzip -n $SRC/corpus_wolfssl_disable-fastmath.zip -d $SRC/cryptofuzz_seed_corpus/
+
+    # Import Botan corpora
+    mkdir $SRC/botan-p256-corpus/
+    unzip $SRC/corpus_botan_ecc_p256.zip -d $SRC/botan-p256-corpus/
+    find $SRC/botan-p256-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,secp256r1 \;
+
+    mkdir $SRC/botan-p384-corpus/
+    unzip $SRC/corpus_botan_ecc_p384.zip -d $SRC/botan-p384-corpus/
+    find $SRC/botan-p384-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,secp384r1 \;
+
+    mkdir $SRC/botan-p521-corpus/
+    unzip $SRC/corpus_botan_ecc_p521.zip -d $SRC/botan-p521-corpus/
+    find $SRC/botan-p521-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,secp521r1 \;
+
+    mkdir $SRC/botan-bp256-corpus/
+    unzip $SRC/corpus_botan_ecc_bp256.zip -d $SRC/botan-bp256-corpus/
+    find $SRC/botan-bp256-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,brainpool256r1 \;
+
     # Pack it
-    zip -j $SRC/cryptofuzz_wycheproof_seed_corpus.zip $SRC/corpus-cryptofuzz-wycheproof/*
+    cd $SRC/cryptofuzz_seed_corpus
+    zip -r $SRC/cryptofuzz_seed_corpus.zip .
+
     # Use it as the seed corpus for each Cryptofuzz-based fuzzer
-    cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-sp-math-all_seed_corpus.zip
-    cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-sp-math-all-8bit_seed_corpus.zip
-    cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-sp-math_seed_corpus.zip
-    cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-disable-fastmath_seed_corpus.zip
+    cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-normal-math_seed_corpus.zip
+    cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-sp-math-all_seed_corpus.zip
+    cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-sp-math-all-8bit_seed_corpus.zip
+    cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-sp-math_seed_corpus.zip
+    cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-disable-fastmath_seed_corpus.zip
+
+    # Remove files that are no longer needed to prevent running out of disk space
+    rm -rf $SRC/botan-p256-corpus/
+    rm -rf $SRC/botan-p384-corpus/
+    rm -rf $SRC/botan-p521-corpus/
+    rm -rf $SRC/botan-bp256-corpus/
+    rm -rf $SRC/cryptofuzz_seed_corpus/
+    rm -rf $SRC/cryptofuzz_seed_corpus.zip
 
     # Build SSL/SSH fuzzers
     NEW_SRC=$SRC/wolf-ssl-ssh-fuzzers/oss-fuzz/projects/wolf-ssl-ssh/
diff --git a/projects/wolfssl/project.yaml b/projects/wolfssl/project.yaml
index a6a31a1..fdd186b 100644
--- a/projects/wolfssl/project.yaml
+++ b/projects/wolfssl/project.yaml
@@ -10,10 +10,11 @@
   - "levi@wolfssl.com"
   - "testing@wolfssl.com"
   - "dgarske80@gmail.com"
+  - "jeffelms.wolfssl@gmail.com"
+  - "douzzer@mega.nu"
   - "guidovranken@gmail.com"
 fuzzing_engines:
   - libfuzzer
-  - afl
   - honggfuzz
   - dataflow
 sanitizers:
diff --git a/projects/wuffs/build.sh b/projects/wuffs/build.sh
index b8d4f53..17c4fc8 100755
--- a/projects/wuffs/build.sh
+++ b/projects/wuffs/build.sh
@@ -19,14 +19,34 @@
 # Wuffs' generated C files are "drop-in libraries" a la
 # http://gpfault.net/posts/drop-in-libraries.txt.html
 
-for f in fuzz/c/std/*_fuzzer.c; do
-  # Extract the format name, such as "gzip", from the C file name,
-  # "fuzz/c/std/gzip_fuzzer.c".
-  b=$(basename $f _fuzzer.c)
+for f in fuzz/c/std/*_fuzzer.c*; do
+  # Extract the format name (such as "gzip", from the C or C++ file name,
+  # "fuzz/c/std/gzip_fuzzer.c") and make the "gzip_fuzzer" binary. First
+  # compile the (C or C++) Wuffs code...
+  extension="${f##*.}"
+  if [   "$extension" = "c" ]; then
+    echo "Building (C)   $f"
+    b=$(basename $f _fuzzer.c)
+    $CC  $CFLAGS   -c $f -o $WORK/${b}_fuzzer.o
+  elif [ "$extension" = "cc" ]; then
+    if [[ $LIB_FUZZING_ENGINE == *"DataFlow"* ]]; then
+      # Linking (below) with "--engine dataflow" works with the C fuzzers but
+      # not the C++ ones. With C++, we get errors like `undefined reference to
+      # `dfs$_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev'`
+      #
+      # This is possibly "DFsan instrumented dependencies"
+      # https://github.com/google/oss-fuzz/issues/3388
+      echo "Skipping (C++) $f"
+      continue
+    fi
+    echo "Building (C++) $f"
+    b=$(basename $f _fuzzer.cc)
+    $CXX $CXXFLAGS -c $f -o $WORK/${b}_fuzzer.o
+  else
+    continue
+  fi
 
-  # Make the "gzip_fuzzer" binary. First compile the (C) Wuffs code, then link
-  # the (C++) fuzzing library.
-  $CC $CFLAGS -c $f -o $WORK/${b}_fuzzer.o
+  # ...then link the (C++) fuzzing library.
   $CXX $CXXFLAGS $WORK/${b}_fuzzer.o -o $OUT/${b}_fuzzer $LIB_FUZZING_ENGINE
 
   # Make the optional "gzip_fuzzer_seed_corpus.zip" archive. This means
diff --git a/projects/xmlsec/Dockerfile b/projects/xmlsec/Dockerfile
index 75814fc..013c530 100644
--- a/projects/xmlsec/Dockerfile
+++ b/projects/xmlsec/Dockerfile
@@ -16,7 +16,7 @@
 
 FROM gcr.io/oss-fuzz-base/base-builder
 RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config \
-    libssl-dev libxslt-dev wget liblzma-dev
+    libssl-dev wget liblzma-dev python-dev python3-dev
 
 RUN git clone --depth 1 https://github.com/lsh123/xmlsec
 RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
diff --git a/projects/xmlsec/build.sh b/projects/xmlsec/build.sh
index b2976c3..bb601a7 100755
--- a/projects/xmlsec/build.sh
+++ b/projects/xmlsec/build.sh
@@ -28,7 +28,7 @@
 make install
 
 cd $SRC/libxslt
-./autogen.sh --prefix="$XMLSEC_DEPS_PATH"
+./autogen.sh --prefix="$XMLSEC_DEPS_PATH" --with-libxml-src=${SRC}/libxml2
 make -j$(nproc)
 make install
 
@@ -40,7 +40,8 @@
 
 for file in $SRC/xmlsec/tests/oss-fuzz/*_target.c; do
     b=$(basename $file _target.c)
-    $CC $CFLAGS -c $file -I /usr/include/libxml2 -I ./include/ \
+    echo -e "#include <stdint.h>\n$(cat $file)" > $file
+    $CC $CFLAGS -c $file -I${XMLSEC_DEPS_PATH=}/include/libxml2 -I${XMLSEC_DEPS_PATH=}/include/ -I ./include/ \
     -o $OUT/${b}_target.o
     $CXX $CXXFLAGS $OUT/${b}_target.o ./src/.libs/libxmlsec1.a \
     ./src/openssl/.libs/libxmlsec1-openssl.a $LIB_FUZZING_ENGINE \
diff --git a/projects/xnu/Dockerfile b/projects/xnu/Dockerfile
new file mode 100644
index 0000000..ab69648
--- /dev/null
+++ b/projects/xnu/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  automake \
+  libtool \
+  ninja-build
+
+# Install Protobuf for C++ as the version in the base-builder repos may
+# be outdated.
+RUN curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.18.1/protobuf-cpp-3.18.1.tar.gz
+RUN tar xf protobuf-cpp-3.18.1.tar.gz
+WORKDIR $SRC/protobuf-3.18.1
+# Build statically
+RUN ./configure --disable-shared
+RUN make -j $(nproc)
+RUN make install
+
+WORKDIR $SRC
+RUN git clone --depth 1 https://github.com/googleprojectzero/SockFuzzer.git
+COPY build.sh $SRC
diff --git a/projects/xnu/build.sh b/projects/xnu/build.sh
new file mode 100755
index 0000000..715e32b
--- /dev/null
+++ b/projects/xnu/build.sh
@@ -0,0 +1,24 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+mkdir build
+cd build
+
+cmake -GNinja $SRC/SockFuzzer
+ninja
+
+cp $SRC/build/net_fuzzer $OUT
diff --git a/projects/xnu/project.yaml b/projects/xnu/project.yaml
new file mode 100644
index 0000000..e0d8831
--- /dev/null
+++ b/projects/xnu/project.yaml
@@ -0,0 +1,9 @@
+homepage: "https://opensource.apple.com/"
+language: "c"
+primary_contact: "nedwill@google.com"
+main_repo: "https://github.com/googleprojectzero/SockFuzzer"
+fuzzing_engines:
+  - libfuzzer
+  - honggfuzz
+sanitizers:
+  - address
diff --git a/projects/xpdf/Dockerfile b/projects/xpdf/Dockerfile
index a3090f0..5c43ae7 100755
--- a/projects/xpdf/Dockerfile
+++ b/projects/xpdf/Dockerfile
@@ -15,7 +15,7 @@
 ################################################################################
 
 FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make wget cmake libqt4-dev
+RUN apt-get update && apt-get install software-properties-common -y && apt-get update && apt-add-repository ppa:rock-core/qt4 && apt-get install -y make wget cmake libqt4-dev
 RUN wget --no-check-certificate https://dl.xpdfreader.com/xpdf-latest.tar.gz
 
 WORKDIR $SRC
diff --git a/projects/yajl-ruby/project.yaml b/projects/yajl-ruby/project.yaml
index d1da04d..11edfb9 100644
--- a/projects/yajl-ruby/project.yaml
+++ b/projects/yajl-ruby/project.yaml
@@ -5,12 +5,10 @@
   - libfuzzer
   - afl
   - honggfuzz
-  - dataflow
 sanitizers:
   - address
   - undefined
   - memory
-  - dataflow
 auto_ccs:
   - aaron.patterson@gmail.com
   - jonathan@titanous.com
diff --git a/projects/ygot/Dockerfile b/projects/ygot/Dockerfile
index b592c30..c8f0a41 100644
--- a/projects/ygot/Dockerfile
+++ b/projects/ygot/Dockerfile
@@ -14,7 +14,7 @@
 #
 ################################################################################
 
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
 RUN git clone --depth 1 https://github.com/openconfig/ygot
 
 COPY build.sh $SRC/
diff --git a/projects/zeek/build.sh b/projects/zeek/build.sh
index 996fe9c..bd6c570 100644
--- a/projects/zeek/build.sh
+++ b/projects/zeek/build.sh
@@ -20,12 +20,12 @@
                 --build-type=debug \
                 --generator=Ninja \
                 --enable-fuzzers \
+                --enable-mobile-ipv6 \
                 --disable-python \
                 --disable-zeekctl \
                 --disable-auxtools \
                 --disable-broker-tests
 
-
 cd build
 ninja install
 
diff --git a/projects/zeek/project.yaml b/projects/zeek/project.yaml
index b0239da..5d1b068 100644
--- a/projects/zeek/project.yaml
+++ b/projects/zeek/project.yaml
@@ -11,6 +11,9 @@
   - "vern@corelight.com"
   - "vlad@es.net"
   - "dominik.charousset@corelight.com"
+fuzzing_engines:
+  - libfuzzer
+  - honggfuzz
 sanitizers:
   - address
 main_repo: 'https://github.com/zeek/zeek'
diff --git a/projects/znc/Dockerfile b/projects/znc/Dockerfile
new file mode 100644
index 0000000..923e015
--- /dev/null
+++ b/projects/znc/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install -y make
+RUN git clone --depth 1 https://github.com/znc/znc
+WORKDIR $SRC/znc
+COPY build.sh msg_parse_fuzzer.cpp $SRC/
diff --git a/projects/znc/build.sh b/projects/znc/build.sh
new file mode 100755
index 0000000..7472ad8
--- /dev/null
+++ b/projects/znc/build.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -eu
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+git submodule update --init --recursive
+mkdir build && cd build
+cmake -DBUILD_SHARED_LIBS=OFF \
+	  -DWANT_ICU=OFF \
+	  -DWANT_OPENSSL=OFF \
+	  -DWANT_ZLIB=OFF \
+	  -DWANT_IPV6=OFF ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DGTEST_HAS_POSIX_RE=0 \
+	-I/src/znc/include -I/src/znc/build/include \
+	-fPIE -include znc/zncconfig.h -std=c++11 \
+	-c $SRC/msg_parse_fuzzer.cpp -o msg_parse_fuzzer.o
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+	msg_parse_fuzzer.o -o $OUT/msg_parse_fuzzer \
+	/src/znc/build/src/libznc.a 
diff --git a/projects/znc/msg_parse_fuzzer.cpp b/projects/znc/msg_parse_fuzzer.cpp
new file mode 100644
index 0000000..7338945
--- /dev/null
+++ b/projects/znc/msg_parse_fuzzer.cpp
@@ -0,0 +1,30 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+*/
+
+#include <stdint.h>
+#include <znc/Message.h>
+
+extern "C"
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+	std::string input(reinterpret_cast<const char*>(data), size);
+	CMessage msg;
+	msg.Parse(input);
+	msg.SetParam(1, input);
+	msg.GetParams();
+	return 0;
+}
diff --git a/projects/znc/project.yaml b/projects/znc/project.yaml
new file mode 100644
index 0000000..984e040
--- /dev/null
+++ b/projects/znc/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://znc.in"
+language: c++
+primary_contact: "alexey+znc@asokolov.org"
+auto_ccs:
+  - "Adam@adalogics.com"
+  - "ktonibud@gmail.com"
+sanitizers:
+  - address
+  - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
+main_repo: "https://github.com/znc/znc"
\ No newline at end of file
diff --git a/projects/zopfli/project.yaml b/projects/zopfli/project.yaml
index 33c9f31..ba175ad 100644
--- a/projects/zopfli/project.yaml
+++ b/projects/zopfli/project.yaml
@@ -3,6 +3,7 @@
 primary_contact: "lode@google.com"
 sanitizers:
   - address
-  - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+#  - memory
   - undefined
-main_repo: 'https://github.com/google/zopfli'
+main_repo: 'https://github.com/google/zopfli'
\ No newline at end of file
diff --git a/projects/zxing/Dockerfile b/projects/zxing/Dockerfile
new file mode 100644
index 0000000..389b7c0
--- /dev/null
+++ b/projects/zxing/Dockerfile
@@ -0,0 +1,29 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+
+RUN curl -L https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \
+    unzip maven.zip -d $SRC/maven && \
+    rm -rf maven.zip
+
+ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn
+
+RUN git clone --depth 1 https://github.com/zxing/zxing
+
+COPY build.sh $SRC/
+COPY MultiFormatDecodeFuzzer.java MultiFormatEncodeFuzzer.java $SRC/
+WORKDIR $SRC/zxing
diff --git a/projects/zxing/MultiFormatDecodeFuzzer.java b/projects/zxing/MultiFormatDecodeFuzzer.java
new file mode 100644
index 0000000..991428d
--- /dev/null
+++ b/projects/zxing/MultiFormatDecodeFuzzer.java
@@ -0,0 +1,56 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.BufferedImageLuminanceSource;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.ReaderException;
+import com.google.zxing.Result;
+import com.google.zxing.common.HybridBinarizer;
+
+import javax.imageio.ImageIO;
+import java.io.IOException;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+
+public final class MultiFormatDecodeFuzzer {
+    private static MultiFormatReader barcodeReader = new MultiFormatReader();
+
+    public static void fuzzerInitialize() {
+    }
+
+    public static void fuzzerTestOneInput(byte[] input) {
+        BufferedImage image;
+        try {
+            image = ImageIO.read(new ByteArrayInputStream(input));
+        } catch (IOException e) {
+            return;
+        }
+        if (image == null)
+            return;
+        if ((long) image.getHeight() * (long) image.getWidth() > 10000000)
+            return;
+
+        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
+        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+        try {
+            Result result = barcodeReader.decode(bitmap);
+            result.getText();
+            result.getResultMetadata();
+        } catch (ReaderException ignored) {
+        }
+    }
+}
diff --git a/projects/zxing/MultiFormatEncodeFuzzer.java b/projects/zxing/MultiFormatEncodeFuzzer.java
new file mode 100644
index 0000000..46a9e80
--- /dev/null
+++ b/projects/zxing/MultiFormatEncodeFuzzer.java
@@ -0,0 +1,187 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.aztec.encoder.AztecCode;
+import com.google.zxing.aztec.AztecReader;
+import com.google.zxing.datamatrix.DataMatrixReader;
+import com.google.zxing.maxicode.MaxiCodeReader;
+import com.google.zxing.oned.MultiFormatOneDReader;
+import com.google.zxing.pdf417.PDF417Reader;
+import com.google.zxing.qrcode.QRCodeReader;
+import com.google.zxing.oned.CodaBarReader;
+import com.google.zxing.oned.Code128Reader;
+import com.google.zxing.oned.Code39Reader;
+import com.google.zxing.oned.Code93Reader;
+import com.google.zxing.oned.EAN13Reader;
+import com.google.zxing.oned.EAN8Reader;
+import com.google.zxing.oned.ITFReader;
+import com.google.zxing.oned.UPCAReader;
+import com.google.zxing.oned.UPCEReader;
+import com.google.zxing.pdf417.PDF417Reader;
+import com.google.zxing.qrcode.QRCodeReader;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import javax.naming.NameNotFoundException;
+
+import com.google.zxing.Reader;
+import com.google.zxing.Binarizer;
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.WriterException;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.FormatException;
+import com.google.zxing.ChecksumException;
+import com.google.zxing.LuminanceSource;
+import com.google.zxing.Result;
+import com.google.zxing.pdf417.PDF417Writer;
+
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.google.zxing.qrcode.decoder.Mode;
+import com.google.zxing.qrcode.encoder.QRCode;
+
+import com.google.zxing.datamatrix.encoder.HighLevelEncoder;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+public final class MultiFormatEncodeFuzzer {
+
+    public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+        int width = data.consumeInt(100, 200);
+        int height = data.consumeInt(100, 200);
+        BarcodeFormat format = data.pickValue(BarcodeFormat.values());
+        String originalData = data.consumeRemainingAsAsciiString();
+
+        BitMatrix matrix;
+        try {
+            matrix = new MultiFormatWriter().encode(originalData, format, width, height);
+        } catch (WriterException | IllegalArgumentException e) {
+            return;
+        }
+
+        BinaryBitmap bitmap = null;
+        Result result;
+        try {
+            bitmap = new BinaryBitmap(new TrivialBinarizer(matrix));
+            result = getReader(format).decode(bitmap);
+        } catch (NotFoundException | ChecksumException | FormatException e) {
+            throw new IllegalStateException("Failed to recover\n" + originalData + "\nencoded with " + format + " in "
+                    + width + "x" + height + "\n\n" + matrix.toString() + "\n\n" + bitmap.toString(), e);
+        }
+        String decodedData = result.getText();
+        if (!decodedData.equals(originalData)) {
+            throw new IllegalStateException(
+                    "Failed to recover\n" + originalData + "\nencoded with " + format + " in " + width + "x" + height
+                            + ", got:\n" + decodedData + "\n\n" + matrix.toString() + "\n\n" + bitmap.toString());
+        }
+    }
+
+    private static Reader getReader(BarcodeFormat format) {
+        switch (format) {
+            case EAN_8:
+                return new EAN8Reader();
+            case UPC_E:
+                return new UPCEReader();
+            case EAN_13:
+                return new EAN13Reader();
+            case UPC_A:
+                return new UPCAReader();
+            case QR_CODE:
+                return new QRCodeReader();
+            case CODE_39:
+                return new Code39Reader();
+            case CODE_93:
+                return new Code93Reader();
+            case CODE_128:
+                return new Code128Reader();
+            case ITF:
+                return new ITFReader();
+            case PDF_417:
+                return new PDF417Reader();
+            case CODABAR:
+                return new CodaBarReader();
+            case DATA_MATRIX:
+                return new DataMatrixReader();
+            case AZTEC:
+                return new AztecReader();
+            default:
+                throw new IllegalArgumentException("No encoder available for format " + format);
+        }
+    }
+
+    private static final class TrivialBinarizer extends Binarizer {
+        private final BitMatrix matrix;
+
+        public TrivialBinarizer(BitMatrix matrix) {
+            super(new TrivialLuminanceSource(matrix));
+            this.matrix = matrix;
+        }
+
+        public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
+            return matrix.getRow(y, row);
+        }
+
+        public BitMatrix getBlackMatrix() throws NotFoundException {
+            return matrix;
+        }
+
+        public Binarizer createBinarizer(LuminanceSource source) {
+            return new TrivialBinarizer(matrix);
+        }
+    }
+
+    private static final class TrivialLuminanceSource extends LuminanceSource {
+        private final BitMatrix matrix;
+
+        public TrivialLuminanceSource(BitMatrix matrix) {
+            super(matrix.getWidth(), matrix.getHeight());
+            this.matrix = matrix;
+        }
+
+        public byte[] getRow(int y, byte[] row) {
+            if (row.length != matrix.getWidth()) {
+                row = new byte[matrix.getWidth()];
+            }
+            BitArray bitRow = matrix.getRow(y, null);
+            for (int i = 0; i < matrix.getWidth(); i++) {
+                if (bitRow.get(i)) {
+                    row[i] = 0;
+                } else {
+                    row[i] = (byte) 255;
+                }
+            }
+            return row;
+        }
+
+        public byte[] getMatrix() {
+            byte[] bytes = new byte[matrix.getWidth() * matrix.getHeight()];
+            for (int x = 0; x < matrix.getWidth(); x++) {
+                for (int y = 0; y < matrix.getHeight(); y++) {
+                    if (!matrix.get(x, y))
+                        bytes[x + y * matrix.getWidth()] = (byte) 255;
+                }
+            }
+            return bytes;
+        }
+    }
+}
diff --git a/projects/zxing/build.sh b/projects/zxing/build.sh
new file mode 100644
index 0000000..70f15c0
--- /dev/null
+++ b/projects/zxing/build.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -eu
+# Copyright 2021 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15"
+$MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS
+CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \
+ -Dexpression=project.version -q -DforceStdout)
+cp "core/target/core-$CURRENT_VERSION.jar" $OUT/zxing.jar
+
+mkdir -p $OUT/com/google/zxing
+cp core/target/test-classes/com/google/zxing/BufferedImageLuminanceSource.class $OUT/com/google/zxing
+
+ALL_JARS="zxing.jar"
+
+# The classpath at build-time includes the project jars in $OUT as well as the
+# Jazzer API. Additionally, include $OUT itself to pick up
+# BufferedImageLuminanceSource.
+BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH:$OUT
+
+# All .jar and .class files lie in the same directory as the fuzzer at runtime.
+RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
+
+for fuzzer in $(find $SRC -name '*Fuzzer.java'); do
+  fuzzer_basename=$(basename -s .java $fuzzer)
+  javac -cp $BUILD_CLASSPATH $fuzzer
+  cp $SRC/$fuzzer_basename*.class $OUT/
+
+  # Create an execution wrapper that executes Jazzer with the correct arguments.
+  echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m;-Djava.awt.headless=true\" \
+\$@" > $OUT/$fuzzer_basename
+  chmod u+x $OUT/$fuzzer_basename
+done
diff --git a/projects/zxing/project.yaml b/projects/zxing/project.yaml
new file mode 100644
index 0000000..ceab3c3
--- /dev/null
+++ b/projects/zxing/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/zxing/zxing"
+language: jvm
+primary_contact: "srowen@gmail.com"
+auto_ccs:
+  - "wagner@code-intelligence.com"
+  - "meumertzheim@code-intelligence.com"
+fuzzing_engines:
+  - libfuzzer
+main_repo: "https://github.com/zxing/zxing.git"
+sanitizers:
+  - address
diff --git a/projects/zydis/build.sh b/projects/zydis/build.sh
index b38ce5b..98103a4 100755
--- a/projects/zydis/build.sh
+++ b/projects/zydis/build.sh
@@ -20,6 +20,7 @@
 mkdir build && cd build
 
 cmake                                   \
+    -DZYAN_FORCE_ASSERTS=ON             \
     -DZYDIS_BUILD_EXAMPLES=OFF          \
     -DZYDIS_BUILD_TOOLS=OFF             \
     -DCMAKE_BUILD_TYPE=RelWithDebInfo   \
@@ -29,7 +30,7 @@
     -DCMAKE_CXX_FLAGS="$CXXFLAGS"       \
     ..
 
-make -j8
+make -j$(nproc) VERBOSE=1
 
 $CXX                                    \
     $CXXFLAGS                           \