### Set Up Virtual Environment and Install Dependencies Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Create and activate a Python virtual environment, then install ClusterFuzzLite and development dependencies using pip. All subsequent commands should be run within this activated environment. ```bash python3 -m venv .venv source .venv/bin/activate # Install ClusterFuzzLite dependencies. pip install -r infra/cifuzz/requirements.txt # Install development requirements. pip install -r infra/ci/requirements.txt ``` -------------------------------- ### Example build.sh for Expat Source: https://google.github.io/clusterfuzzlite/build-integration This script demonstrates building fuzz targets by configuring, compiling, and linking them with libFuzzer. It also shows how to copy dictionaries and options files. ```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 # Optional: Copy dictionaries and options files. cp $SRC/*.dict $SRC/*.options $OUT/ ``` -------------------------------- ### Build and Install Python Project Source: https://google.github.io/clusterfuzzlite/build-integration/python-lang Use 'pip3 install .' to build and install the Python project, ensuring C extensions are built with appropriate CFLAGS and CXXFLAGS. ```bash # Build and install project (using current CFLAGS, CXXFLAGS). This is required # for projects with C extensions so that they're built with the proper flags. pip3 install . ``` -------------------------------- ### Install Hypothesis Package Source: https://google.github.io/clusterfuzzlite/build-integration/python-lang Install the Hypothesis package in your Dockerfile using 'pip3 install hypothesis' to enable property-based testing. ```bash RUN pip3 install hypothesis ``` -------------------------------- ### Example Fuzzer Java File Structure Source: https://google.github.io/clusterfuzzlite/build-integration/jvm-lang A basic fuzzer in Java should be a single file named '*Fuzzer.java' without a package directive. Implement the fuzzerTestOneInput method to process input. ```java public class ExampleFuzzer { public static void fuzzerTestOneInput(byte[] input) { ... // Call a function of the project under test with arguments derived from // input and throw an exception if something unwanted happens. ... } } ``` -------------------------------- ### Install Maven in Dockerfile Source: https://google.github.io/clusterfuzzlite/build-integration/jvm-lang Add this line to your Dockerfile if your JVM project requires Maven for building. The base image includes OpenJDK 15. ```dockerfile RUN apt-get update && apt-get install -y maven ``` -------------------------------- ### Dockerfile for ClusterFuzzLite Build Environment Source: https://google.github.io/clusterfuzzlite/build-integration Defines the Docker image used to build your project and fuzz targets. It includes installing dependencies, copying source code, and setting the working directory. ```dockerfile FROM gcr.io/oss-fuzz-base/base-builder:v1 # Base image with clang toolchain RUN apt-get update && apt-get install -y ... # Install required packages to build your project. COPY . $SRC/ # Copy your project's source code. WORKDIR $SRC/ # Working directory for build.sh. COPY ./.clusterfuzzlite/build.sh $SRC/ # Copy build.sh into $SRC dir. ``` -------------------------------- ### Fuzz Target with FuzzedDataProvider Source: https://google.github.io/clusterfuzzlite/build-integration/jvm-lang Example of a Java fuzz target using FuzzedDataProvider to consume an integer and the remaining string input. Ensure the Jazzer API library is in the classpath. ```java import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class ExampleFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { int number = data.consumeInt(); String string = data.consumeRemainingAsString(); // ... } } ``` -------------------------------- ### Generate Build Integration Files Source: https://google.github.io/clusterfuzzlite/build-integration Use the helper script to generate initial configuration files for your project's build integration. Specify the project path and programming language. ```bash cd /path/to/oss-fuzz export PATH_TO_PROJECT= python infra/helper.py generate --external --language=c++ $PATH_TO_PROJECT ``` -------------------------------- ### Build Docker image and fuzz targets Source: https://google.github.io/clusterfuzzlite/build-integration Commands to build the Docker image and fuzz targets for local testing. Specify the sanitizer type as needed. ```bash $ python infra/helper.py build_image --external $PATH_TO_PROJECT ``` ```bash $ python infra/helper.py build_fuzzers --external $PATH_TO_PROJECT --sanitizer
``` -------------------------------- ### Build Go Fuzz Target with compile_go_fuzzer Source: https://google.github.io/clusterfuzzlite/build-integration/go-lang Use the compile_go_fuzzer script in build.sh to build Go fuzz targets, which also supports coverage builds. Arguments include package path, fuzz function name, fuzzer name, and an optional tag. ```bash compile_go_fuzzer github.com/miekg/dns FuzzNewRR fuzz_newrr fuzz ``` -------------------------------- ### Configure Continuous Builds with GitHub Actions Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions Set up a GitHub Actions workflow for continuous builds. This workflow triggers a build and uploads it as an artifact on every push to the main branch, used to verify if crashes are newly introduced. ```yaml name: ClusterFuzzLite continuous builds on: push: branches: - main # Use your actual default branch here. permissions: read-all jobs: Build: runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} cancel-in-progress: true strategy: fail-fast: false matrix: sanitizer: - address # Override this with the sanitizers you want. # - undefined # - memory steps: - name: Build Fuzzers (${{ matrix.sanitizer }}) id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: c++ # Change this to the language you are fuzzing. sanitizer: ${{ matrix.sanitizer }} upload-build: true ``` -------------------------------- ### Run Linting, Formatting, and Unit Tests Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Execute code formatting, linting, and unit tests using the presubmit script. The `END_TO_END_TESTS` and `INTEGRATION_TESTS` variables enable specific test suites. The `-p` flag runs tests in parallel, and `-s` skips non-ClusterFuzzLite tests. ```bash python infra/presubmit.py format python infra/presubmit.py lint # Run tests in parallel with -p option. Use -s to skip irrelevant tests. END_TO_END_TESTS=1 INTEGRATION_TESTS=1 python infra/presubmit.py infra-tests -p -s ``` -------------------------------- ### Annotated build.sh for Java Projects Source: https://google.github.io/clusterfuzzlite/build-integration/jvm-lang This script builds a Java project's JAR, determines its version, copies it to $OUT, and then compiles and wraps fuzzers using Jazzer. It sets up the necessary classpaths for building and runtime. ```bash # Step 1: Build the project # Build the project .jar as usual, e.g. using Maven. mvn package # In this example, the project is built with Maven, which typically includes the # project version into the name of the packaged .jar file. The version can be # obtained as follows: CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) # Copy the project .jar into $OUT under a fixed name. cp "target/sample-project-$CURRENT_VERSION.jar" $OUT/sample-project.jar # Specify the projects .jar file(s), separated by spaces if there are multiple. PROJECT_JARS="sample-project.jar" # Step 2: Build the fuzzers (should not require any changes) # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $PROJECT_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 $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 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 ``` -------------------------------- ### Configure Batch Fuzzing with GitHub Actions Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions Set up a GitHub Actions workflow for batch fuzzing. This workflow runs on a schedule to continuously fuzz your latest code and build up a corpus of inputs. Customize the language, sanitizers, and fuzzing duration as needed. ```yaml name: ClusterFuzzLite batch fuzzing on: schedule: - cron: '0 0/6 * * *' # Every 6th hour. Change this to whatever is suitable. permissions: read-all jobs: BatchFuzzing: runs-on: ubuntu-latest strategy: fail-fast: false matrix: sanitizer: - address # Override this with the sanitizers you want. # - undefined # - memory steps: - name: Build Fuzzers (${{ matrix.sanitizer }}) id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: c++ # Change this to the language you are fuzzing. sanitizer: ${{ matrix.sanitizer }} - name: Run Fuzzers (${{ matrix.sanitizer }}) id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 3600 mode: 'batch' sanitizer: ${{ matrix.sanitizer }} output-sarif: true # Optional but recommended: For storing certain artifacts from fuzzing. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". ``` -------------------------------- ### Configure Coverage Reports with ClusterFuzzLite Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/google-cloud-build Add this configuration to `.clusterfuzzlite/cflite_coverage.yml` to generate periodic coverage reports. Set `CLOUD_BUCKET`, `REPOSITORY`, `LANGUAGE`, `SANITIZER`, and `CFL_PLATFORM` appropriately. The `MODE` should be set to `coverage`. ```yaml steps: - name: gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'LANGUAGE=c++' # Change this to your project's language. - 'SANITIZER=coverage' - 'CFL_PLATFORM=gcb' - name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'LANGUAGE=c++' # Change this to your project's language. - 'MODE=coverage - 'SANITIZER=coverage' - 'CFL_PLATFORM=gcb' ``` -------------------------------- ### Build Fuzz Targets with cargo-fuzz Source: https://google.github.io/clusterfuzzlite/build-integration/rust-lang Use 'cargo fuzz build -O' to build fuzz targets in release mode. Copy the resulting binaries to the $OUT directory. Consider adding '--debug-assertions' for more checks. ```bash cd $SRC/json cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/from_slice $OUT/ ``` -------------------------------- ### Configure ClusterFuzzLite for Coverage Reports Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions Integrate this configuration into your `.github/workflows/cflite_cron.yml` to generate periodic coverage reports. Ensure the `language` is set correctly. Using a `storage-repo` allows viewing reports online. ```yaml jobs: Coverage: runs-on: ubuntu-latest steps: - name: Build Fuzzers id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: c++ # Change this to the language you are fuzzing. sanitizer: coverage - name: Run Fuzzers id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 600 mode: 'coverage' sanitizer: 'coverage' # Optional but recommended. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". ``` -------------------------------- ### Configure GitHub Actions for Testing Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Modify the `cifuzz.yml` file in your test repository to point to your fork of the OSS-Fuzz repository and the branch you wish to test. This ensures that your changes are tested using your specific build. ```yaml uses: /oss-fuzz/@ ``` -------------------------------- ### Clone Project Dependencies in Dockerfile Source: https://google.github.io/clusterfuzzlite/build-integration/go-lang Use 'RUN git clone' commands in your Dockerfile to fetch project dependencies. The OSS-Fuzz builder image includes Golang. ```dockerfile # Dependency for one of the fuzz targets. RUN git clone --depth 1 https://github.com/ianlancetaylor/demangle ``` -------------------------------- ### Specify Go Language in project.yaml Source: https://google.github.io/clusterfuzzlite/build-integration/go-lang Set the 'language' attribute to 'go' in your project.yaml file to indicate a Go project. ```yaml language: go ``` -------------------------------- ### Configure Git Repository for Artifact Storage Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/gitlab Set up variables in `.gitlab-ci.yml` to use a separate Git repository for storing coverage reports and corpus. Requires a project access token. ```yaml GIT_STORE_REPO: "https://oauth2:${CFL_TOKEN}@gitlab.hostname/namespace/project-cfl.git" GIT_STORE_BRANCH: main GIT_STORE_BRANCH_COVERAGE: coverage ``` -------------------------------- ### Configure Prow Job for Coverage Reports Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Use this Prow job configuration for periodic jobs to generate coverage reports from the latest corpus. Remember to substitute placeholders like `` and `` with your actual details. Daily scheduling is recommended. ```yaml - name: labels: preset-dind-enabled: "true" decorate: true extra_refs: - org: repo: base_ref: # This should be the branch you want to fuzz. interval: 24h # Note: this can be a cron as well. spec: serviceAccountName: containers: - image: gcr.io/k8s-testimages/clusterfuzzlite:latest command: - runner.sh args: - python3 - "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" # docker-in-docker needs privileged mode securityContext: privileged: true env: - name: MODE value: coverage - name: SANITIZER value: coverage - name: CLOUD_BUCKET value: - name: CFL_PLATFORM value: prow ``` -------------------------------- ### Create Google Cloud Service Account Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Use this gcloud command to create a new Google Cloud service account for ClusterFuzzLite integration. ```bash gcloud beta iam service-accounts create `` --project=`` --description=`` --display-name=`` ``` -------------------------------- ### Configure GitLab Pages for Coverage Reports Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/gitlab Add a `pages` job to your coverage report repository to build a static website. This allows you to host and view coverage reports via GitLab Pages. ```yaml pages: script: - mkdir .public - cp -r * .public - mv .public public artifacts: paths: - public ``` -------------------------------- ### ClusterFuzzLite Batch Fuzzing Configuration for GCB Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/google-cloud-build Add this to `.clusterfuzzlite/cflite_batch.yml` for batch fuzzing. Recommended to run on a cron schedule. Adjust `FUZZ_SECONDS` for desired fuzzing time. ```yaml steps: - name: gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'SANITIZER=address' # This can be changed to other sanitizers you use. - 'LANGUAGE=c++' # Change this to your project's language. - 'CFL_PLATFORM=gcb' - name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'SANITIZER=address' # This can be changed to other sanitizers you use. - 'LANGUAGE=c++' # Change this to your project's language. - 'CFL_PLATFORM=gcb' - 'MODE=batch - 'FUZZ_SECONDS=3600' # You can change this to a value you prefer. ``` -------------------------------- ### ClusterFuzzLite Continuous Build Configuration for GCB Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/google-cloud-build Add this to `.clusterfuzzlite/cflite_build.yml` to set up continuous builds. This job runs on pushes to your main branch to save a build for each commit. ```yaml steps: - name: gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'SANITIZER=address' # This can be changed to other sanitizers you use. - 'LANGUAGE=c++' # Change this to your project's language. - 'UPLOAD_BUILD=True' - 'CFL_PLATFORM=gcb' ``` -------------------------------- ### Check build integrity Source: https://google.github.io/clusterfuzzlite/build-integration Command to verify that fuzz targets are compiled with the correct sanitizer and do not crash immediately. ```bash $ python infra/helper.py check_build --external $PATH_TO_PROJECT --sanitizer
``` -------------------------------- ### Build fuzz targets for code coverage Source: https://google.github.io/clusterfuzzlite/build-integration Command to build fuzz targets specifically for generating code coverage reports. ```bash $ python infra/helper.py build_fuzzers --external --sanitizer coverage $PATH_TO_PROJECT ``` -------------------------------- ### Batch Fuzzing Job Configuration Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Configure this Prow job for periodic batch fuzzing. Set 'MODE' to 'batch' and specify the repository, branch, and fuzzing duration. Ensure 'extra_refs' are correctly set for the target repository. ```yaml - name: labels: preset-dind-enabled: "true" decorate: true extra_refs: - org: repo: base_ref: # This should be the branch you want to fuzz. interval: 24h # This can be a cron as well. spec: serviceAccountName: containers: - image: gcr.io/k8s-testimages/clusterfuzzlite:latest command: - runner.sh args: - python3 - "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" # docker-in-docker needs privileged mode securityContext: privileged: true env: - name: MODE value: batch - name: SANITIZER value: address # Change this to whatever sanitizer you want to use. - name: CLOUD_BUCKET value: - name: FUZZ_SECONDS value: 3600 # 1 Hour. You can change this. - name: CFL_PLATFORM value: prow - name: LANGUAGE value: go # Change this to whatever language you are fuzzing ``` -------------------------------- ### Configure Coverage Reports in .gitlab-ci.yml Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/gitlab Add this job to `.gitlab-ci.yml` to generate periodic coverage reports. Ensure a GitLab schedule is set up with `MODE` variable set to `coverage`. ```yaml clusterfuzzlite-coverage: image: name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 entrypoint: [""] services: - docker:dind # may be removed in self-managed GitLab instances stage: test variables: SANITIZER: "coverage" rules: - if: $MODE == "coverage" before_script: - export CFL_CONTAINER_ID=`cut -c9- < /proc/1/cpuset` script: - python3 "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" artifacts: when: always paths: - artifacts/ ``` -------------------------------- ### Configure ClusterFuzzLite for Corpus Pruning Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions Add this configuration to your `.github/workflows/cflite_cron.yml` to enable periodic corpus pruning. Customize the `language` field to match your project's language. The `storage-repo` options are recommended for better corpus management. ```yaml name: ClusterFuzzLite cron tasks on: schedule: - cron: '0 0 * * *' # Once a day at midnight. permissions: read-all jobs: Pruning: runs-on: ubuntu-latest steps: - name: Build Fuzzers id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: c++ # Change this to the language you are fuzzing - name: Run Fuzzers id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 600 mode: 'prune' output-sarif: true # Optional but recommended. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". ``` -------------------------------- ### Configure Corpus Pruning with ClusterFuzzLite Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/google-cloud-build Add this configuration to `.clusterfuzzlite/cflite_cron.yml` to enable corpus pruning. Ensure `CLOUD_BUCKET`, `REPOSITORY`, `SANITIZER`, `LANGUAGE`, and `CFL_PLATFORM` are set correctly. ```yaml jobs: steps: - name: gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'SANITIZER=address' # This can be changed to other sanitizers you use. - 'LANGUAGE=c++' # Change this to your project's language. - 'CFL_PLATFORM=gcb' - name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'SANITIZER=address' # This can be changed to other sanitizers you use. - 'LANGUAGE=c++' # Change this to your project's language. - 'CFL_PLATFORM=gcb' - 'MODE=prune' ``` -------------------------------- ### Configure Cache for Continuous Builds with GitLab Filestore Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/gitlab When using GitLab artifacts for continuous builds, define `CFL_CACHE_DIR` and configure a cache in your job. Ensure runners share access to the cache. ```yaml variables: CFL_CACHE_DIR: cfl-cache cache: key: clusterfuzzlite paths: - cfl-cache/ ``` -------------------------------- ### Specify Language in project.yaml Source: https://google.github.io/clusterfuzzlite/build-integration/python-lang Set the 'language' attribute to 'python' in your project.yaml file to indicate a Python project. ```yaml language: python ``` -------------------------------- ### Build ClusterFuzzLite Docker Images Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Use this script to rebuild ClusterFuzzLite Docker images, incorporating your source code changes for local testing. ```bash ./infra/cifuzz/build-images.sh ``` -------------------------------- ### Push Retagged Docker Images Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Push your newly retagged Docker images to your repository. This makes them available for use on remote testing systems. ```bash docker push /clusterfuzzlite-build-fuzzers:v1 ``` ```bash docker push /clusterfuzzlite-run-fuzzers:v1 ``` -------------------------------- ### Define a Fuzz Target Function Source: https://google.github.io/clusterfuzzlite/overview This C++ function is the entry point for libFuzzer. It receives input data and its size, and should call the code to be fuzzed. Return 0 for success; non-zero is reserved for future use. ```c++ // fuzz_target.cc extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { DoSomethingInterestingWithMyAPI(Data, Size); return 0; // Non-zero return values are reserved for future use. } ``` -------------------------------- ### Clone OSS-Fuzz Repository Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Obtain the ClusterFuzzLite source code by cloning the OSS-Fuzz repository. This command is assumed to be run from the root of your development environment. ```bash git clone git@github.com:google/oss-fuzz.git ``` -------------------------------- ### Set Rust Project Language in project.yaml Source: https://google.github.io/clusterfuzzlite/build-integration/rust-lang Specify 'rust' as the language in your project.yaml file. Only the 'address' sanitizer is supported. ```yaml language: rust ``` -------------------------------- ### Configure Prow Job for Corpus Pruning Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Add this configuration to your Prow job config for periodic jobs to enable corpus pruning. Ensure you replace placeholders like `` and `` with your specific values. Schedule this job to run daily for optimal results. ```yaml - name: labels: preset-dind-enabled: "true" decorate: true extra_refs: - org: repo: base_ref: # This should be the branch you want to fuzz. interval: 24h # This can be a cron as well. spec: serviceAccountName: containers: - image: gcr.io/k8s-testimages/clusterfuzzlite:latest command: - runner.sh args: - python3 - "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" # docker-in-docker needs privileged mode securityContext: privileged: true env: - name: MODE value: prune - name: CLOUD_BUCKET value: - name: CFL_PLATFORM value: prow - name: LANGUAGE value: go # Change this to whatever language you are fuzzing ``` -------------------------------- ### Configure Kubernetes Service Account for ClusterFuzzLite Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Define a Kubernetes ServiceAccount and link it to your Google Cloud service account using annotations. This allows Prow jobs to use the specified cloud service account. ```yaml apiVersion: v1 kind: ServiceAccount metadata: annotations: iam.gke.io/gcp-service-account: name: `` namespace: test-pods ``` -------------------------------- ### Build and Run Fuzzers with Private Repo Access Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions Pass the GITHUB_TOKEN to the build_fuzzers and run_fuzzers actions when ClusterFuzzLite needs to access private repositories. This token is automatically provided by GitHub Actions. ```yaml steps: - name: Build Fuzzers id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} ... - name: Run Fuzzers id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} ... ``` -------------------------------- ### Configure Continuous Builds in .gitlab-ci.yml Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/gitlab Add this job to `.gitlab-ci.yml` to trigger builds on new pushes to main/default branches. It's used to check if crashes found during MR fuzzing are newly introduced. ```yaml clusterfuzzlite-build: image: name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 entrypoint: [""] services: - docker:dind # may be removed in self-managed GitLab instances stage: test rules: # Use $CI_DEFAULT_BRANCH or $CFL_BRANCH. - if: $CI_COMMIT_BRANCH == $CFL_BRANCH && $CI_PIPELINE_SOURCE == "push" variables: MODE: "code-change" UPLOAD_BUILD: "true" before_script: - export CFL_CONTAINER_ID=`docker ps -q -f "label=com.gitlab.gitlab-runner.job.id=$CI_JOB_ID" -f "label=com.gitlab.gitlab-runner.type=build"` script: - python3 "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" artifacts: when: always paths: - artifacts/ ``` -------------------------------- ### Retag Docker Images for Remote Systems Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Retag your locally built Docker images to use your own repository for deployment on remote systems. This ensures your custom images are used instead of the default ones. ```bash docker tag \ gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 \ /clusterfuzzlite-build-fuzzers:v1 ``` ```bash docker tag \ gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 \ /clusterfuzzlite-run-fuzzers:v1 ``` -------------------------------- ### Run a specific fuzz target Source: https://google.github.io/clusterfuzzlite/build-integration Command to execute a particular fuzz target locally, using a temporary corpus directory. ```bash $ python infra/helper.py run_fuzzer --external --corpus-dir= $PATH_TO_PROJECT ``` -------------------------------- ### Fuzzing-Specific Dependencies in Cargo.toml Source: https://google.github.io/clusterfuzzlite/build-integration/rust-lang Define fuzzing-specific dependencies by wrapping them under '[target."cfg(fuzzing)".dependencies]'. This is similar to how test dependencies are defined. ```toml [target.'cfg(fuzzing)'.dependencies] ``` -------------------------------- ### Generate code coverage report Source: https://google.github.io/clusterfuzzlite/build-integration Command to generate a code coverage report for a specified fuzz target using a corpus directory. ```bash $ python infra/helper.py coverage --external $PATH_TO_PROJECT --fuzz-target= --corpus-dir= ``` -------------------------------- ### Grant Storage Access to Service Account Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Grant the created service account 'objectAdmin' role to both your custom cloud bucket and the Prow results bucket. ```bash gcloud storage buckets add-iam-policy-binding "" --member="serviceAccount:" --role="roles/storage.objectAdmin" gcloud storage buckets add-iam-policy-binding "" --member="serviceAccount:" --role="roles/storage.objectAdmin" ``` -------------------------------- ### Specify JVM Language in project.yaml Source: https://google.github.io/clusterfuzzlite/build-integration/jvm-lang Set the language attribute to 'jvm' in your project.yaml file for JVM projects. Only 'address' and 'undefined' sanitizers are supported. ```yaml language: jvm ``` -------------------------------- ### Create Standalone Python Fuzzer Packages with PyInstaller Source: https://google.github.io/clusterfuzzlite/build-integration/python-lang Use PyInstaller to create standalone packages for Python fuzzers. This is required to keep fuzzers working properly and avoid issues with Python version conflicts or environment changes. ```bash # Build fuzzers into $OUT. These could be detected in other ways. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do fuzzer_basename=$(basename -s .py $fuzzer) fuzzer_package=${fuzzer_basename}.pkg # To avoid issues with Python version conflicts, or changes in environment # over time, we use pyinstaller to create a standalone # package. Though not necessarily required for reproducing issues, this is # required to keep fuzzers working properly. pyinstaller --distpath $OUT --onefile --name $fuzzer_package $fuzzer # Create execution wrapper. Atheris requires that certain libraries are # preloaded, so this is also done here to ensure compatibility and simplify # test case reproduction. Since this helper script is what will # actually execute, it is also always required. # NOTE: If you are fuzzing python-only code and do not have native C/C++ # extensions, then remove the LD_PRELOAD line below as preloading sanitizer # library is not required and can lead to unexpected startup crashes. 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 +x $OUT/$fuzzer_basename done ``` -------------------------------- ### ClusterFuzzLite Pull Request Fuzzing Configuration for GCB Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/google-cloud-build Add this to `.clusterfuzzlite/cflite_pr.yml` to enable fuzzing on all pull requests. Set the `FUZZ_SECONDS` environment variable to control fuzzing duration. ```yaml steps: - name: gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'SANITIZER=address' # This can be changed to other sanitizers you use. - 'LANGUAGE=c++' # Change this to your project's language. - 'CFL_PLATFORM=gcb' - name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 env: - 'CLOUD_BUCKET=' - 'REPOSITORY=' - 'LANGUAGE=c++' # Change this to your project's language. - 'CFL_PLATFORM=gcb' ``` -------------------------------- ### Presubmit/Postsubmit Fuzzing Job Configuration Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/prow Add this configuration to your Prow job definition to enable ClusterFuzzLite fuzzing for pull requests or commits. Ensure 'MODE' is set to 'code-change'. ```yaml - name: labels: preset-dind-enabled: "true" decorate: true spec: serviceAccountName: containers: - image: gcr.io/k8s-testimages/clusterfuzzlite:latest command: - runner.sh args: - python3 - "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" # docker-in-docker needs privileged mode securityContext: privileged: true env: - name: MODE value: code-change - name: SANITIZER value: address # Change this to whatever sanitizer you want to use. - name: CLOUD_BUCKET value: - name: CFL_PLATFORM value: prow - name: LANGUAGE value: go # Change this to whatever language you are fuzzing ``` -------------------------------- ### Automatically Copy All Fuzz Targets Source: https://google.github.io/clusterfuzzlite/build-integration/rust-lang This bash script iterates through all fuzz target files and copies their compiled binaries to the output directory, ensuring new targets are automatically integrated. ```bash FUZZ_TARGET_OUTPUT_DIR=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 ``` -------------------------------- ### ClusterFuzzLite PR Fuzzing Workflow Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions This workflow enables fuzzing for all pull requests to your repository. It uses the 'build_fuzzers' and 'run_fuzzers' actions. Customize the 'language' and 'sanitizer' options as needed. The 'fuzz-seconds' parameter controls the fuzzing duration. ```yaml name: ClusterFuzzLite PR fuzzing on: pull_request: paths: - '**' permissions: read-all jobs: PR: runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} cancel-in-progress: true strategy: fail-fast: false matrix: sanitizer: - address # Override this with the sanitizers you want. # - undefined # - memory steps: - name: Build Fuzzers (${{ matrix.sanitizer }}) id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: c++ # Change this to the language you are fuzzing. github-token: ${{ secrets.GITHUB_TOKEN }} sanitizer: ${{ matrix.sanitizer }} # Optional but recommended: used to only run fuzzers that are affected # by the PR. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". - name: Run Fuzzers (${{ matrix.sanitizer }}) id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 600 mode: 'code-change' sanitizer: ${{ matrix.sanitizer }} output-sarif: true # Optional but recommended: used to download the corpus produced by # batch fuzzing. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". ``` -------------------------------- ### Run Specific Pytest Tests Source: https://google.github.io/clusterfuzzlite/developing-clusterfuzzlite Execute specific tests using pytest with the `-k` option to filter by name. Ensure `CIFUZZ_TEST=1` is set, along with `END_TO_END_TESTS` and `INTEGRATION_TESTS` if applicable. ```bash END_TO_END_TESTS=1 CIFUZZ_TEST=1 INTEGRATION_TESTS=1 pytest -s -vv -k GetGitUrlTest ``` -------------------------------- ### Configure Batch Fuzzing Trigger on Push Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/github-actions Modify the GitHub Actions workflow to trigger batch fuzzing on every push to your main branch. Ensure the `branches` field correctly specifies your project's default branch. ```yaml on: push: branches: - main # Use your actual default branch here. ``` -------------------------------- ### Batch Fuzzing and Corpus Pruning Configuration for GitLab CI Source: https://google.github.io/clusterfuzzlite/running-clusterfuzzlite/gitlab This configuration enables continuous, scheduled fuzzing and corpus pruning. Set the `MODE` variable to `batch` for fuzzing and `prune` for corpus pruning via GitLab schedules. This job should target the main/default/`CFL_BRANCH` branch. ```yaml clusterfuzzlite-corpus: image: name: gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 entrypoint: [""] services: - docker:dind # may be removed in self-managed GitLab instances stage: test rules: - if: $MODE == "prune" - if: $MODE == "batch" before_script: - export CFL_CONTAINER_ID=`docker ps -q -f "label=com.gitlab.gitlab-runner.job.id=$CI_JOB_ID" -f "label=com.gitlab.gitlab-runner.type=build"` script: - python3 "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py" artifacts: when: always paths: - artifacts/ ``` -------------------------------- ### Conditional Compilation for Rust Tests Source: https://google.github.io/clusterfuzzlite/build-integration/rust-lang Wrap test code in #[cfg(test)] to ensure it's only compiled when building in test mode. ```rust #[cfg(test)] mod tests { use super::*; ... ``` -------------------------------- ### Combined Test and Fuzzing Logic in Rust Source: https://google.github.io/clusterfuzzlite/build-integration/rust-lang Combine test and fuzzing logic by using the #[cfg(any(test, fuzzing))] attribute. This allows code to be compiled in both test and fuzzing builds. ```rust #[cfg(any(test, fuzzing))] ```