Published December 28, 2023 | Version v3
Software Open

ICSE2024 Artifact for "RPG: Rust Library Fuzzing with Pool-based Fuzz Target Generation and Generic Support"

Creators

Description

## Setup

### Requirements
- Hardware Requirements:
- Operating System: >= Ubuntu 20.04 LTS.
- Docker: The only requirement is to install Docker.

### Install Locally

#### Install dependencies

For MacOS, install the tool dependencies with
 
brew install python3 expect tmux

For Ubuntu install the tool dependencies with

sudo apt install python3 expect tmux

Install the rustup tool with
 
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain nightly-2022-09-15

Then reload your PATH environment with (or following the command provided by rustup installation)

source "$HOME/.cargo/env"

#### Install tool (One-click build)

For simplicity, we provide shell script for the whole installation. Navigate to the root of the cloned repository and run the following script (you must see the "exit 0" on your terminal after the installation)

scripts/build.sh init

This will clone rust-1.65.0 from the gitclone. you can use `scripts/build.sh init0` to clone rust-1.65.0 from github.

In case the installation process is interrupted due to network timeouts or other reasons, it may be necessary to run the installation process again.

If rust-1.65.0 has been built, you can use `scripts/build.sh build` to build the tool fast.

----------

## Usage

### Setup Environment Variables

You can use the following script to quickly set environment variables.

# Every time you open a new terminal, you need to re-execute this command.
# You need to give a param to choose a sequence traversal strategy.
# Currently supported:
# 1. bfs
# 2. ubfs
# 3. wubfs(default)
source scripts/init_env.sh wubfs

Or setup environment variables manually:

# Add root directory to `PATH`
export ROOT_DIR={path_to_rpg}/Rust-Lib-Testing
export PATH=${ROOT_DIR}:$PATH

# Sequence Traversal Strategy
# Currently supported:
# 1. bfs
# 2. ubfs
# 3. wubfs(default)
export Strategy=wubfs

# Generic Support
# 1. true(default)
# 2. false
export GenericMode=true

# Search Heuristics
# Currently supported:
# 1. heuristic
# 2. unsafeHeuristic
# 3. all
export GenChoose=unsafeHeuristic

### Compile with Address Sanitizer

You can compile the prgrom with Adress Sanitizer, which helps with finding bugs. Then, nightly symbol is necessary when compiling.

export RUSTFLAGS=-Zsanitizer=address
export RUSTDOCFLAGS=-Zsanitizer=address

### Generate Raw API Call Sequences

In the following, we use the crate `unicode-segmentation` of version v1.8.0 in the `tests` folder as our example to explain how to use the tool. You can use the following instructions to generate fuzz targets for `unicode-segmentation`.

cd tests/unicode-segmentation
rustgen init

Then you will get fuzz targets in the folder `tests/unicode-segmentation/fuzz_target/unicode-segmentation_wubfs_generic_fuzz` and get information about generated fuzz targets as follows:

>>>>> WRITING FILE START
CRATE TEST DIR: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_targetunicode_segmentation_wubfs_generic_fuzz
targets covered by reverse search: 1
average time to fuzz each api = 1.4285714285714286
0->1(0), 0->2(0), 0->3(0), 0->4(0), 0->5(0), 0->6(0), CRATE DOT: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_graph_generic.dot
LIBFUZZER_FUZZ_TARGET_DIR: /Rust-Lib-Testing/tests/unicode-segmentation/libfuzzer_target/unicode_segmentation_wubfs_fuzz
CRATE API: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_api_generic.txt
CRATE DEPENDENCY: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_dependency_generic.txt
-----------------STATISTICS-----------------
------------------------------------------------
|       TN      |       IN      |       CN      |
|       7       |       7       |       1.00    |
------------------------------------------------
|       UTN     |       UIN     |       UCN     |
|       0       |       0       |       NaN     |
------------------------------------------------
|       TE      |       IE      |       CE      |
|       16      |       6       |       0.38    |
------------------------------------------------
|       UTE     |       UIE     |       UCE     |
|       0       |       0       |       NaN     |
------------------------------------------------
CRATE API: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_info_generic.xls
CRATE SEQUENCE: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_sequence_generic.txt
CRATE API GRAPH: /Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_api_graph_generic.txt
WRITING FILE FINISHED <<<<<


