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
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:

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());
}

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 }

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 }

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 }

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 }