aboutsummaryrefslogtreecommitdiff
path: root/lib/xixanta/src/assembler.rs
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2025-09-03 21:31:31 +0200
committerMiquel Sabaté Solà <mikisabate@gmail.com>2025-09-03 21:40:46 +0200
commite0b1faf993bab97288540769f6f5f7955b3e0996 (patch)
tree862130ab64adefc17b7796eb6ed53dcdd581c065 /lib/xixanta/src/assembler.rs
parent9dcbf460ff692c049e4d327afcbdbc39ba4e8c65 (diff)
downloadtools.nes-e0b1faf993bab97288540769f6f5f7955b3e0996.tar.gz
tools.nes-e0b1faf993bab97288540769f6f5f7955b3e0996.zip
Add a check for variable names
This check ensures that asan-friendly names actually match their expected scope. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'lib/xixanta/src/assembler.rs')
-rw-r--r--lib/xixanta/src/assembler.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index 09f0c9d..01a1982 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -498,6 +498,13 @@ impl<'a> Assembler<'a> {
match self.evaluate_node(node.left.as_ref().unwrap()) {
Ok(value) => {
+ // Check that the given name makes sense if the
+ // address sanitizer is enable and the assigned
+ // value is known.
+ if self.asan_enabled && value.resolved {
+ self.asan_check_variable_name(node, &value);
+ }
+
if let Err(err) = self.context.set_variable(
&node.value,
&Object {
@@ -2626,6 +2633,66 @@ impl<'a> Assembler<'a> {
}
}
+ // Check that the variable name follows the coding convention as expected
+ // from the address sanitizer.
+ fn asan_check_variable_name(&mut self, node: &PNode, bundle: &Bundle) {
+ // If this is not an asan-friendly name, skip it, as it might be a
+ // constant or something else that might be catched later.
+ if !is_asan_friendly_name(&node.value.value) {
+ return;
+ }
+
+ // Let's create this object now to makes things easier for possible
+ // error messages.
+ let actual_name = node.value.value.split("::").last().unwrap_or("");
+
+ if actual_name.starts_with("zp_") {
+ if bundle.size > 1 {
+ let value = bundle.value() as usize;
+ let range = MemoryRange {
+ name: node.value.value.to_owned(),
+ range: (value..(value + self.asan_next_reserve as usize)),
+ };
+ self.warnings.push(Error {
+ line: node.value.line,
+ message: format!("you are assigning the zero-page variable {range} to something outside of zero page"),
+ source: self.source_for(node),
+ global: false,
+ });
+ }
+ } else if bundle.size != 2 {
+ let value = bundle.value() as usize;
+ let range = MemoryRange {
+ name: node.value.value.to_owned(),
+ range: (value..(value + self.asan_next_reserve as usize)),
+ };
+ self.warnings.push(Error {
+ line: node.value.line,
+ message: format!(
+ "you are assigning the variable {range} to something in zero page"
+ ),
+ source: self.source_for(node),
+ global: false,
+ });
+ } else if actual_name.starts_with("wr_") {
+ let value = bundle.value() as usize;
+ let range = MemoryRange {
+ name: node.value.value.to_owned(),
+ range: (value..(value + self.asan_next_reserve as usize)),
+ };
+ if !(0x6000..0x8000).contains(&value) {
+ self.warnings.push(Error {
+ line: node.value.line,
+ message: format!(
+ "you are assigning the variable {range} to something outside of Working RAM"
+ ),
+ source: self.source_for(node),
+ global: false,
+ });
+ }
+ }
+ }
+
fn to_relative_address(&self, node: &PNode, bundle: &mut Bundle) -> Result<(), Error> {
if !bundle.resolved {
return Ok(());