Skip to content

Getting Started

Warning

Documentation is still a work-in-progress!

RustSmith at it's core is simply an executable that will run and generate programs based on command-line arguments passed in. Follow the steps below to start the generation of programs!

Getting the executable

To download and install RustSmith, the recommended method is to simply download the "RustSmith Executable" from the latest release from the "Releases" panel on the right.

RustSmith can then be invoked as below:

./rustsmith --help

Docker

Docker can also be used in the following way using the latest docker image:

docker run --rm ghcr.io/rustsmith/rustsmith --help

Running RustSmith using the JAR File

Alternatively, the JAR file in the releases can be downloaded and used instead. RustSmith would then be invoked as:

java -jar RustSmith-1.0-SNAPSHOT-all.jar

Building from Source

To build RustSmith from source, an installation of Java 15 is required. More information for installing OpenJDK 15 can be found on the OpenJDK Website.

Building and executing RustSmith can then be done as follows:

git clone git@github.com:rustsmith/rustsmith.git
cd rustsmith
./gradlew build

This will create both the standalone executable under ./run/rustsmith and the packaged JAR file under ./build/libs/RustSmith-1.0-SNAPSHOT-all.jar which can then be executed as described above.

Basic Usage of Rustsmith

Run command

RustSmith is just a command line tool that can generate you valid Rust programs randomly.

The most basic usage of rustsmith would be the following command:

./rustsmith -n 1

Folder structure of output

Which, when ran, should set up a folder structure wherever you ran the program in the following way:

./outRust
|-- file0
|   |-- file0.rs
|   |-- file0.txt

Depending on the number of files you want to generate (specified by the -n flag) the number of programs will increase.

Within each folder there are 2 main files: fileX.rs and fileX.txt.

  • file0.rs is the valid and automatically generated rust file!
  • file0.txt is the list of command line arguments that should be passed into the executable

Example file output

file0.rs will look something like the following:

Generated Rust Program snippet
#![allow(warnings, unused, unconditional_panic)]
use std::env;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
const CONST1: f32 = 0.2419321f32;
const CONST2: i128 = 131415789711622847644195956159839136052i128;
const CONST3: u8 = 173u8;
const CONST4: f32 = 0.32691818f32;
const CONST5: bool = false;
const CONST6: u32 = 2727919348u32;
const CONST7: u32 = 1813123347u32;
const CONST8: i128 = 53614034395947885105180317431878184857i128;
const CONST9: f32 = 0.41204387f32;
const CONST10: u16 = 887u16;
macro_rules! reconditioned_mod{
    ($a:expr,$b:expr, $zero: expr) => {
        {
            let denominator = $b;
            if (denominator != $zero) {($a % denominator)} else {$zero}
        }
    }
}
macro_rules! reconditioned_div{
    ($a:expr,$b:expr, $zero: expr) => {
        {
            let denominator = $b;
            if (denominator != $zero) {($a / denominator)} else {$zero}
        }
    }
}
macro_rules! reconditioned_access{
    ($a:expr,$b:expr) => {{
        let arrLength = $a.len();
        let index = $b;
        $a[if (index < arrLength) { index } else { 0 }]
    }};
}
#[derive(Debug)]
struct Struct2 {
var6: Option<u32>,
var7: f32,
var8: i32,
var9: u8,
}

impl Struct2 {
#[inline(never)]
fn fun7(&self, var41: f64, var42: Option<u16>, var43: i128, var44: Option<Struct2>, hasher: &mut DefaultHasher) -> Struct3 {
44i8;
();
138654581908947122899287364284989451186i128;
let var45: u16 = 34348u16;
Struct2 {var6: None::<u32>, var7: 0.7830445f32, var8: 899283879i32, var9: 227u8,};
let mut var46: i128 = 74743375548520924870409283084422405671i128;
var46 = 28713462321172602643073431590454312989i128;
1517252645i32;
735464689u32;
0.7460238032098697f64;
format!("{:?}", var41).hash(hasher);
format!("{:?}", var44).hash(hasher);
vec![0.8649663464953213f64,0.05053026936017313f64,0.8529252322989213f64,0.0075586315580329355f64];
();
........

This is your first randomly generated, valid, Rust program!

Testing the generated rust file

This can then be compiled against rustc and run with the command line arguments:

> rustc file0.rs

> ./file0.rs 0.78968924 159490765721744842190015396263998969651 104585524602189803966499020697899014819 RRDoKHc 4442417947899502423 8901 true -1624219412 89 0.16808917087337594 -4799608715056474785 # input from 1.txt

Program Seed: 8760012246522298462
7619823349681210740

The output produces the following 2 lines of output always:

  • Program Seed: this is a seed used throughout the generation process for all random selections taken in the program. The idea is you can reproduce the same program through rustsmith by using the seed printed here (through the -s <SEED> option!)
  • Hashed output: this number is the hash of all variables in scope by the end of the program along with any other variables that were randomly chosen in the generation of the program to be added to the hasher. This is the main number to compare when running differential testing across different optimization levels and compilers.

Usage options in RustSmith

Usage: rustsmith [OPTIONS]

Options:
  -n, -count INT    No. of files to generate
  -p, -print        Print out program only
  -f, -fail-fast    Use fail fast approach
  -s, -seed INT     Optional Seed
  --directory TEXT  Directory to save files
  -h, --help        Show this message and exit