6 releases (breaking)

0.5.0 Jul 17, 2023
0.4.0 Apr 6, 2023
0.3.1 Mar 24, 2023
0.2.0 Mar 13, 2023
0.1.0 Mar 12, 2023

#8 in #grammar-based

29 downloads per month

MIT license

40KB
574 lines

tree-splicer

tree-splicer is a simple grammar-based test case generator. It parses a number of input files using tree-sitter grammars, and produces new files formed by splicing together their ASTs.

tree-splicer generates test cases in the tree-crasher fuzzer and in icemaker, though it can also be used as a standalone tool.

tree-sitter grammars are resistant to syntax errors. Therefore, tree-splicer can even mutate syntactically-invalid inputs! You can also use tree-splicer with an incomplete grammar.

Example

Given this simple Rust program:

use std::env;

fn even(x: usize) -> bool {
    if x % 2 == 0 {
        return true;
    } else {
        return false;
    }
}

fn main() -> () {
    let argc = env::args().len();
    println!("Hello, world!");
    if even(argc) {
        println!("Even!");
    } else {
        println!("Odd!");
    }
    return ();
}

Here are a few candidates created by tree-splicer-rust:

use even::env;

fn even() -> bool {
    if even(argc) {
        println!("Even!");
    } else {
        println!("Odd!");
    }
}

fn std() -> () {
    return true;
}
use args::env;

fn argc(main: usize) -> bool {
    return true;
}

fn even(x: usize) -> bool {
    if x % 2 == 0 {
        return true;
    } else {
        return false;
    }
}
use std::env;

fn x(x: usize) -> bool {
    return true;
}

fn x(x: usize) -> () {
    return false;
}

Supported languages

Languages are easy to add, see PR #3 for an example.

  • JavaScript
  • Rust
  • TypeScript

Bugs found

boa

#2717 #2718 #2719

clang

#61635 #61666 #61667 #61746 #61747

deno

#18338

rustc

#109066 #109071 #109072 #109078 #109079 #109090 #109129 #109141 #109143 #109144 #109146 #109147 #109148 #109152 #109178 #109188 #109191 #109204 #109232 #109239 #109296 #109297 #109298 #109299 #109300 #109304 #109305

rustfmt

#5716 #5738 #5739

Installation

Pre-compiled binaries

Pre-compiled binaries are available on the releases page.

Build from source

To install from source, you'll need to install Rust and Cargo. Follow the instructions on the Rust installation page.

From a release on crates.io

You can build a released version from crates.io. To install the latest release of tree-splicer for the language <LANG>, run:

cargo install tree-splicer-<LANG>

This will automatically download the source from crates.io, build it, and install it in Cargo's global binary directory (~/.cargo/bin/ by default).

From the latest unreleased version on Github

To build and install the very latest unreleased version, run:

cargo install --git https://github.com/langston-barrett/tree-splicer.git tree-splicer-LANG

Uninstalling

To uninstall, run cargo uninstall tree-splicer-<LANG>.

Build

To build from source, you'll need to install Rust and Cargo. Follow the instructions on the Rust installation page. Then, get the source:

git clone https://github.com/langston-barrett/tree-splicer
cd tree-splicer

Finally, build everything:

cargo build --release

You can find binaries in target/release. Run tests with cargo test.

Dependencies

~12–25MB
~395K SLoC