// get_sign.rs // Showcase how we automatically can interface Rust to KLEE // #![no_std] #![no_main] use klee_sys::klee_make_symbolic; use panic_klee as _; fn sum_first_elements(arr: &[u8], index: usize) -> u8 { let mut acc = 0; for i in 0..index { if index < arr.len() { acc += arr[i as usize]; } else { break; } } acc } #[no_mangle] fn main() { let mut arr = [0u8; 8]; for i in 0..arr.len() { let mut element: u8 = 0; klee_make_symbolic!(&mut element, "element"); arr[i] = element; } let mut i: usize = 0; klee_make_symbolic!(&mut i, "i"); let b = sum_first_elements(&arr, i); } // A) Array indexing is tricky to analyse at compile time. // Thus Rust (rustc) will inject code for run-time verification // `panic`ing on index out of range. // // (Compare to C/C++, where a "buffer overflow" might pass unnoticed // causing all sorts of problems.) // // Compare the test generated in release `--release` (optimized) to // test generated in debug/dev mode (un-optimized). // // Try to explain in your own words the difference and why? // (Hint, even if we don't use the result `b`, Rust do not optimize out the call, why?) // // [your answer here]] // The diffrence is that debug test all 10 possible paths and release only checks 2. This is becaus // 9 of the paths are basicly the same. These are the path were index is 0..8, the last path is // diffrent because then the index is out side of the array(index = 255), thus there will be an error. // // // Debug: // KLEE: done: total instructions = 4686 // KLEE: done: completed paths = 10 // KLEE: done: generated tests = 10 // // Release: // KLEE: done: total instructions = 32 // KLEE: done: completed paths = 2 // KLEE: done: generated tests = 2 // // // B) Fix the code so that you don't get an error. // (It should still compute the sum of the n first elements // and return the sum of the whole array if index larger than size/length). // The fix should be in the function (not on the caller side). // // [Git commit "B"] // // C) In the example, the array is holding only zeroes. // Figure out a way to make the content symbolic. // (Hint, declare as mutable, iterate and set each element symbolic.) // (Hint2, it seems that you can set the whole array symbolic directly // without messing with an iterator, super!!!.) // // [Git commit "C"] // // D) Analyze the example using KLEE. Now a new (maybe unexpected) error should occur! // Notice, the error occurs only in `debug/dev` builds. // // Explain what caused the error. // // [your answer here] // // E) Make a sensible fix to the code. // Motivate your choice. // // [your answer here] // // [Git commit "D"] // // F) Learning outcome. // 70% of Microsoft security updates over the last decade is directly related to // memory safety. // // Explain in your own words what Microsoft would gain by using Rust. // // [your answer here] // // Explain in your own words what Microsoft would gain by using `cargo klee` // on their Rust code. // // And YES, Microsoft is rewriting core system functionality in Rust as we speak!