Pieces of a fuzzer, WIP

This commit is contained in:
Jesse Ruderman 2011-07-08 02:16:46 -07:00 committed by Brian Anderson
parent 6d3513eaee
commit e91f8b5db2
3 changed files with 182 additions and 42 deletions

38
src/fuzzer/ast_match.rs Normal file
View File

@ -0,0 +1,38 @@
use std;
import std::ivec;
fn ivec_equal[T](&T[] v, &T[] u, fn (&T, &T) -> bool element_equality_test) -> bool {
auto Lv = ivec::len(v);
if (Lv != ivec::len(u)) {
ret false;
}
auto i = 0u;
while (i < Lv) {
if (!element_equality_test(v.(i), u.(i))) {
ret false;
}
i += 1u;
}
ret true;
}
fn builtin_equal[T](&T a, &T b) -> bool {
ret a == b;
}
fn main() {
// These pass
assert builtin_equal(5, 5);
assert !builtin_equal(5, 4);
// This passes
assert !ivec_equal(~[5, 5], ~[5], builtin_equal);
// These crash
// https://github.com/graydon/rust/issues/633
assert !ivec_equal(~[5, 5], ~[5, 4], builtin_equal);
assert !ivec_equal(~[5, 5], ~[4, 5], builtin_equal);
assert ivec_equal(~[5, 5], ~[5, 5], builtin_equal);
log_err "Pass";
}

View File