Generic functions Num: 0
total functions in crate : 7
total test sequences : 109
Total Time Used: 246
Fuzz Target Generator exits successfully. Total time cost: 585 ms

As shown in the output above, the fuzz targets cover all functions of the crate (7/7, IN/TN) and part of edges of the crate (6/16, IE/TE). And there are no `unsafe` function in this crate. You can get the generated sequences in file `/Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_sequence_generic.txt` (CRATE SEQUENCE).

### Generate Compilable Fuzz Targets

Next, we deploy the Compilable fuzz targets that can be used by afl.rs. You need to make sure you have correctly installed AFL.rs and run AFL.rs properly. You can follow the instructions on rust-fuzz-book.

cd tests/unicode-segmentation
rustgen target

If RPG works normally, you can get the information about compilable fuzz targets:

cargo.toml created
Initializing "test_unicode_segmentation3"
Initializing "test_unicode_segmentation1"
Initializing "test_unicode_segmentation0"
Initializing "test_unicode_segmentation2"
Initializing "replay_unicode_segmentation3"
Initializing "replay_unicode_segmentation1"
Initializing "replay_unicode_segmentation0"
Initializing "replay_unicode_segmentation2"
[CARGO_TOML] [package]
[CARGO_TOML]
[CARGO_TOML] name = "unicode-segmentation"
[CARGO_TOML] version = "1.10.1"
[CARGO_TOML] authors = ["kwantam <kwantam@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"]
[CARGO_TOML]
[CARGO_TOML] edition = "2018"
[CARGO_TOML] homepage = "https://github.com/unicode-rs/unicode-segmentation"
[CARGO_TOML] repository = "https://github.com/unicode-rs/unicode-segmentation"
[CARGO_TOML] documentation = "https://unicode-rs.github.io/unicode-segmentation"
[CARGO_TOML]
test version: {path="/Rust-Lib-Testing/tests/unicode-segmentation"}, false
test version: {path="/Rust-Lib-Testing/tests/unicode-segmentation"}, false
test version: {path="/Rust-Lib-Testing/tests/unicode-segmentation"}, false
test version: {path="/Rust-Lib-Testing/tests/unicode-segmentation"}, false
Building "unicode_segmentation"
status: exit status: 0
Finish building crate.
total: 4 success: 4

We can know from the output above that RPG has generated 4 fuzz targets and all of 4 targets is compilable.

[Mac OS Note]: According to the issue 858 of AFLplusplus, MacOS has a ridiculous small default shared memory size. Try `ipcs -m | cut -f2 -d' ' | xargs -I {} sudo ipcrm -m {}; ipcs -m | cut -f3 -d' ' | xargs -I {} sudo ipcrm -m {}` to remove old maps, then `sudo sysctl -w kern.sysv.shmall=65536` and `sudo sysctl -w kern.sysv.shmmax=16777216`.

### Fuzzing with AFL.rs

After you get fuzz targets, you can fuzz these targets with AFL.rs. You can follow the instructions of AFL on your own. Or use the command below.

cd tests/unicode-segmentation
rustgen fuzz

The fuzzing info will be displayed on your terminal:

----------------------- FUZZ INFO -----------------------
FUZZING HAS RUN 7200 SECONDS.
Crash for "/Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_generic_fuzz/multipleTargets/out/test_unicode_segmentation1": 2
Crash for "/Rust-Lib-Testing/tests/unicode-segmentation/fuzz_target/unicode_segmentation_wubfs_generic_fuzz/multipleTargets/out/test_unicode_segmentation0": 31
TOTAL CRASH:    33
EXIT IN PERIOD: 0
EXITED THREADS: 3
RUNNING THREADS:1
WAITING THREADS:0
----------------------- FUZZ INFO -----------------------
Fuzzing totally runs 7200282 ms. All fuzzing thread finished

This only shows the result of one of the fuzzing threads. The fuzzing thread triggered 33 crashes, 2 by fuzzing `test_unicode_segmentation1` and 31 by fuzzing `test_unicode_segmentation0`.

Files

RPG.zip

Files (3.7 MB)

Name Size Download all
md5:a5336b081d248d14a5ee9625d77fb6e0
3.7 MB Preview Download