Add GoodBad C# example project, integration test (#2148)

This commit is contained in:
Joe Ranweiler
2022-07-12 12:07:30 -07:00
committed by GitHub
parent c1f9d738d9
commit 69b11f60c2
4 changed files with 141 additions and 2 deletions

View File

@ -371,7 +371,7 @@ jobs:
- uses: actions/cache@v3
id: cache-radamsa-build-linux
with:
# key on the shell script only: this script fixes the
# key on the shell script only: this script fixes the
# version to a particular commit, so if it changes we need to rebuild
key: radamsa-linux-${{ hashFiles('src/ci/radamsa-linux.sh') }}
path: artifacts
@ -388,7 +388,7 @@ jobs:
- uses: actions/cache@v3
id: cache-radamsa-build-windows
with:
# key on the shell script only: this script fixes the
# key on the shell script only: this script fixes the
# version to a particular commit, so if it changes we need to rebuild
key: radamsa-windows-${{ hashFiles('src/ci/radamsa-windows.sh') }}
path: artifacts
@ -524,6 +524,11 @@ jobs:
(cd libfuzzer-aarch64-crosscompile; make)
cp -r libfuzzer-aarch64-crosscompile/fuzz.exe libfuzzer-aarch64-crosscompile/inputs artifacts/linux-libfuzzer-aarch64-crosscompile
# C# target.
sudo apt-get install -y dotnet-sdk-6.0
(cd GoodBad; dotnet publish -c Release -o out)
mv GoodBad/out artifacts/GoodBadDotnet
- uses: actions/upload-artifact@v2.2.2
with:
name: integration-test-artifacts
@ -603,3 +608,36 @@ jobs:
with:
name: integration-test-artifacts
path: src/integration-tests/artifacts
integration-tests-linux:
runs-on: ubuntu-18.04
needs:
- build-integration-tests-linux
- dotnet-fuzzing-tools-linux
steps:
- uses: actions/checkout@v2
- uses: actions/download-artifact@v2.0.8
with:
name: build-artifacts
path: build-artifacts
- uses: actions/download-artifact@v2.0.8
with:
name: integration-test-artifacts
path: integration-test-artifacts
- name: test
shell: bash
run: |
set -ex -o pipefail
# Must be absolute paths.
export GOODBAD_DOTNET="${GITHUB_WORKSPACE}/integration-test-artifacts/GoodBadDotnet"
export LIBFUZZER_DOTNET="${GITHUB_WORKSPACE}/build-artifacts/third-party/dotnet-fuzzing-linux/libfuzzer-dotnet/libfuzzer-dotnet"
chmod +x $LIBFUZZER_DOTNET
export LIBFUZZER_DOTNET_LOADER="${GITHUB_WORKSPACE}/build-artifacts/third-party/dotnet-fuzzing-linux/LibFuzzerDotnetLoader/LibFuzzerDotnetLoader"
chmod +x $LIBFUZZER_DOTNET_LOADER
export SHARPFUZZ="${GITHUB_WORKSPACE}/build-artifacts/third-party/dotnet-fuzzing-linux/sharpfuzz/SharpFuzz.CommandLine"
chmod +x $SHARPFUZZ
./src/ci/test-libfuzzer-dotnet.sh

45
src/ci/test-libfuzzer-dotnet.sh Executable file
View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -ex -o pipefail
# Required environment variables:
# - GOODBAD_DOTNET
# - LIBFUZZER_DOTNET
# - LIBFUZZER_DOTNET_LOADER
# - SHARPFUZZ
export GOODBAD_DLL='GoodBad/GoodBad.dll'
TMP=$(mktemp -d)
cd $TMP
cp -r ${GOODBAD_DOTNET} GoodBad
# Instrument DLL under test.
${SHARPFUZZ} GoodBad/GoodBad.dll
# Create seed and crash inputs.
printf 'good' > good.txt
printf 'bad!' > bad.txt
# Test individual env vars.
export LIBFUZZER_DOTNET_TARGET_ASSEMBLY="${GOODBAD_DLL}"
export LIBFUZZER_DOTNET_TARGET_CLASS='GoodBad.Fuzzer'
export LIBFUZZER_DOTNET_TARGET_METHOD='TestInput'
${LIBFUZZER_DOTNET} --target_path=${LIBFUZZER_DOTNET_LOADER} good.txt
# Expect nonzero exit.
! ${LIBFUZZER_DOTNET} --target_path=${LIBFUZZER_DOTNET_LOADER} bad.txt
# Test delimited env var.
export LIBFUZZER_DOTNET_TARGET="${LIBFUZZER_DOTNET_TARGET_ASSEMBLY}:${LIBFUZZER_DOTNET_TARGET_CLASS}:${LIBFUZZER_DOTNET_TARGET_METHOD}"
unset LIBFUZZER_DOTNET_TARGET_ASSEMBLY
unset LIBFUZZER_DOTNET_TARGET_CLASS
unset LIBFUZZER_DOTNET_TARGET_METHOD
${LIBFUZZER_DOTNET} --target_path=${LIBFUZZER_DOTNET_LOADER} good.txt
# Expect nonzero exit.
! ${LIBFUZZER_DOTNET} --target_path=${LIBFUZZER_DOTNET_LOADER} bad.txt
rm -rf $TMP

View File

@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace GoodBad;
public class BinaryParser
{
int count = 0;
public void ProcessInput(ReadOnlySpan<byte> data) {
if (data.Length < 4) {
return;
}
if (data[0] == 'b') { count++; }
if (data[1] == 'a') { count++; }
if (data[2] == 'd') { count++; }
if (data[3] == '!') { count++; }
// Simulate an out-of-bounds access while parsing.
if (count >= 4) {
var _ = data[0xdead];
}
}
}
public class Fuzzer {
/// Preferred test method.
public static void TestInput(ReadOnlySpan<byte> data) {
var parser = new BinaryParser();
parser.ProcessInput(data);
}
/// Backwards-compatible test method for legacy code that can't use `Span` types.
///
/// Incurs an extra copy of `data` per fuzzing iteration.
public static void TestInputCompat(byte[] data) {
var parser = new BinaryParser();
parser.ProcessInput(data);
}
/// Invalid static method that has a fuzzing-incompatible signature.
public static void BadSignature(ReadOnlySpan<int> data) {
return;
}
}

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<LangVersion>10.0</LangVersion>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>