Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: restrict duplicate macros #1

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions huff_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ impl Parser {
TokenKind::Macro | TokenKind::Fn | TokenKind::Test => {
let m = self.parse_macro()?;
tracing::info!(target: "parser", "SUCCESSFULLY PARSED MACRO {}", m.name);
if contract.macros.iter().any(|existing| existing.name == m.name) {
return Err(ParserError {
kind: ParserErrorKind::DuplicateMacro(m.name),
hint: Some("MACRO names should be unique".to_string()),
spans: AstSpan(vec![self.spans[2].clone()]),
})
}
contract.macros.push(m);
}
TokenKind::JumpTable | TokenKind::JumpTablePacked | TokenKind::CodeTable => {
Expand Down
66 changes: 66 additions & 0 deletions huff_parser/tests/macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1232,3 +1232,69 @@ fn empty_test_with_multi_flag_decorator() {
assert_eq!(macro_definition, expected);
assert_eq!(parser.current_token.kind, TokenKind::Eof);
}

#[test]
fn test_duplicate_macro_error() {
let source = r#"
#define macro CONSTRUCTOR() = takes(0) returns (0) {}

#define macro MINT() = takes(0) returns (0) {
0x04 calldataload // [to]
0x00 // [from (0x00), to]
0x24 calldataload // [value, from, to]
}

#define macro MINT() = takes(0) returns (0) {
0x04 calldataload // [to]
0x00 // [from (0x00), to]
0x24 calldataload // [value, from, to]
}

#define macro MAIN() = takes(0) returns (0) {
0x00 calldataload 0xE0 shr
dup1 0x40c10f19 eq mints jumpi

mints:
MINT()
}
"#;

//let const_start = source.find("MINT()").unwrap_or(0);
//let const_end = const_start + "MINT()".len() - 1;
let mut start = 0;
let target = "MINT";
let target_len = target.len();
let mut occurrences = Vec::new();

while let Some(pos) = source[start..].find(target) {
let adjusted_start = start + pos;
let adjusted_end = adjusted_start + target_len - 1;

occurrences.push((adjusted_start, adjusted_end));
start = adjusted_end + 1;
}

let full_source = FullFileSource { source, file: None, spans: vec![] };
let lexer = Lexer::new(full_source.source);
let tokens = lexer.into_iter().map(|x| x.unwrap()).collect::<Vec<Token>>();
let mut parser = Parser::new(tokens, Some("".to_string()));

// This should be caught before codegen invalid macro statement
match parser.parse() {
Ok(_) => panic!("moose"),
Err(e) => {
assert_eq!(
e,
ParserError {
kind: ParserErrorKind::DuplicateMacro("MINT".to_string()),
hint: Some("MACRO names should be unique".to_string()),
spans: AstSpan(vec![Span {
start: occurrences[1].0.clone(),
end: occurrences[1].1.clone(),
file: None
}]),
}
)
}
}
}
10 changes: 10 additions & 0 deletions huff_utils/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub enum ParserErrorKind {
InvalidDecoratorFlag(String),
/// Invalid decorator flag argument
InvalidDecoratorFlagArg(TokenKind),
/// Duplicate MACRO
DuplicateMacro(String),
}

/// A Lexing Error
Expand Down Expand Up @@ -488,6 +490,14 @@ impl fmt::Display for CompilerError {
pe.spans.error(pe.hint.as_ref())
)
}
ParserErrorKind::DuplicateMacro(mn) => {
write!(
f,
"\nError: Duplicate MACRO name found: \"{}\" \n{}\n",
mn,
pe.spans.error(pe.hint.as_ref())
)
}
},
CompilerError::PathBufRead(os_str) => {
write!(
Expand Down