@ -1,3 +1,6 @@
use std;
use rustc;
import std::fs;
import std::getopts;
import std::getopts::optopt;
@ -5,56 +8,57 @@
import std::getopts::opt_str;
import std::io;
import std::vec;
import std::ivec;
import std::str;
type src_gen = iter() -> str;
import rustc::back::link;
import rustc::syntax::ast;
import driver = rustc::driver::rustc; // see https://github.com/graydon/rust/issues/624
import rustc::driver::session;
iter dir_src_gen(str dir) -> str {
}
fn usage(str binary) {
io::stdout().write_line("usage");
}
type session = rec(str srcdir);
fn make_session(vec[str] args) -> session {
// Directory of rust source files to use as input
auto opt_src = "src";
auto binary = vec::shift[str](args);
auto opts = [optopt(opt_src)];
auto match;
alt (getopts::getopts(args, opts)) {
case (getopts::failure(?f)) {
log_err #fmt("error: %s", getopts::fail_str(f));
fail;
fn find_rust_files(&mutable str[] files, str root) {
for (str filename in fs::list_dir(root)) {
if (str::ends_with(filename, ".rs")) {
files += ~[filename];
}
case (getopts::success(?m)) {
match = m;
}
};
if (!opt_present(match, opt_src)) {
usage(binary);
fail;
}
auto srcdir = opt_str(match, opt_src);
ret rec(srcdir = srcdir);
}
fn log_session(session sess) {
log #fmt("srcdir: %s", sess.srcdir);
}
fn run_session(session sess) {
}
fn main(vec[str] args) {
auto sess = make_session(args);
log_session(sess);
run_session(sess);
auto files = ~[];
auto root = "/Users/jruderman/code/rust/src/lib/"; // XXX
find_rust_files(files, root); // not using driver::time here because that currently screws with passing-a-mutable-array
auto binary = vec::shift[str](args);
auto binary_dir = fs::dirname(binary);
let @session::options sopts =
@rec(library=false,
static=false,
optimize=0u,
debuginfo=false,
verify=true,
run_typestate=true,
save_temps=false,
stats=false,
time_passes=false,
time_llvm_passes=false,
output_type=link::output_type_bitcode,
library_search_paths=[binary_dir + "/lib"],
sysroot=driver::get_default_sysroot(binary),
cfg=~[],
test=false);
let session::session sess = driver::build_session(sopts);
log_err ivec::len(files);
for (str file in files) {
log_err file;
// Can't use parse_input here because of https://github.com/graydon/rust/issues/632 :(
//auto crate = driver::parse_input(sess, ~[], file);
//let @ast::crate crate = driver::time(true, "parsing " + file, bind driver::parse_input(sess, ~[], file));
}
}
// Local Variables:

98
src/fuzzer/ivec_fuzz.rs Normal file
View File

@ -0,0 +1,98 @@
/*
Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
two functions, "return all edits" and "return a random edit" <-- leaning toward this model
or
two functions, "return the number of possible edits" and "return edit #n"
It would be nice if this could be data-driven, so the two functions could share information:
type vec_modifier = rec(fn (&int[] v, uint i) -> int[] fun, uint lo, uint di);
const vec_modifier[] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
https://github.com/graydon/rust/issues/570
vec_edits is not an iter because iters might go away and:
https://github.com/graydon/rust/issues/639
vec_omit and friends are not type-parameterized because:
https://github.com/graydon/rust/issues/640
*/
use std;
import std::ivec;
import std::ivec::slice;
import std::ivec::len;
import std::int;
//fn vec_reverse(&int[] v) -> int[] { ... }
fn vec_omit (&int[] v, uint i) -> int[] { slice(v, 0u, i) + slice(v, i+1u, len(v)) }
fn vec_dup (&int[] v, uint i) -> int[] { slice(v, 0u, i) + ~[v.(i)] + slice(v, i, len(v)) }
fn vec_swadj (&int[] v, uint i) -> int[] { slice(v, 0u, i) + ~[v.(i+1u), v.(i)] + slice(v, i+2u, len(v)) }
fn vec_prefix (&int[] v, uint i) -> int[] { slice(v, 0u, i) }
fn vec_suffix (&int[] v, uint i) -> int[] { slice(v, i, len(v)) }
fn vec_poke (&int[] v, uint i, int x) -> int[] { slice(v, 0u, i) + ~[x] + slice(v, i+1u, len(v)) }
fn vec_insert (&int[] v, uint i, int x) -> int[] { slice(v, 0u, i) + ~[x] + slice(v, i, len(v)) }
// Iterates over 0...length, skipping the specified number on each side.
iter ix(uint skip_low, uint skip_high, uint length) -> uint { let uint i = skip_low; while (i + skip_high <= length) { put i; i += 1u; } }
// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
fn vec_edits(&int[] v, &int[] xs) -> int[][] {
let int[][] edits = ~[];
let uint Lv = len(v);
if (Lv != 1u) { edits += ~[~[]]; } // When Lv == 1u, this is redundant with omit
//if (Lv >= 3u) { edits += ~[vec_reverse(v)]; }
for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_omit (v, i)]; }
for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_dup (v, i)]; }
for each (uint i in ix(0u, 2u, Lv)) { edits += ~[vec_swadj (v, i)]; }
for each (uint i in ix(1u, 2u, Lv)) { edits += ~[vec_prefix(v, i)]; }
for each (uint i in ix(2u, 1u, Lv)) { edits += ~[vec_suffix(v, i)]; }
for each (uint j in ix(0u, 1u, len(xs))) {
for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_poke (v, i, xs.(j))]; }
for each (uint i in ix(0u, 0u, Lv)) { edits += ~[vec_insert(v, i, xs.(j))]; }
}
edits
}
// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
fn vec_to_str(&int[] v) -> str {
auto i = 0u;
auto s = "[";
while (i < len(v)) {
s += int::str(v.(i));
if (i + 1u < len(v)) {
s += ", "
}
i += 1u;
}
ret s + "]";
}
fn show_edits(&int[] a, &int[] xs) {
log_err "=== Edits of " + vec_to_str(a) + " ===";
auto b = vec_edits(a, xs);
for each (uint i in ix(0u, 1u, len(b))) {
log_err vec_to_str(b.(i));
}
}
fn demo_edits() {
auto xs = ~[7, 8];
show_edits(~[], xs);
show_edits(~[1], xs);
show_edits(~[1,2], xs);
show_edits(~[1,2,3], xs);
show_edits(~[1,2,3,4], xs);
}
fn main() {
demo_edits();
}