• Stars
    star
    335
  • Rank 125,904 (Top 3 %)
  • Language
    Rust
  • License
    Other
  • Created over 7 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

symbolic execution engine for Rust

Seer: Symbolic Execution Engine for Rust

Build Status crates.io

Seer is a fork of miri that adds support for symbolic execution, using z3 as a solver backend.

Given a program written in Rust, Seer attempts to exhaustively enumerate the possible execution paths through it. To achieve this, Seer represents the program's input in a symbolic form, maintaining a set of constraints on it. When Seer reaches a branch point in the program, it invokes its solver backend to compute which continuations are possible given the current constraints. The possible continuations are then enqueued for exploration, augmented with the respective new constraints learned from the branch condition.

Seer considers any bytes read in through ::std::io::stdin() as symbolic input. This means that once Seer finds an interesting input for your program, you can easily compile your program with plain rustc and run it on that input.

example: decode base64 given only an encoder

[source code]

Suppose we are given a base64 encoder function:

fn base64_encode(input: &[u8]) -> String { ... }

and suppose that we would like to decode a base64-encoded string, but we don't want to bother to actually write the corresponding base64_decode() function. We can write the following program and ask Seer to execute it:

fn main() {
    let value_to_decode = "aGVsbG8gd29ybGQh";
    let mut data: Vec<u8> = vec![0; (value_to_decode.len() + 3) / 4 * 3];
    std::io::stdin().read_exact(&mut data[..]).unwrap();

    let result = base64_encode(&data[..]);

    if result.starts_with(value_to_decode) {
        panic!("we found it!");
    }
}

Seer will then attempt to find input values that can trigger the panic. It succeeds after a few seconds:

$ cargo run --bin seer -- example/standalone/base64.rs
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/seer example/standalone/base64.rs`
ExecutionComplete { input: [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33], result: Err(Panic) }
as string: Ok("hello world!")
hit an error. halting

There is our answer! Our string decodes as "hello world!"

using the helper crate

The helper crate provides some extra conveniences. The input that triggers a panic can be split by variable and types that implement Debug are printed in their debug representation instead of using the underlying bytes:

#[macro_use]
extern crate seer_helper;
seer_helper_init!();

#[derive(Debug)]
struct MyStruct {
    a: u32,
    b: u64,
}

fn main() {
    let mut t = MyStruct { a: 0, b: 0 };
    seer_helper::mksym(&mut t);
    if t.a == 123 && t.b == 321 {
        panic!();
    }
}

For the formatting to work, it is necessary to build MIR for the standard library, so we will use Xargo:

$ RUSTFLAGS="-Z always-encode-mir" xargo seer
...
ExecutionComplete { input: [stdin: [], t: "MyStruct { a: 123, b: 321 }"], result: Err(NoMirFor("std::sys::unix::fast_thread_local::register_dtor::::__cxa_thread_atexit_impl")) }
hit an error. halting

The full example crate can be found here.

limitations

Seer is currently in the proof-of-concept stage and therefore has lots of unimplemented!() holes in it. In particular, it does not yet handle:

  • allocations with size depending on symbolic input
  • pointer-to-pointer with symbolic offset
  • overflow checking on symbolic arithmetic
  • ... lots of other things that you will quickly discover if you try to use it!

long-term vision

The goal is that Seer will help in two primary use cases:

  • in exploratory tests, as a complementary approach to fuzzing
  • in program verification, to exhaustively check that error states cannot be reached

More Repositories

1

gj

event loop and promises in Rust
Rust
108
star
2

fuzz-rustc

setup for fuzzing the Rust compiler
Rust
55
star
3

lean4-maze

maze game encoded in Lean 4 syntax
Lean
35
star
4

animate-lean-proofs

tool for turning Lean proofs into Blender animations
Lean
33
star
5

acronymy

user-editable, acronym-only dictionary
Rust
22
star
6

compfiles

Catalog Of Math Problems Formalized In Lean
Lean
22
star
7

acronymy-assistant

interactive backronym composition tool
AGS Script
22
star
8

sandstorm-rawapi-example-rust

Example Sandstorm app using only the raw Cap'n Proto API, written in Rust.
Rust
22
star
9

gitlab-sandstorm

GitLab as a Sandstorm app
Cap'n Proto
21
star
10

gjio

asynchronous I/O in Rust
Rust
14
star
11

wordpress-sandstorm

wordpress as a sandstorm app
PHP
13
star
12

duoludo

a game whose purpose is games
JavaScript
11
star
13

capnp-zmq-rust

Rust library for using ZeroMQ with Cap'n Proto serialization
Rust
11
star
14

sandstorm-rust

Sandstorm Cap'n Proto interfaces, packaged for Rust
Cap'n Proto
10
star
15

acronymy-workers

user-editable, acronym-only dictionary
JavaScript
9
star
16

math-puzzles-in-lean

math puzzles from various sources, formalized in Lean
Lean
9
star
17

zillions

toy chat server spec and example implementations
Rust
8
star
18

gitweb-sandstorm

git repo as Sandstorm app
Ruby
6
star
19

nicer-trees

JavaScript
5
star
20

Chess.lean

Chess in Lean 4
Lean
3
star
21

fuzz-capnproto

C++
2
star
22

capnp-gj

Rust
2
star
23

config

configuration files
1
star
24

lepidopter

game for ludum dare 24
JavaScript
1
star
25

asciiworld

game for ludum dare 23
JavaScript
1
star
26

aione

game for ludum dare 22
Standard ML
1
star
27

lobsters-sandstorm

Sandstorm port of lobste.rs
Cap'n Proto
1
star