From 8ff154cf142b77b8aed620b4b61003a5372a2105 Mon Sep 17 00:00:00 2001 From: BeneficialCode <3123132899@qq.com> Date: Mon, 22 May 2023 06:39:18 -0400 Subject: [PATCH 1/4] tweaked memory share config bug --- .vscode/launch.json | 176 +++++++++++++++++++++++++++++++ forksrv/src/lib.rs | 3 +- test | Bin 0 -> 100392 bytes test.c | 2 + test_cases/grammar_regex_root.py | 2 +- 5 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 .vscode/launch.json create mode 100755 test diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..464eaf7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,176 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in library 'forksrv'", + "cargo": { + "args": [ + "test", + "--no-run", + "--lib", + "--package=forksrv" + ], + "filter": { + "name": "forksrv", + "kind": "lib" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in library 'grammartec'", + "cargo": { + "args": [ + "test", + "--no-run", + "--lib", + "--package=grammartec" + ], + "filter": { + "name": "grammartec", + "kind": "lib" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in library 'regex_mutator'", + "cargo": { + "args": [ + "test", + "--no-run", + "--lib", + "--package=regex_mutator" + ], + "filter": { + "name": "regex_mutator", + "kind": "lib" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'fuzzer'", + "cargo": { + "args": [ + "build", + "--bin=fuzzer", + "--package=fuzzer" + ], + "filter": { + "name": "fuzzer", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'fuzzer'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=fuzzer", + "--package=fuzzer" + ], + "filter": { + "name": "fuzzer", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'generator'", + "cargo": { + "args": [ + "build", + "--bin=generator", + "--package=fuzzer" + ], + "filter": { + "name": "generator", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'generator'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=generator", + "--package=fuzzer" + ], + "filter": { + "name": "generator", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'mutator'", + "cargo": { + "args": [ + "build", + "--bin=mutator", + "--package=fuzzer" + ], + "filter": { + "name": "mutator", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'mutator'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=mutator", + "--package=fuzzer" + ], + "filter": { + "name": "mutator", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/forksrv/src/lib.rs b/forksrv/src/lib.rs index f1d2289..257b491 100644 --- a/forksrv/src/lib.rs +++ b/forksrv/src/lib.rs @@ -228,7 +228,8 @@ impl ForkServer { "shmclt {:?}", CString::from_raw(strerror(errno())) ); - (shm_id, trace_bits.cast::<[u8; 65536]>()) + let ptr: *mut u8 = trace_bits.cast(); + (shm_id, std::slice::from_raw_parts_mut(ptr,bitmap_size)) } } } diff --git a/test b/test new file mode 100755 index 0000000000000000000000000000000000000000..0fd94a565e3f313084ca0a13f447121f2d5517f0 GIT binary patch literal 100392 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 atf%|0VEf}x7*+rE4`|A5feL}F_5T1 Date: Wed, 24 May 2023 22:44:57 -0400 Subject: [PATCH 2/4] optimize the RegExp generate strategy --- Cargo.lock | 8 ++++---- config.ron | 2 +- fuzzer/src/fuzzer.rs | 11 ++++++++++- fuzzer/src/main.rs | 13 ++++++++++++ fuzzer/src/state.rs | 38 +++++++++++++++++++++++++++++++++++- grammartec/src/chunkstore.rs | 19 ++++++++++++++++++ grammartec/src/context.rs | 6 ++++++ grammartec/src/tree.rs | 9 +++++++++ 8 files changed, 99 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8333b71..9e0215c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,7 +255,7 @@ dependencies = [ [[package]] name = "forksrv" -version = "0.3.0" +version = "0.3.1" dependencies = [ "byteorder", "libc", @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "fuzzer" -version = "0.3.0" +version = "0.3.1" dependencies = [ "chrono", "clap", @@ -295,7 +295,7 @@ dependencies = [ [[package]] name = "grammartec" -version = "0.3.0" +version = "0.3.1" dependencies = [ "lazy_static", "loaded_dice", @@ -758,7 +758,7 @@ checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "regex_mutator" -version = "0.3.0" +version = "0.3.1" dependencies = [ "regex-syntax 0.6.29", ] diff --git a/config.ron b/config.ron index 0e122f1..76dc7a7 100644 --- a/config.ron +++ b/config.ron @@ -25,4 +25,4 @@ Config( max_tree_size: 1000, //see state.rs generate random number_of_deterministic_mutations: 1, //see main.rs process_input -) +) \ No newline at end of file diff --git a/fuzzer/src/fuzzer.rs b/fuzzer/src/fuzzer.rs index 7ad1ad7..db60b8f 100644 --- a/fuzzer/src/fuzzer.rs +++ b/fuzzer/src/fuzzer.rs @@ -67,6 +67,7 @@ pub struct Fuzzer { pub asan_found_by_det: u64, pub asan_found_by_det_afl: u64, pub asan_found_by_gen: u64, + pub total_found_path: usize, work_dir: String, } @@ -112,6 +113,7 @@ impl Fuzzer { asan_found_by_det: 0, asan_found_by_det_afl: 0, asan_found_by_gen: 0, + total_found_path: 0, work_dir, } } @@ -175,24 +177,31 @@ impl Fuzzer { match exec_reason { ExecutionReason::Havoc => { self.bits_found_by_havoc += 1; /*print!("Havoc+")*/ + self.total_found_path += 1; } ExecutionReason::HavocRec => { self.bits_found_by_havoc_rec += 1; /*print!("HavocRec+")*/ + self.total_found_path += 1; } ExecutionReason::Min => { self.bits_found_by_min += 1; /*print!("Min+")*/ + self.total_found_path += 1; } ExecutionReason::MinRec => { self.bits_found_by_min_rec += 1; /*print!("MinRec+")*/ + self.total_found_path += 1; } ExecutionReason::Splice => { self.bits_found_by_splice += 1; /*print!("Splice+")*/ + self.total_found_path += 1; } ExecutionReason::Det => { self.bits_found_by_det += 1; /*print!("Det+")*/ + self.total_found_path += 1; } ExecutionReason::Gen => { self.bits_found_by_gen += 1; /*print!("Gen+")*/ + self.total_found_path += 1; } } } @@ -331,7 +340,7 @@ impl Fuzzer { let run_bitmap = self.forksrv.get_shared(); for (i, &v) in old_bitmap.iter().enumerate() { if run_bitmap[i] != v { - println!("found fucky bit {i}"); + // println!("found fucky bit {i}"); } } new_bits.retain(|&i| run_bitmap[i] != 0); diff --git a/fuzzer/src/main.rs b/fuzzer/src/main.rs index 93009bd..48edc5c 100644 --- a/fuzzer/src/main.rs +++ b/fuzzer/src/main.rs @@ -359,6 +359,7 @@ fn main() { let bits_found_by_splice; let bits_found_by_havoc; let bits_found_by_havoc_rec; + let total_found_path; let last_found_asan; let last_found_sig; let last_timeout; @@ -376,6 +377,14 @@ fn main() { bits_found_by_splice = shared_state.bits_found_by_splice; bits_found_by_havoc = shared_state.bits_found_by_havoc; bits_found_by_havoc_rec = shared_state.bits_found_by_havoc_rec; + total_found_path = bits_found_by_det + + bits_found_by_gen + + bits_found_by_havoc + + bits_found_by_havoc + + bits_found_by_havoc_rec + + bits_found_by_min + + bits_found_by_min_rec + + bits_found_by_splice; last_found_asan = shared_state.last_found_asan.clone(); last_found_sig = shared_state.last_found_sig.clone(); last_timeout = shared_state.last_timeout.clone(); @@ -481,6 +490,10 @@ fn main() { "New paths found by Havoc Rec: {} ", bits_found_by_havoc_rec ); + println!( + "Total paths found: {} ", + total_found_path + ); println!("------------------------------------------------------ "); //println!("Global bitmap: {:?}", global_state.lock().expect("RAND_1887203473").bitmaps.get(&false).expect("RAND_1887203473")); thread::sleep(time::Duration::from_secs(1)); diff --git a/fuzzer/src/state.rs b/fuzzer/src/state.rs index e3c9eee..9165d94 100644 --- a/fuzzer/src/state.rs +++ b/fuzzer/src/state.rs @@ -19,10 +19,12 @@ use std::fs::File; use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Instant; +use std::io::ErrorKind; use grammartec::chunkstore::ChunkStoreWrapper; use grammartec::context::Context; use grammartec::mutator::Mutator; +use grammartec::rule::{RegExpRule, Rule}; use grammartec::tree::{TreeLike, TreeMutation}; use config::Config; @@ -205,7 +207,41 @@ impl FuzzingState { pub fn generate_random(&mut self, nt: &str) -> Result<(), SubprocessError> { let nonterm = self.ctx.nt_id(nt); let len = self.ctx.get_random_len_for_nt(&nonterm); - let tree = self.ctx.generate_tree_from_nt(nonterm, len); + let mut tree = self.ctx.generate_tree_from_nt(nonterm, len); + let chunk = self.cks.chunkstore.read().expect("read error").get_chunk(); + let mut code: Vec = tree.unparse_to_vec(&self.ctx); + let chunk = match chunk { + Ok(chunk) => chunk, + Err(error) => match error.kind() { + ErrorKind::NotFound => { + code.clone() + }, + e => panic!("Other error: {:?}",e) + } + }; + let rid = self.ctx.get_random_rule_for_nt(nonterm, len); + let rule = self.ctx.get_rule(rid); + match rule { + Rule::Plain(..) | Rule::Script(..) => { + + } + Rule::RegExp(RegExpRule { .. }) => { + let mut i: usize= 0; + let total_path = self.fuzzer.total_found_path; + if code != chunk && total_path > 1{ + while i < total_path - 1 { + let len = chunk.len(); + if len == 0 { + break; + } + code[i] = chunk[i]; + i+=1; + } + tree = self.ctx.generate_tree_from_vec(&mut code, nonterm, len); + } + } + } + self.fuzzer .run_on_with_dedup(&tree, ExecutionReason::Gen, &self.ctx)?; Ok(()) diff --git a/grammartec/src/chunkstore.rs b/grammartec/src/chunkstore.rs index c959e7e..51ce8ab 100644 --- a/grammartec/src/chunkstore.rs +++ b/grammartec/src/chunkstore.rs @@ -14,12 +14,14 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use rand::Rng; use rand::seq::IteratorRandom; use rand::thread_rng; use std::collections::HashMap; use std::collections::HashSet; use std::fs::File; use std::io::Write; +use std::io::Read; use std::sync::atomic::AtomicBool; use std::sync::RwLock; @@ -114,6 +116,23 @@ impl ChunkStore { pub fn trees(&self) -> usize { self.trees.len() } + + pub fn get_chunk(&self) -> Result,std::io::Error> { + let mut buffer :Vec = Vec::new(); + if self.number_of_chunks < 2 { + return Ok(buffer) + } + let mut rng = rand::thread_rng(); + let high = self.number_of_chunks as usize; + let id = rng.gen_range(0..high); + let path = format!( + "{}/outputs/chunks/chunk_{:09}", + self.work_dir,id + ); + let mut file = File::open(path)?; + file.read_to_end(&mut buffer)?; + Ok(buffer) + } } #[cfg(test)] diff --git a/grammartec/src/context.rs b/grammartec/src/context.rs index 8867349..414a9e1 100644 --- a/grammartec/src/context.rs +++ b/grammartec/src/context.rs @@ -340,6 +340,12 @@ impl Context { tree.generate_from_rule(r, len, self); tree } + + pub fn generate_tree_from_vec(&self,vec:&mut Vec,nt: NTermID, max_len: usize) -> Tree { + let mut tree = Tree::from_rule_vec(vec![], self); + tree.generate_from_vec(vec,self.get_random_rule_for_nt(nt, max_len)); + tree + } } impl Default for Context { diff --git a/grammartec/src/tree.rs b/grammartec/src/tree.rs index 8501ee5..62e9baa 100644 --- a/grammartec/src/tree.rs +++ b/grammartec/src/tree.rs @@ -364,6 +364,15 @@ impl Tree { } } + pub fn generate_from_vec(&mut self,vec:&mut Vec, ruleid: RuleID){ + let rid = RuleIDOrCustom::Custom(ruleid, vec.clone()); + self.truncate(); + self.rules.push(rid); + self.sizes.push(0); + self.paren.push(NodeID::from(0)); + self.sizes[0] = self.rules.len(); + } + #[must_use] pub fn calc_recursions(&self, ctx: &Context) -> Option> { let mut ret = Vec::new(); From 3a5fd837fb773de9f709077a4877b5e43642f21d Mon Sep 17 00:00:00 2001 From: BeneficialCode <3123132899@qq.com> Date: Thu, 25 May 2023 05:59:18 -0400 Subject: [PATCH 3/4] We can support calc the pass rate. --- Cargo.lock | 1 + config.ron | 4 +- forksrv/src/lib.rs | 8 +--- fuzzer/Cargo.toml | 1 + fuzzer/src/fuzzer.rs | 75 +++++++++++++++++++++++++++++++++++--- fuzzer/src/main.rs | 9 ++++- fuzzer/src/shared_state.rs | 2 + 7 files changed, 85 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e0215c..665c794 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,6 +280,7 @@ dependencies = [ "ron", "serde", "serde_json", + "tempfile", ] [[package]] diff --git a/config.ron b/config.ron index 76dc7a7..ff2263a 100644 --- a/config.ron +++ b/config.ron @@ -1,10 +1,10 @@ Config( //You probably want to change the follwoing options //File Paths - path_to_bin_target: "./test", + path_to_bin_target: "/home/luafuzz/Desktop/lua-5.4.6/src/lua", arguments: [ "@@"], //"@@" will be exchanged with the path of a file containing the current input - path_to_grammar: "test_cases/grammar_regex_root.py", + path_to_grammar: "grammars/lua.py", path_to_workdir: "/tmp/workdir", number_of_threads: 1, diff --git a/forksrv/src/lib.rs b/forksrv/src/lib.rs index 257b491..9b3096f 100644 --- a/forksrv/src/lib.rs +++ b/forksrv/src/lib.rs @@ -242,18 +242,14 @@ mod tests { let hide_output = false; let timeout_in_millis = 200; let bitmap_size = 1 << 16; - let target = "../test".to_string(); + let target = "/home/luafuzz/Desktop/lua-5.4.6/src/lua".to_string(); let args = vec![]; let mut fork = ForkServer::new(target, args, hide_output, timeout_in_millis, bitmap_size); assert!(fork.get_shared()[1..].iter().all(|v| *v == 0)); assert_eq!( - fork.run(b"deadbeeg").unwrap(), + fork.run(b"print(\"Hello World!\")").unwrap(), exitreason::ExitReason::Normal(0) ); - assert_eq!( - fork.run(b"deadbeef").unwrap(), - exitreason::ExitReason::Signaled(6) - ); assert!(fork.get_shared()[1..].iter().any(|v| *v != 0)); } } diff --git a/fuzzer/Cargo.toml b/fuzzer/Cargo.toml index 29a29c3..5c1b655 100644 --- a/fuzzer/Cargo.toml +++ b/fuzzer/Cargo.toml @@ -19,6 +19,7 @@ serde_json = "1.0" ron = "0.8" clap = "4.0" pyo3 = "0.18" +tempfile = "3.1" [[bin]] name = "fuzzer" diff --git a/fuzzer/src/fuzzer.rs b/fuzzer/src/fuzzer.rs index db60b8f..80fea16 100644 --- a/fuzzer/src/fuzzer.rs +++ b/fuzzer/src/fuzzer.rs @@ -22,6 +22,10 @@ use std::io::Write; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Instant; +use std::process::{Command}; +use std::path::Path; +use std::fs; + use chrono::Local; use forksrv::exitreason::ExitReason; @@ -31,6 +35,9 @@ use grammartec::context::Context; use grammartec::tree::TreeLike; use shared_state::GlobalSharedState; +extern crate tempfile; + + #[derive(Debug, Clone, Copy)] pub enum ExecutionReason { Havoc, @@ -49,6 +56,8 @@ pub struct Fuzzer { pub global_state: Arc>, pub target_path: String, pub target_args: Vec, + pub total_testcast_count: u64, + pub pass_rate: f64, pub execution_count: u64, pub average_executions_per_sec: f32, pub bits_found_by_havoc: u64, @@ -95,6 +104,8 @@ impl Fuzzer { global_state, target_path: path, target_args: args, + total_testcast_count: 0, + pass_rate: 0.0, execution_count: 0, average_executions_per_sec: 0.0, bits_found_by_havoc: 0, @@ -262,18 +273,70 @@ impl Fuzzer { } pub fn exec_raw(&mut self, code: &[u8]) -> Result<(ExitReason, u32), SubprocessError> { - self.execution_count += 1; + let start = Instant::now(); + + let mut path = self.target_path.clone(); + path += "c"; + let mut luac_file = self.work_dir.clone(); + luac_file += "/testcase.luac"; + let test_file = tempfile::NamedTempFile::new().expect("couldn't create temp file"); + let (mut test_file, test_path) = test_file + .keep() + .expect("couldn't persists temp file for input"); - let exitreason = self.forksrv.run(code)?; + let result = test_file.write_all(code); + match result { + Ok(result)=>result, + Err(error) => panic!("Error write file: {:?}",error) + } - let execution_time = start.elapsed().subsec_nanos(); + let args = ["-o",&luac_file,test_path.to_str().unwrap()]; + let command = format!("{} {}",path,args.join(" ")); + Command::new("sh") + .arg("-c") + .arg(command) + .output() + .expect("failed to execute luac"); + + let luac_path = Path::new(&luac_file); + let mut is_exist = 0; + if luac_path.exists() { + is_exist = 1; + if let Err(err) = fs::remove_file(luac_file) { + println!("Error deleting file: {:?}",err); + } + else{ - self.average_executions_per_sec = self.average_executions_per_sec * 0.9 - + ((1.0 / (execution_time as f32)) * 1_000_000_000.0) * 0.1; + } + } + else{ + is_exist = 0; + } + + self.total_testcast_count+=1; - Ok((exitreason, execution_time)) + if is_exist == 1 { + let exitreason = self.forksrv.run(code)?; + self.execution_count += 1; + + let execution_time = start.elapsed().subsec_nanos(); + + self.average_executions_per_sec = self.average_executions_per_sec * 0.9 + + ((1.0 / (execution_time as f32)) * 1_000_000_000.0) * 0.1; + + if self.total_testcast_count != 0 { + self.pass_rate = self.execution_count as f64 / self.total_testcast_count as f64; + } + Ok((exitreason, execution_time)) + } + else { + if self.total_testcast_count != 0 { + self.pass_rate = self.execution_count as f64 / self.total_testcast_count as f64; + } + Ok((ExitReason::Normal(0),0)) + } } fn input_is_known(&mut self, code: &[u8]) -> bool { diff --git a/fuzzer/src/main.rs b/fuzzer/src/main.rs index 48edc5c..8ba2c7a 100644 --- a/fuzzer/src/main.rs +++ b/fuzzer/src/main.rs @@ -169,6 +169,7 @@ fn fuzzing_thread( stats.average_executions_per_sec += state.fuzzer.average_executions_per_sec as u32; stats.average_executions_per_sec -= old_executions_per_sec; old_executions_per_sec = state.fuzzer.average_executions_per_sec as u32; + stats.pass_rate = state.fuzzer.pass_rate; if state.fuzzer.bits_found_by_havoc > 0 { stats.bits_found_by_havoc += state.fuzzer.bits_found_by_havoc; state.fuzzer.bits_found_by_havoc = 0; @@ -365,9 +366,11 @@ fn main() { let last_timeout; let total_found_asan; let total_found_sig; + let pass_rate; { let shared_state = global_state.lock().expect("RAND_597319831"); execution_count = shared_state.execution_count; + pass_rate = shared_state.pass_rate; average_executions_per_sec = shared_state.average_executions_per_sec; queue_len = shared_state.queue.len(); bits_found_by_gen = shared_state.bits_found_by_gen; @@ -491,9 +494,13 @@ fn main() { bits_found_by_havoc_rec ); println!( - "Total paths found: {} ", + "Total paths found: {} ", total_found_path ); + println!( + "Pass rate: {:.2} ", + pass_rate + ); println!("------------------------------------------------------ "); //println!("Global bitmap: {:?}", global_state.lock().expect("RAND_1887203473").bitmaps.get(&false).expect("RAND_1887203473")); thread::sleep(time::Duration::from_secs(1)); diff --git a/fuzzer/src/shared_state.rs b/fuzzer/src/shared_state.rs index 021cd9a..4154579 100644 --- a/fuzzer/src/shared_state.rs +++ b/fuzzer/src/shared_state.rs @@ -22,6 +22,7 @@ pub struct GlobalSharedState { //false for not crashing input. True for crashing inputs pub bitmaps: HashMap>, pub execution_count: u64, + pub pass_rate: f64, pub average_executions_per_sec: u32, pub bits_found_by_havoc: u64, pub bits_found_by_havoc_rec: u64, @@ -56,6 +57,7 @@ impl GlobalSharedState { queue, bitmaps, execution_count: 0, + pass_rate: 0.0, average_executions_per_sec: 0, bits_found_by_havoc: 0, bits_found_by_havoc_rec: 0, From c27fe36c7a04d8204b721d443ea113f5037f43b9 Mon Sep 17 00:00:00 2001 From: BeneficialCode <3123132899@qq.com> Date: Thu, 25 May 2023 06:32:05 -0400 Subject: [PATCH 4/4] Fixup a warning. --- fuzzer/src/fuzzer.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fuzzer/src/fuzzer.rs b/fuzzer/src/fuzzer.rs index 80fea16..27a7a75 100644 --- a/fuzzer/src/fuzzer.rs +++ b/fuzzer/src/fuzzer.rs @@ -301,9 +301,9 @@ impl Fuzzer { .expect("failed to execute luac"); let luac_path = Path::new(&luac_file); - let mut is_exist = 0; + let is_exist: bool; if luac_path.exists() { - is_exist = 1; + is_exist = true; if let Err(err) = fs::remove_file(luac_file) { println!("Error deleting file: {:?}",err); } @@ -312,12 +312,12 @@ impl Fuzzer { } } else{ - is_exist = 0; + is_exist = false; } self.total_testcast_count+=1; - if is_exist == 1 { + if is_exist { let exitreason = self.forksrv.run(code)?; self.execution_count += 1;