Add array oob checks + improve test handling

This commit is contained in:
0x4261756D
2023-01-11 02:33:30 +01:00
parent 0448b56adf
commit 34f52ae864
6 changed files with 56 additions and 13 deletions

View File

@ -167,8 +167,9 @@ fn main()
{
if let Some(index) = file_content.find(":END:")
{
let expected = &format!("//invalid,{}:END:", msg.replace("\n", "\n//"));
let expected_output = file_content[10..index].replace("\n//", "\n");
println!("\n\n===FAILED===\nExpected the output to be {}", expected_output);
println!("\n===FAILED===\nExpected the output to be\n'{}'\n({})", expected_output, expected);
}
else
{
@ -269,8 +270,12 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec
{
Ok(stderr) =>
{
println!("{:?}", stdout.as_bytes());
Ok(Some(format!("{}{}", stdout, stderr)))
let text = format!("{}{}", stdout, stderr);
match output.status.code()
{
Some(0) => Ok(Some(text)),
_ => Err(text),
}
}
Err(err) => Err(err.to_string()),
}
@ -362,10 +367,38 @@ fn generate_assembly_linux_x64(operations: &Vec<Operation>, functions: &Vec<Func
data.code += "\tlea rax, [dynamic+rsi]\n";
data.code += "\tret\n";
}
if data.code.contains("exception_array_read_out_of_bounds")
{
data.strings += "\texception_array_oob_msg db \"Attempted array out-of-bounds access\", 10\n";
data.code += "exception_array_read_out_of_bounds:\n";
//TODO: report the passed sizes
data.code += "\tmov rax, 1\n";
data.code += "\tmov rdi, 1\n";
// size
data.code += "\tmov rdx, 37\n";
// data
data.code += "\tmov rsi, exception_array_oob_msg\n";
data.code += "\tsyscall\n";
data.code += "\tmov rax, 60\n";
data.code += "\tmov rdi, -1\n";
data.code += "\tsyscall\n";
}
return fs::write("out.asm", format!("{}{}{}{}", ASSEMBLY_LINUX_X64_HEADER, data.code, data.arrays, data.strings));
}
fn generate_assembly_linux_x64_array_oob_check(length: i64) -> String
{
let mut data = String::new();
data += "\t\t;;Array bounds check\n";
data += format!("\tcmp qword rax, {}\n", length).as_str();
data += "\tjge exception_array_read_out_of_bounds\n";
data += "\tcmp qword rax, 0\n";
data += "\tjl exception_array_read_out_of_bounds\n";
data += "\t\t;;Array bounds check over\n";
return data.clone();
}
fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, arrays: &Vec<Arr>, debug: bool) -> AssemblyData
{
let mut data = AssemblyData
@ -640,12 +673,14 @@ fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Ve
}
Operation::Apply(name, word, line, col) =>
{
let array = arrays.iter().find(|x| &x.name == name).unwrap();
data.code += format!("\t;;apply {}.{} {}:{}\n", name, word, line, col).as_str();
match word.as_str()
{
"read" =>
{
data.code += "\tmov rax, [queue+8*r12]\n";
data.code += generate_assembly_linux_x64_array_oob_check(array.length).as_str();
data.code += "\tinc r12\n";
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
data.code += format!("\tmov qword rbx, [arr_{}+8*rax]\n", name).as_str();
@ -655,6 +690,7 @@ fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Ve
"write" =>
{
data.code += "\tmov rax, [queue+8*r12]\n";
data.code += generate_assembly_linux_x64_array_oob_check(array.length).as_str();
data.code += "\tinc r12\n";
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
data.code += "\tmov qword rbx, [queue+8*r12]\n";
@ -664,7 +700,6 @@ fn generate_assembly_linux_x64_block(operations: &Vec<Operation>, functions: &Ve
}
"length" =>
{
let array = arrays.iter().find(|x| &x.name == name).unwrap();
data.code += format!("\tmov qword [queue+8*r13], {}\n", array.length).as_str();
data.code += "\tinc r13\n";
}
@ -896,11 +931,13 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
let position: i64 = queue.remove(0).parse::<i64>().unwrap();
if position >= arr.length
{
return Err(format!("Attempted an out of bounds write for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col));
//return Err(format!("Attempted an out of bounds write for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col));
return Err(String::from("Attempted array out-of-bounds access"));
}
if position < 0
{
return Err(format!("Attempted an out of bounds write for array {} ({} < 0) at {}:{}", arr.name, position, line, col));
//return Err(format!("Attempted an out of bounds write for array {} ({} < 0) at {}:{}", arr.name, position, line, col));
return Err(String::from("Attempted array out-of-bounds access"));
}
let data = queue.remove(0);
if debug
@ -918,11 +955,13 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
let position: i64 = queue.remove(0).parse::<i64>().unwrap();
if position >= arr.length
{
return Err(format!("Attempted an out of bounds read for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col));
//return Err(format!("Attempted an out of bounds read for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col));
return Err(String::from("Attempted array out-of-bounds access"));
}
if position < 0
{
return Err(format!("Attempted an out of bounds read for array {} ({} < 0) at {}:{}", arr.name, position, line, col));
//return Err(format!("Attempted an out of bounds read for array {} ({} < 0) at {}:{}", arr.name, position, line, col));
return Err(String::from("Attempted array out-of-bounds access"));
}
queue.push(arr.data[position as usize].clone());
}