Unverified Commit 1b0f0b48 by Enkelmann Committed by GitHub

prevent huge expressions during expression propagation (#412)

parent 1fcc30cb
......@@ -55,9 +55,15 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
let mut extended_expression = expression.clone();
for input_var in expression.input_vars().into_iter() {
if let Some(expr) = insertable_expressions.get(input_var) {
extended_expression.substitute_input_var(input_var, expr)
// We limit the complexity of expressions to insert.
// This prevents extremely large expressions that can lead to extremely high RAM usage.
// FIXME: Right now this limit is quite arbitrary. Maybe there is a better way to achieve the same result?
if expr.recursion_depth() < 10 {
extended_expression.substitute_input_var(input_var, expr)
}
}
}
extended_expression.substitute_trivial_operations();
insertable_expressions.insert(var.clone(), extended_expression.clone());
// Expressions dependent on the assigned variable are no longer insertable.
insertable_expressions.retain(|_input_var, input_expr| {
......
......@@ -208,6 +208,22 @@ impl Expression {
}
}
}
/// Compute a recursion depth for the expression.
///
/// Because of the recursive nature of the [Expression] type,
/// overly complex expressions are very costly to clone, which in turn can negatively affect some analyses.
/// The recursion depth measure can be used to detect and handle such cases.
pub fn recursion_depth(&self) -> u64 {
use Expression::*;
match self {
Const(_) | Unknown { .. } | Var(_) => 0,
Subpiece { arg, .. } | Cast { arg, .. } | UnOp { arg, .. } => arg.recursion_depth() + 1,
BinOp { lhs, rhs, .. } => {
std::cmp::max(lhs.recursion_depth(), rhs.recursion_depth()) + 1
}
}
}
}
impl fmt::Display for Expression {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment