QuickCheck bug hunting in Rust standard library data structures

Related tags

Testing bughunt-rust
Overview

BugHunt, Rust

Build Status

This project is aiming to provide "stateful" QuickCheck models for Rust's standard library. That is, we build up a random list of operations against an abstract data type, an "obviously correct" model of that ADT and apply the operations to both the model and the reference implementation of the data type. If the model and reference implementation differ in any way then that's a good sign there's a bug to be diagnosed and reported. This is different from fuzzing in that we're interested in higher-level behaviour of data structures--their "properties"--and aren't necessarily looking for crashes. (That said, "do not crash the program" is a pretty good property for most data structures.)

We're inspired by the work @jlouis did in the Erlang community to detect subtle bugs in that language's map implementation and @shnatsel's recent work fuzzing Rust crates for crashes.

Running the Suite

Running the tests takes a little leg work. The project performs model-based fuzzing, which means the tests are driven by a fuzzer, cargo-fuzz (libFuzzer) in particular. We've written about the general approach here. Since this post we've switch from AFL to libFuzzer but the broad details remain the same.

The available targets are listed out in [fuzz/Cargo.toml], the binaries of the project. Say you want to run the str::repeat target. Make sure you've got cargo-fuzz installed by running cargo install cargo-fuzz.

> cargo fuzz run str_repeat

A reasonable test run will take hours and as configured the above run will execute forever. Give the flag --help to cargo fuzz to see its options relating to runtime constriction, corpus definition etc.

Why does this run outside of Rust itself?

Well! I'm not sure that bundling these long-running tests into the Rust compiler project is something anyone would go for and, working here as an external project, we can avoid needing to fiddle with toolchains and longish build cycles. Downside is, the std data structures we're testing don't have any sanitizers turned on etc on account of the project is run against the usual Rust release.

Contributing

Writing QuickCheck models can be slow work and contributions are very welcome, either introducing new models into the project or extending existing ones. We have an experimental clusterfuzz setup running and if you have credits to donate that would be most welcome. I intend to document project balances, money needs once they are clear.

Would you take CI help?

Yes! Right now we have a folder ci/ which has the build scripts used in .travis.yml. We're producing test binaries and feeding them directly into the clusterfuzz setup the project has. Speaking of, I'll be adding configuration for that cluster to this repository in the coming days.

Any improvements in the build pipeline, clusterfuzz configuration are most welcome.

Would you take documentation help?

Yes!

Hey, how can I learn more?

Randomized testing is a touch esoteric but there's a lot of reading material available (itself a problem, kind of). In no certain order:

I, blt, am also happy to answer questions over email. I'm [email protected].

