mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-15 11:28:09 +00:00
Move integration test artifacts into primary source tree (#336)
This commit is contained in:
73
.github/workflows/ci.yml
vendored
73
.github/workflows/ci.yml
vendored
@ -312,3 +312,76 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: release-artifacts
|
name: release-artifacts
|
||||||
path: release-artifacts
|
path: release-artifacts
|
||||||
|
build-integration-tests-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
set -ex
|
||||||
|
cd src/integration-tests
|
||||||
|
mkdir -p artifacts
|
||||||
|
cp integration-test.py artifacts/
|
||||||
|
|
||||||
|
mkdir -p artifacts/linux-libfuzzer
|
||||||
|
(cd libfuzzer ; make )
|
||||||
|
cp -r libfuzzer/fuzz.exe libfuzzer/seeds artifacts/linux-libfuzzer
|
||||||
|
|
||||||
|
mkdir -p artifacts/linux-trivial-crash
|
||||||
|
(cd trivial-crash ; make )
|
||||||
|
cp -r trivial-crash/fuzz.exe trivial-crash/seeds artifacts/linux-trivial-crash
|
||||||
|
|
||||||
|
mkdir -p artifacts/linux-trivial-crash-asan
|
||||||
|
(cd trivial-crash ; make clean; make CFLAGS='-fsanitize=address -fno-omit-frame-pointer')
|
||||||
|
cp -r trivial-crash/fuzz.exe trivial-crash/seeds artifacts/linux-trivial-crash-asan
|
||||||
|
|
||||||
|
mkdir -p artifacts/linux-libfuzzer-rust
|
||||||
|
(cd libfuzzer-rust ; make )
|
||||||
|
cp -r libfuzzer-rust/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 artifacts/linux-libfuzzer-rust
|
||||||
|
|
||||||
|
# AFL v2.75b
|
||||||
|
mkdir -p artifacts/linux-trivial-crash-afl
|
||||||
|
git clone https://github.com/google/AFL
|
||||||
|
(cd AFL; git checkout 82b5e359463238d790cadbe2dd494d6a4928bff3; make afl-gcc afl-fuzz afl-as)
|
||||||
|
export AFL_CC_PATH=$PWD/AFL/afl-clang
|
||||||
|
(cd trivial-crash ; make clean; make CC=$AFL_CC_PATH)
|
||||||
|
cp -r trivial-crash/fuzz.exe trivial-crash/seeds artifacts/linux-trivial-crash-afl
|
||||||
|
- uses: actions/upload-artifact@v2.1.4
|
||||||
|
with:
|
||||||
|
name: integration-test-artifacts
|
||||||
|
path: src/integration-tests/artifacts
|
||||||
|
build-integration-tests-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
Invoke-Expression (Invoke-RestMethod 'https://chocolatey.org/install.ps1')
|
||||||
|
choco install llvm
|
||||||
|
choco install make
|
||||||
|
$env:Path += ";C:\Program Files\LLVM\bin;C:\ProgramData\chocolatey\bin"
|
||||||
|
|
||||||
|
cd src/integration-tests
|
||||||
|
|
||||||
|
mkdir artifacts/windows-libfuzzer
|
||||||
|
cd libfuzzer
|
||||||
|
make
|
||||||
|
cp fuzz.exe,fuzz.pdb,seeds ../artifacts/windows-libfuzzer -Recurse
|
||||||
|
cd ../
|
||||||
|
|
||||||
|
mkdir artifacts/windows-trivial-crash
|
||||||
|
cd trivial-crash
|
||||||
|
make
|
||||||
|
cp fuzz.exe,fuzz.pdb,seeds ../artifacts/windows-trivial-crash -Recurse
|
||||||
|
cd ../
|
||||||
|
|
||||||
|
mkdir artifacts/windows-trivial-crash-asan
|
||||||
|
cd trivial-crash
|
||||||
|
make clean
|
||||||
|
make CFLAGS='-fsanitize=address -fno-omit-frame-pointer'
|
||||||
|
cp fuzz.exe,fuzz.pdb,seeds ../artifacts/windows-trivial-crash-asan -Recurse
|
||||||
|
shell: powershell
|
||||||
|
- uses: actions/upload-artifact@v2.1.4
|
||||||
|
with:
|
||||||
|
name: integration-test-artifacts
|
||||||
|
path: src/integration-tests/artifacts
|
||||||
|
9
src/integration-tests/libfuzzer-rust/Cargo.toml
Normal file
9
src/integration-tests/libfuzzer-rust/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "rust_fuzz_example"
|
||||||
|
version = "0.1.0"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["<fuzzing@microsoft.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.79"
|
10
src/integration-tests/libfuzzer-rust/Makefile
Normal file
10
src/integration-tests/libfuzzer-rust/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all:
|
||||||
|
rustup install nightly
|
||||||
|
cargo install cargo-fuzz
|
||||||
|
cargo +nightly fuzz build --release
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
|
(cd fuzz; cargo clean)
|
22
src/integration-tests/libfuzzer-rust/README.md
Normal file
22
src/integration-tests/libfuzzer-rust/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Fuzzing Rust in OneFuzz
|
||||||
|
|
||||||
|
OneFuzz can orchastrate fuzzing of Rust using
|
||||||
|
[cargo-fuzz](https://crates.io/crates/cargo-fuzz) to build libfuzzer based
|
||||||
|
fuzzing targets.
|
||||||
|
|
||||||
|
Included in this directory is a simple example to demonstrate rust based
|
||||||
|
fuzzing. For more examples, check out the libfuzzer examples in the [rust
|
||||||
|
fuzzing trophy case](https://github.com/rust-fuzz/trophy-case).
|
||||||
|
|
||||||
|
## Example command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ensure the latest cargo-fuzz is installed
|
||||||
|
cargo install cargo-fuzz --force
|
||||||
|
# build your fuzzing targets
|
||||||
|
cargo +nightly fuzz build --release
|
||||||
|
# Launch a fuzz job for each of the targets provided by cargo-fuzz
|
||||||
|
for target in $(cargo fuzz list); do
|
||||||
|
onefuzz template libfuzzer basic $PROJECT_NAME $target $BUILD_NUMBER $POOL_NAME --target_exe ./fuzz/target/x86_64-unknown-linux-gnu/release/$target --inputs ./fuzz/corpus/$target
|
||||||
|
done
|
||||||
|
```
|
3
src/integration-tests/libfuzzer-rust/fuzz/.gitignore
vendored
Normal file
3
src/integration-tests/libfuzzer-rust/fuzz/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target
|
||||||
|
corpus
|
||||||
|
artifacts
|
25
src/integration-tests/libfuzzer-rust/fuzz/Cargo.toml
Normal file
25
src/integration-tests/libfuzzer-rust/fuzz/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[package]
|
||||||
|
name = "rust-fuzz"
|
||||||
|
version = "0.0.0"
|
||||||
|
authors = ["Automatically generated"]
|
||||||
|
publish = false
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
cargo-fuzz = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libfuzzer-sys = "0.3"
|
||||||
|
|
||||||
|
[dependencies.rust_fuzz_example]
|
||||||
|
path = ".."
|
||||||
|
|
||||||
|
# Prevent this from interfering with workspaces
|
||||||
|
[workspace]
|
||||||
|
members = ["."]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "fuzz_target_1"
|
||||||
|
path = "fuzz_targets/fuzz_target_1.rs"
|
||||||
|
test = false
|
||||||
|
doc = false
|
@ -0,0 +1,7 @@
|
|||||||
|
#![no_main]
|
||||||
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
use rust_fuzz_example;
|
||||||
|
|
||||||
|
fuzz_target!(|data: &[u8]| {
|
||||||
|
rust_fuzz_example::check(data);
|
||||||
|
});
|
34
src/integration-tests/libfuzzer-rust/src/lib.rs
Normal file
34
src/integration-tests/libfuzzer-rust/src/lib.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
extern crate libc;
|
||||||
|
|
||||||
|
pub fn check(data: &[u8]) -> bool {
|
||||||
|
if data.len() < 4 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if data[0] != 0x41 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if data[1] != 0x42 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if data[2] != 0x43 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match data[3] {
|
||||||
|
// OOB access
|
||||||
|
4 => data[100000] == 0xFF,
|
||||||
|
// null ptr
|
||||||
|
5 => unsafe {
|
||||||
|
let ptr: *mut u8 = 0 as *mut u8;
|
||||||
|
*ptr = 10;
|
||||||
|
true
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
16
src/integration-tests/libfuzzer/Makefile
Normal file
16
src/integration-tests/libfuzzer/Makefile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
CC=clang
|
||||||
|
|
||||||
|
CFLAGS=-g3 -fsanitize=fuzzer -fsanitize=address
|
||||||
|
|
||||||
|
all: fuzz.exe
|
||||||
|
|
||||||
|
fuzz.exe: simple.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
test: fuzz.exe
|
||||||
|
./fuzz.exe -runs=100 seeds
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f fuzz.exe
|
1
src/integration-tests/libfuzzer/seeds/good.txt
Normal file
1
src/integration-tests/libfuzzer/seeds/good.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
good
|
65
src/integration-tests/libfuzzer/simple.c
Normal file
65
src/integration-tests/libfuzzer/simple.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t len) {
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
if (len < 4) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[0] == 'x') { cnt++; }
|
||||||
|
if (data[1] == 'y') { cnt++; }
|
||||||
|
if (data[2] == 'z') { cnt++; }
|
||||||
|
|
||||||
|
if (cnt >= 3) {
|
||||||
|
switch (data[3]) {
|
||||||
|
case '0': {
|
||||||
|
// segv
|
||||||
|
int *p = NULL; *p = 123;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '1': {
|
||||||
|
// stack-buffer-underflow
|
||||||
|
int* p = &cnt - 32; for (int i = 0; i < 32; i++) { *(p + i) = 0; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '2': {
|
||||||
|
// stack-buffer-overflow
|
||||||
|
int* p = &cnt + 32; for (int i = 0; i < 32; i++) { *(p - i) = 0; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '3': {
|
||||||
|
// bad-free
|
||||||
|
int *p = &cnt; free(p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '4': {
|
||||||
|
// double-free
|
||||||
|
int* p = malloc(sizeof(int)); free(p); free(p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '5': {
|
||||||
|
// heap-use-after-free
|
||||||
|
int* p = malloc(sizeof(int)); free(p); *p = 123;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '6': {
|
||||||
|
// heap-buffer-overflow
|
||||||
|
int* p = malloc(8 * sizeof(int)); for (int i = 0; i < 32; i++) { *(p + i) = 0; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '7': {
|
||||||
|
// fpe
|
||||||
|
int x = 0; int y = 123 / x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
19
src/integration-tests/trivial-crash/Makefile
Executable file
19
src/integration-tests/trivial-crash/Makefile
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
CLEANCMD=del fuzz.exe, fuzz.exp, fuzz.lib, fuzz.pdb, fuzz-afl.exe, afl-llvm-rt.o.o, fuzz.o, main.o
|
||||||
|
else
|
||||||
|
CLEANCMD=rm -rf fuzz.exe fuzz.exp fuzz.lib fuzz.pdb fuzz-afl.exe afl-llvm-rt.o.o fuzz.o main.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
CC=clang
|
||||||
|
OBJS=fuzz.c
|
||||||
|
CFLAGS=-O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||||
|
|
||||||
|
all: fuzz.exe
|
||||||
|
|
||||||
|
fuzz.exe: $(OBJS)
|
||||||
|
$(CC) -g3 $(CFLAGS) $(OBJS) -o $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(CLEANCMD)
|
83
src/integration-tests/trivial-crash/fuzz.c
Normal file
83
src/integration-tests/trivial-crash/fuzz.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#include <io.h>
|
||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#define STDIN_FILENO _fileno(stdin)
|
||||||
|
#define read _read
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIZE 8192
|
||||||
|
#define BUF_SIZE 32
|
||||||
|
|
||||||
|
int check(const char *data, size_t len)
|
||||||
|
{
|
||||||
|
char buf[BUF_SIZE];
|
||||||
|
memset(buf, 0, BUF_SIZE);
|
||||||
|
strncpy(buf, data, len); // BUG - This incorrectly uses length of src, not dst
|
||||||
|
|
||||||
|
// do something to ensure this isn't optimized away
|
||||||
|
int buflen = strlen(buf);
|
||||||
|
for (int i = 0; i <= ((buflen % 2 == 1) ? buflen - 1 : buflen) / 2; i++)
|
||||||
|
{
|
||||||
|
if (buf[i] != buf[buflen - 1 - i])
|
||||||
|
{
|
||||||
|
printf("not palindrome\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int from_stdin()
|
||||||
|
{
|
||||||
|
char input[SIZE] = {0};
|
||||||
|
int size = read(STDIN_FILENO, input, SIZE);
|
||||||
|
return check(input, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int from_file(char *filename)
|
||||||
|
{
|
||||||
|
FILE *infile;
|
||||||
|
char *buffer;
|
||||||
|
long length;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
infile = fopen(filename, "r");
|
||||||
|
|
||||||
|
if (infile == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fseek(infile, 0L, SEEK_END);
|
||||||
|
length = ftell(infile);
|
||||||
|
|
||||||
|
fseek(infile, 0L, SEEK_SET);
|
||||||
|
buffer = calloc(length, sizeof(char));
|
||||||
|
if (buffer == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
length = fread(buffer, sizeof(char), length, infile);
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
result = check(buffer, length);
|
||||||
|
free(buffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
return from_stdin();
|
||||||
|
}
|
||||||
|
else if (argc > 1)
|
||||||
|
{
|
||||||
|
return from_file(argv[1]);
|
||||||
|
}
|
||||||
|
}
|
1
src/integration-tests/trivial-crash/seeds/fail.txt
Normal file
1
src/integration-tests/trivial-crash/seeds/fail.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
hello
|
1
src/integration-tests/trivial-crash/seeds/pass.txt
Normal file
1
src/integration-tests/trivial-crash/seeds/pass.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
racecar
|
Reference in New Issue
Block a user