diff --git a/cedar-policy-core/src/evaluator.rs b/cedar-policy-core/src/evaluator.rs index 2a4825c998..6db00d87a0 100644 --- a/cedar-policy-core/src/evaluator.rs +++ b/cedar-policy-core/src/evaluator.rs @@ -1159,7 +1159,7 @@ impl Value { } #[inline(always)] -fn stack_size_check() -> Result<()> { +pub(crate) fn stack_size_check() -> Result<()> { // We assume there's enough space if we cannot determine it with `remaining_stack` if stacker::remaining_stack().unwrap_or(REQUIRED_STACK_SPACE) < REQUIRED_STACK_SPACE { return Err(EvaluationError::recursion_limit(None)); diff --git a/cedar-policy-core/src/tpe/evaluator.rs b/cedar-policy-core/src/tpe/evaluator.rs index 5b22479511..159c449348 100644 --- a/cedar-policy-core/src/tpe/evaluator.rs +++ b/cedar-policy-core/src/tpe/evaluator.rs @@ -22,6 +22,7 @@ use crate::tpe::err::ExprToResidualError; use crate::validator::types::Type; use crate::{ ast::{self, BinaryOp, EntityUID, Expr, PartialValue, Set, Value, ValueKind, Var}, + evaluator::stack_size_check, extensions::Extensions, }; @@ -60,6 +61,13 @@ impl Evaluator<'_> { } Residual::Partial { kind, ty: _ty } => kind, }; + + // Guard against stack overflows (just like the concrete evaluator), given the recursive nature of interpret + match stack_size_check() { + Ok(_) => (), + Err(_) => return Residual::Error(ty), + } + match kind { ResidualKind::Var(Var::Action) => Residual::Concrete { value: self.request.action.clone().into(),