Comments
  • Use fuzzing to drive property testing

    Use fuzzing to drive property testing

    This series of commits introduces the use of arbitrary and honggfuzz-rs in driving property tests, as discussed briefly by @Shnatsel and myself in #2. The code is now split between the library bits -- the Op, Arbitrary definition etc -- and the interpreter loop, now in the fuzz target called hash_map. If you have honggfuzz-rs installed you can run the fuzz target like:

    > cargo hfuzz run hash_map
    

    Installation instructions for honggfuzz can be found at the above project link.

    In terms of finding bugs, this was effective at finding the panic crash resulting from @llogiq's introduction of Op::Reserve. The problem, as discussed in 9596448, is that we can make very large capacity requests of the HashMap and it will be unable to allocate memory to meet that request, causing a panic. HashMap does not publish its overhead per pair so we cannot determine if a reservation will fail ahead of time. The check we have in place mostly guards against this but fuzzing managed to turn up truly large reservation failures. It was neat.

    The downside to this approach is there's no tooling support for it: no shrinking, failure reports are given as the byte inputs. Dropping into a debugger works well enough but it's not the best.

    opened by blt 12
  • Update README to reflect AFL runner

    Update README to reflect AFL runner

    This commit updates the README to reflect the changes made to use model-based fuzzing, as opposed to straight QuickCheck. This resolves

    Signed-off-by: Brian L. Troutwine [email protected]

    opened by blt 4
  • Adapt bughunt-rust to run in clusterfuzz

    Adapt bughunt-rust to run in clusterfuzz

    Now that clusterfuzz is open-source we can resolve a long-standing issue of bughunt-rust: not having enough CPU time. We should port tests to be runnable in clusterfuzz, setup a build pipeline etc.

    Specific tickets to follow.

    opened by blt 1
  • Introduce ClusterFuzz support

    Introduce ClusterFuzz support

    With this series of commits I've now enabled clusterfuzz support for the project, running at https://bughunt.appspot.com/. The use of AFL is now removed in favor of cargo-fuzz/libFuzzer for easy compatibility with clusterfuzz. This has made the README instructions more straightforward, which hopefully will help new contributors to the project.

    For reasons related, I think, to the travis org/com distinction the branch push builds -- done on org -- fail while the branch builds -- done on com -- succeed. This is a result of the secrets being pegged to com. I'll see after this is merged if I can sort out which domain the project will always run on.

    The clusterfuzz setup consumes actual funds, though for now we're operating out of credits. This project will need to sort out funding at some point, if the clusterfuzz setup proves worth keeping.

    opened by blt 0
  • Introduce more Ops for HashMap

    Introduce more Ops for HashMap

    This commit introduces three new operations against HashMap: ShrinkToFit, CheckCapacity and Clear. The consequences of these operations are documented in the commit itself. I've also updated the travis CI runner to run more tests of larger size by default. This will need to be dialed backward as the number of models grow.

    Signed-off-by: Brian L. Troutwine [email protected]

    opened by blt 0
  • Introduce an initial travis CI configuration

    Introduce an initial travis CI configuration

    This commit introduces a basic Travis CI configuration into the project. QC tests will just fly right on by but our clippy and formatting warnings will be checked. The developer should still run their models on their local machines for long periods.

    Signed-off-by: Brian L. Troutwine [email protected]

    opened by blt 0
  • Collect a list of known defects

    Collect a list of known defects

    Any bug searching technique lives and dies by its ability to find, well, bugs. To judge how well our approach is doing in this project we need a list of known defects. That is:

    • details / bug issue number
    • [optional] method to reproduce
    • impacted version(s) of Rust

    From this we can start to build a table of Time to Discovery for the given issue.

    opened by blt 1
  • Resolve OOM panics

    Resolve OOM panics

    As detailed in this post hunting for bugs is hampered right now because of Rust's panic strategy around allocation failures. We should introduce techniques to avoid these panics, related issues of edge-cases being masked by OOM panics.

    opened by blt 2
  • Thoughts on README in no particular order

    Thoughts on README in no particular order

    Opening an issue because github doesn't provide a better communication mechanism. Hopefully some of these points are actionable.

    Downside is, the std data structures we're testing don't have any sanitizers turned on etc on account of the project is run against the usual Rust releases.

    libdislocator can catch many (but not all) memory errors for black-box binaries, assuming they use the system allocator.

    Rust sanitizer integration lists steps to rebuild stdlib with sanitizer support, but calls it "better backtraces". We might want to get in touch and check how exactly sanitizers can be enabled for stdlib primitives.

    This project will happily take fuzz code. Or, if someone could contrive to combine a fuzzer with a shrinking step this project will jump on that in a heartbeat.

    Both AFL and libfuzzer shrink the inputs as they go along. They have Rust integration as afl.rs and cargo-fuzz respectively. Both have a one-shot testcase minimization command, which doesn't usually do a great job. However, AFL also comes with a crash exploration mode lets you explore alternative crashing inputs and minimize the testcase to your heart's content.

    Also, Rust QuickCheck README mentions proptest as an alternative to QuickCheck that improves on shrinking and links to some comparisons of the two.

    opened by Shnatsel 26
