From 46423006839c1594422e7dade08687a2942f6f69 Mon Sep 17 00:00:00 2001 From: Jesse Ruderman Date: Thu, 28 Jul 2011 21:18:07 -0700 Subject: [PATCH] Make the fuzzer check for obvious errors in the 'rest of the compiler', not just the parser. (Disabled by default because it's slow and messy.) --- src/fuzzer/fuzzer.rs | 71 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs index 0ecd69e1997..254ff7f7951 100644 --- a/src/fuzzer/fuzzer.rs +++ b/src/fuzzer/fuzzer.rs @@ -85,6 +85,9 @@ fn safe_to_steal(e: ast::expr_) -> bool { ast::expr_ret(option::none.) { false } ast::expr_put(option::none.) { false } + ast::expr_ret(_) { false /* lots of code generation issues, such as https://github.com/graydon/rust/issues/770 */ } + ast::expr_fail(_) { false } + _ { true } @@ -149,7 +152,7 @@ fn as_str(f: fn(ioivec::writer) ) -> str { ret w.get_str(); } -fn pp_variants(crate: &ast::crate, codemap: &codemap::codemap, filename: &str) { +fn check_variants_of_ast(crate: &ast::crate, codemap: &codemap::codemap, filename: &str) { let exprs = steal_exprs(crate); let exprsL = ivec::len(exprs); if (exprsL < 100u) { @@ -166,11 +169,64 @@ fn pp_variants(crate: &ast::crate, codemap: &codemap::codemap, filename: &str) { // 1u would be sane here, but the pretty-printer currently has lots of whitespace and paren issues, // and https://github.com/graydon/rust/issues/766 is hilarious. check_roundtrip_convergence(str3, 7u); + //check_whole_compiler(str3); } } } } +// We'd find more bugs if we could take an AST here, but +// - that would find many "false positives" or unimportant bugs +// - that would be tricky, requiring use of tasks or serialization or randomness. +// This seems to find plenty of bugs as it is :) +fn check_whole_compiler(code: &str) { + let filename = "test.rs"; + write_file(filename, code); + let p = std::run::program_output("/Users/jruderman/code/rust/build/stage1/rustc", ["-c", filename]); + //log_err #fmt("Status: %d", p.status); + //log_err "Output: " + p.out; + if p.err != "" { + if contains(p.err, "argument of incompatible type") { + log_err "https://github.com/graydon/rust/issues/769"; + } else if contains(p.err, "Cannot create binary operator with two operands of differing type") { + log_err "https://github.com/graydon/rust/issues/770"; + } else if contains(p.err, "May only branch on boolean predicates!") { + log_err "https://github.com/graydon/rust/issues/770 or https://github.com/graydon/rust/issues/776"; + } else if contains(p.err, "Invalid constantexpr cast!") && contains(code, "!") { + log_err "https://github.com/graydon/rust/issues/777"; + } else if contains(p.err, "Both operands to ICmp instruction are not of the same type!") && contains(code, "!") { + log_err "https://github.com/graydon/rust/issues/777 #issuecomment-1678487"; + } else if contains(p.err, "Ptr must be a pointer to Val type!") && contains(code, "!") { + log_err "https://github.com/graydon/rust/issues/779"; + } else if contains(p.err, "Calling a function with bad signature!") && (contains(code, "iter") || contains(code, "range")) { + log_err "https://github.com/graydon/rust/issues/771 - calling an iter fails"; + } else if contains(p.err, "Calling a function with a bad signature!") && contains(code, "empty") { + log_err "https://github.com/graydon/rust/issues/775 - possibly a modification of run-pass/import-glob-crate.rs"; + } else if contains(p.err, "Invalid type for pointer element!") && contains(code, "put") { + log_err "https://github.com/graydon/rust/issues/773 - put put ()"; + } else if contains(p.err, "pointer being freed was not allocated") && contains(p.out, "Out of stack space, sorry") { + log_err "https://github.com/graydon/rust/issues/768 + https://github.com/graydon/rust/issues/778" + } else { + log_err "Stderr: " + p.err; + fail "Unfamiliar error message"; + } + } else if contains(p.out, "non-exhaustive match failure") && contains(p.out, "alias.rs") { + log_err "https://github.com/graydon/rust/issues/772"; + } else if contains(p.out, "non-exhaustive match failure") && contains(p.out, "trans.rs") && contains(code, "put") { + log_err "https://github.com/graydon/rust/issues/774"; + } else if contains(p.out, "Out of stack space, sorry") { + log_err "Possibly a variant of https://github.com/graydon/rust/issues/768"; + } else if p.status == 256 { + if !contains(p.out, "error:") { + fail "Exited with status 256 without a span-error"; + } + } else if p.status == 11 { + log_err "What is this I don't even"; + } else if p.status != 0 { + fail "Unfamiliar status code"; + } +} + fn parse_and_print(code: &str) -> str { let filename = "tmp.rs"; let codemap = codemap::new_codemap(); @@ -186,7 +242,9 @@ fn content_is_dangerous_to_modify(code: &str) -> bool { let dangerous_patterns = [ "obj", // not safe to steal; https://github.com/graydon/rust/issues/761 "#macro", // not safe to steal things inside of it, because they have a special syntax - " be " // don't want to replace its child with a non-call: "Non-call expression in tail call" + "#", // strange representation of the arguments to #fmt, for example + " be ", // don't want to replace its child with a non-call: "Non-call expression in tail call" + "@" // hangs when compiling: https://github.com/graydon/rust/issues/768 ]; for p: str in dangerous_patterns { if contains(code, p) { ret true; } } @@ -277,18 +335,18 @@ fn check_convergence(files: &str[]) { } } -fn check_convergence_of_variants(files: &str[]) { +fn check_variants(files: &str[]) { for file in files { if !file_is_confusing(file) { let s = read_whole_file(file); if content_is_dangerous_to_modify(s) || content_is_confusing(s) { cont; } - log_err "check_convergence_of_variants: " + file; + log_err "check_variants: " + file; let codemap = codemap::new_codemap(); let crate = parser::parse_crate_from_source_str(file, s, ~[], codemap); log_err as_str(bind pprust::print_crate(codemap, crate, file, ioivec::string_reader(s), _, pprust::no_ann())); - pp_variants(*crate, codemap, file); + check_variants_of_ast(*crate, codemap, file); } } } @@ -303,7 +361,8 @@ fn main(args: vec[str]) { find_rust_files(files, root); check_convergence(files); - check_convergence_of_variants(files); + check_variants(files); + log_err "Fuzzer done"; } // Local Variables: