Skip to content

Commit

Permalink
Fix: nasl-interpreter: string handling in operation
Browse files Browse the repository at this point in the history
When a string is added to a number, the number should be casted to a
string and not the string to number.

For example: 1 + "" + 3 should return "13" and not 5.
  • Loading branch information
nichtsfrei committed May 15, 2024
1 parent adaa4b2 commit ac9a5d5
Showing 1 changed file with 47 additions and 15 deletions.
62 changes: 47 additions & 15 deletions rust/nasl-interpreter/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ where
// because it is handled as a SyntaxError. Therefore we don't double check and
// and let it run into a index out of bound panic to immediately escalate.
let (left, right) = {
for (i, e) in stmts.iter().enumerate() {
println!("{i} {e}");
}

let first = self.resolve(&stmts[0])?;
if stmts.len() == 1 {
(first, None)
Expand Down Expand Up @@ -81,6 +85,22 @@ fn not_match_regex(a: NaslValue, matches: Option<NaslValue>) -> InterpretResult
Ok(NaslValue::Boolean(!bool::from(result)))
}

macro_rules! add_left_right_string {
($left: ident, $right:ident) => {{
let right = $right.map(|x| x.to_string()).unwrap_or_default();
let x = $left;
Ok(NaslValue::String(format!("{x}{right}")))
}};
}

macro_rules! minus_left_right_string {
($left: ident, $right:ident) => {{
let right = $right.map(|x| x.to_string()).unwrap_or_default();
let x = $left.to_string();
Ok(NaslValue::String(x.replacen(&right, "", 1)))
}};
}

impl<'a, K> OperatorExtension for Interpreter<'a, K>
where
K: AsRef<str>,
Expand All @@ -90,36 +110,44 @@ where
// number and string
TokenCategory::Plus => self.execute(stmts, |a, b| match a {
NaslValue::String(x) => {
let right = b.map(|x| x.to_string()).unwrap_or_default();
Ok(NaslValue::String(format!("{x}{right}")))
add_left_right_string!(x, b)
}
NaslValue::Data(x) => {
let right: String = b.map(|x| x.to_string()).unwrap_or_default();
let x: String = x.into_iter().map(|b| b as char).collect();
// TODO: wrong return value, should be data
Ok(NaslValue::String(format!("{x}{right}")))
}
left => {
let right = b.map(|x| i64::from(&x)).unwrap_or_default();
Ok(NaslValue::Number(i64::from(&left) + right))
}
// on plus only we need to cast to string when right is a string
left => match b {
Some(NaslValue::String(_)) => add_left_right_string!(left, b),
_ => {
let right = b.map(|x| i64::from(&x)).unwrap_or_default();
Ok(NaslValue::Number(i64::from(&left) + right))
}
},
}),
TokenCategory::Minus => self.execute(stmts, |a, b| match a {
NaslValue::String(x) => {
let right: String = b.map(|x| x.to_string()).unwrap_or_default();
Ok(NaslValue::String(x.replacen(&right, "", 1)))
minus_left_right_string!(x, b)
}
NaslValue::Data(x) => {
let right: String = b.map(|x| x.to_string()).unwrap_or_default();
let x: String = x.into_iter().map(|b| b as char).collect();
Ok(NaslValue::String(x.replacen(&right, "", 1)))
}
left => {
let result = match b {
Some(right) => i64::from(&left) - i64::from(&right),
None => -i64::from(&left),
};
Ok(NaslValue::Number(result))
}
left => match b {
Some(NaslValue::String(_)) => {
minus_left_right_string!(left, b)
}
_ => {
let result = match b {
Some(right) => i64::from(&left) - i64::from(&right),
None => -i64::from(&left),
};
Ok(NaslValue::Number(result))
}
},
}),
// number
TokenCategory::Star => self.execute(stmts, |a, b| num_expr!(* a b)),
Expand Down Expand Up @@ -242,6 +270,10 @@ mod tests {
}
create_test! {
numeric_plus: "1+2;" => 3.into(),
cast_to_string_middle_plus: "1+\"\"+2;" => "12".into(),
cast_to_string_end_plus: "1+2+\"\";" => "3".into(),
cast_to_string_end_plus_4: "1+2+\"\" + 4;" => "34".into(),
cast_to_string_minus: "11-\"1\";" => "1".into(),
string_plus: "\"hello \" + \"world!\";" => "hello world!".into(),
string_minus : "\"hello \" - 'o ';" => "hell".into(),
data_plus: "'hello ' + 'world!';" => "hello world!".into(),
Expand Down

0 comments on commit ac9a5d5

Please sign in to comment.