Owner
Brian L. Troutwine
Brian L. Troutwine
The trait for generating structured data from arbitrary, unstructured input.

Arbitrary The trait for generating structured data from arbitrary, unstructured input. About The Arbitrary crate lets you construct arbitrary instance

Rust Fuzzing Authority 407 Dec 24, 2022
TestDrive automatically scrapes input/output data from BOJ(Baekjoon Online Judge) and runs tests for your executable binary file!

?? TestDrive What does it do? TestDrive automatically scrapes input/output data from BOJ(Baekjoon Online Judge) and runs tests for your executable bin

Hyeonseok Jung 3 Mar 5, 2022
Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library.

?? Playwright for Rust Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library. Installation [dependenci

octaltree 132 Jan 6, 2023
HTTP mocking library for Rust.

httpmock HTTP mocking library for Rust. Documentation · Crate · Report Bug · Request Feature · Changelog Features Simple, expressive, fluent API. Many

Alexander Liesenfeld 320 Dec 21, 2022
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Dec 29, 2022
Rust testing library

K9 - Rust Testing Library Snapshot testing + better assertions Available test macros snapshot assert_equal assert_greater_than assert_greater_than_or_

Aaron Abramov 269 Dec 10, 2022
Struct mocking library for Rust

faux   A library to create mocks out of structs. faux allows you to mock the methods of structs for testing without complicating or polluting your cod

Andres 322 Dec 20, 2022
beaver is a library for setting up Rust objects inspired by factory_bot.

beaver is a library for setting up Rust objects inspired by factory_bot. Usage | Examples | Docs Dependencies [dependenci

Takayuki Maeda 40 Sep 6, 2022
Rustress - stress testing library in Rust. For fun

rustress Simple network stress testing library. To get familiar with Rust Planned features (Subject to change) Multithreaded client/server Throughput

Hakan Sönmez 7 Sep 22, 2022
insta: a snapshot testing library for Rust

insta: a snapshot testing library for Rust Introduction Snapshots tests (also sometimes called approval tests) are tests that assert values against a

Armin Ronacher 1.4k Jan 1, 2023
`mutatis` is a library for writing custom, structure-aware test-case mutators for fuzzers in Rust.

mutatis Easily create custom, structure-aware mutators for fuzzing. Repository | Docs | Guide | Contributing About The most popular fuzzers — includin

Nick Fitzgerald 4 Aug 19, 2024
Simple assertion library for unit testing in python with a fluent API

Simple assertions library for unit testing in Python with a nice fluent API. Supports both Python 2 and 3.

snakedye 19 Sep 10, 2022
A tiny, super simple and portable benchmarking library.

benchmark-simple A tiny benchmarking library for Rust. Trivial to use Works pretty much everywhere, including WebAssembly (WASI, but also in-browser)

Frank Denis 3 Dec 26, 2022
This is a tiny (but delightful!) utility library for exhaustive testing.

Exhaustigen This is a tiny (but delightful!) utility library for exhaustive testing. It is based (directly) on the idea and code in the following blog

Graydon Hoare 34 Dec 14, 2022
A minimalist property-based testing library based on the arbitrary crate.

A minimalist property-based testing library based on the arbitrary crate.

Aleksey Kladov 61 Dec 21, 2022
A structure-aware HTTP fuzzing library

?? FeroxFuzz ?? A structure-aware HTTP fuzzing library ?? Another ferox? why? ?? Chill, it's not another command-line tool, this one's a library! ?? M

epi 141 Dec 27, 2022
An unofficial client library for the fuzz-introspector API.

fuzz-introspector-client An unofficial client library for the fuzz-introspector API. Quickstart Add package as a dependency; cargo add fuzz-introspect

Nathaniel Brough 4 Nov 25, 2023
Handle some lichess.org/tournament load with Rust, while learning Rust

lila-http Take some of the HTTP load away from lila. WIP! Arena tournaments Clients connected to a tournament page request new data about the tourname

Lichess 22 Jan 2, 2023
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022