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

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2022 0x4261756D Copyright (c) 2022-2023 0x4261756D
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -167,8 +167,9 @@ fn main()
{ {
if let Some(index) = file_content.find(":END:") 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"); 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 else
{ {
@ -269,8 +270,12 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec
{ {
Ok(stderr) => Ok(stderr) =>
{ {
println!("{:?}", stdout.as_bytes()); let text = format!("{}{}", stdout, stderr);
Ok(Some(format!("{}{}", stdout, stderr))) match output.status.code()
{
Some(0) => Ok(Some(text)),
_ => Err(text),
}
} }
Err(err) => Err(err.to_string()), 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 += "\tlea rax, [dynamic+rsi]\n";
data.code += "\tret\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)); 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 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 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) => 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(); data.code += format!("\t;;apply {}.{} {}:{}\n", name, word, line, col).as_str();
match word.as_str() match word.as_str()
{ {
"read" => "read" =>
{ {
data.code += "\tmov rax, [queue+8*r12]\n"; 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 += "\tinc r12\n";
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE; data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
data.code += format!("\tmov qword rbx, [arr_{}+8*rax]\n", name).as_str(); 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" => "write" =>
{ {
data.code += "\tmov rax, [queue+8*r12]\n"; 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 += "\tinc r12\n";
data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE; data.code += ASSEMBLY_LINUX_X64_TRY_RESET_QUEUE;
data.code += "\tmov qword rbx, [queue+8*r12]\n"; 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" => "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 += format!("\tmov qword [queue+8*r13], {}\n", array.length).as_str();
data.code += "\tinc r13\n"; 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(); let position: i64 = queue.remove(0).parse::<i64>().unwrap();
if position >= arr.length 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 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); let data = queue.remove(0);
if debug 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(); let position: i64 = queue.remove(0).parse::<i64>().unwrap();
if position >= arr.length 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 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()); queue.push(arr.data[position as usize].clone());
} }

View File

@ -1,4 +1,5 @@
//invalid,Attempted an out of bounds read for array test (5 >= 4) at 5:12:END: //invalid,Attempted array out-of-bounds access
//:END:
arr test { bool 4 } arr test { bool 4 }

View File

@ -1,4 +1,5 @@
//invalid,Attempted an out of bounds write for array test (5 >= 4) at 5:19:END: //invalid,Attempted array out-of-bounds access
//:END:
arr test { bool 4 } arr test { bool 4 }

View File

@ -1,4 +1,5 @@
//invalid,Attempted an out of bounds read for array test (-1 < 0) at 5:13:END: //invalid,Attempted array out-of-bounds access
//:END:
arr test { bool 4 } arr test { bool 4 }

View File

@ -1,4 +1,5 @@
//invalid,Attempted an out of bounds write for array test (-1 < 0) at 5:19:END: //invalid,Attempted array out-of-bounds access
//:END:
arr test { bool 4 } arr test { bool 4 }