Skip to content

Commit

Permalink
Added stack bound for const calculations.
Browse files Browse the repository at this point in the history
commit-id:f8cbd2f9
  • Loading branch information
orizi committed Jan 4, 2025
1 parent 7ce12a6 commit 45b2ddd
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
4 changes: 4 additions & 0 deletions crates/cairo-lang-semantic/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,9 @@ impl DiagnosticEntry for SemanticDiagnostic {
SemanticDiagnosticKind::FailedConstantCalculation => {
"Failed to calculate constant.".into()
}
SemanticDiagnosticKind::ConstantCalculationDepthExceeded => {
"Constant calculation depth exceeded.".into()
}
SemanticDiagnosticKind::InnerFailedConstantCalculation(inner, _) => inner.format(db),
SemanticDiagnosticKind::DivisionByZero => "Division by zero.".into(),
SemanticDiagnosticKind::ExternTypeWithImplGenericsNotSupported => {
Expand Down Expand Up @@ -1322,6 +1325,7 @@ pub enum SemanticDiagnosticKind {
UnsupportedOutsideOfFunction(UnsupportedOutsideOfFunctionFeatureName),
UnsupportedConstant,
FailedConstantCalculation,
ConstantCalculationDepthExceeded,
InnerFailedConstantCalculation(Box<SemanticDiagnostic>, Vec<DiagnosticNote>),
DivisionByZero,
ExternTypeWithImplGenericsNotSupported,
Expand Down
11 changes: 11 additions & 0 deletions crates/cairo-lang-semantic/src/expr/test_data/constant
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ const fn panic_if_true(cond: bool) {
}
}

const FUNC_CALC_STACK_EXCEEDED: felt252 = call_myself();

const fn call_myself() -> felt252 {
call_myself()
}

//! > expected_diagnostics
error: Type not found.
--> lib.cairo:1:17
Expand Down Expand Up @@ -156,6 +162,11 @@ note: In `core::result::ResultTraitImpl::<core::felt252, core::felt252>::unwrap_
self.expect_err('Result::unwrap_err failed.')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Constant calculation depth exceeded.
--> lib.cairo:37:43
const FUNC_CALC_STACK_EXCEEDED: felt252 = call_myself();
^^^^^^^^^^^^^

//! > ==========================================================================

//! > Const of wrong type.
Expand Down
32 changes: 24 additions & 8 deletions crates/cairo-lang-semantic/src/items/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ pub fn validate_const_expr(ctx: &mut ComputationContext<'_>, expr_id: ExprId) {
vars: Default::default(),
generic_substitution: Default::default(),
info: info.as_ref(),
depth: 0,
diagnostics: ctx.diagnostics,
};
eval_ctx.validate(expr_id);
Expand Down Expand Up @@ -419,6 +420,7 @@ pub fn resolve_const_expr_and_evaluate(
vars: Default::default(),
generic_substitution: Default::default(),
info: info.as_ref(),
depth: 0,
diagnostics: ctx.diagnostics,
};
eval_ctx.validate(value.id);
Expand Down Expand Up @@ -468,8 +470,9 @@ struct ConstantEvaluateContext<'a> {
arenas: &'a Arenas,
vars: OrderedHashMap<VarId, ConstValue>,
generic_substitution: GenericSubstitution,
diagnostics: &'a mut SemanticDiagnostics,
info: &'a ConstCalcInfo,
depth: usize,
diagnostics: &'a mut SemanticDiagnostics,
}
impl ConstantEvaluateContext<'_> {
/// Validate the given expression can be used as constant.
Expand Down Expand Up @@ -903,6 +906,13 @@ impl ConstantEvaluateContext<'_> {
require(signature.is_const)?;
let generic_substitution = body_id.substitution(db).ok()?;
let body = db.function_body(concrete_body_id).ok()?;
const MAX_CONST_EVAL_DEPTH: usize = 100;
if self.depth > MAX_CONST_EVAL_DEPTH {
return Some(ConstValue::Missing(
self.diagnostics
.report(stable_ptr, SemanticDiagnosticKind::ConstantCalculationDepthExceeded),
));
}
let mut diagnostics = SemanticDiagnostics::default();
let mut inner = ConstantEvaluateContext {
db,
Expand All @@ -915,19 +925,25 @@ impl ConstantEvaluateContext<'_> {
.collect(),
generic_substitution,
info: self.info,
depth: self.depth + 1,
diagnostics: &mut diagnostics,
};
let value = inner.evaluate(body.body_expr);
for diagnostic in diagnostics.build().get_all() {
let location = diagnostic.location(db.elongate());
let (inner_diag, mut notes) =
if let SemanticDiagnosticKind::InnerFailedConstantCalculation(inner_diag, notes) =
diagnostic.kind
{
let (inner_diag, mut notes) = match diagnostic.kind {
SemanticDiagnosticKind::ConstantCalculationDepthExceeded => {
self.diagnostics.report(
stable_ptr,
SemanticDiagnosticKind::ConstantCalculationDepthExceeded,
);
continue;
}
SemanticDiagnosticKind::InnerFailedConstantCalculation(inner_diag, notes) => {
(inner_diag, notes)
} else {
(diagnostic.into(), vec![])
};
}
_ => (diagnostic.into(), vec![]),
};
notes.push(DiagnosticNote::with_location(
format!("In `{}`", concrete_function.full_name(db)),
location,
Expand Down

0 comments on commit 45b2ddd

Please sign in to comment.