difftreelog
feat detect infinite recursion in object evaluation
in: master
3 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth106 #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]106 #[error("stack overflow, try to reduce recursion, or set --max-stack to bigger value")]107 StackOverflow,107 StackOverflow,108 #[error("infinite recursion detected")]108 #[error("infinite recursion detected")]109 RecursiveLazyValueEvaluation,109 InfiniteRecursionDetected,110 #[error("tried to index by fractional value")]110 #[error("tried to index by fractional value")]111 FractionalIndex,111 FractionalIndex,112 #[error("attempted to divide by zero")]112 #[error("attempted to divide by zero")]crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth1use crate::error::LocError;1use crate::function::CallLocation;2use crate::function::CallLocation;2use crate::gc::{GcHashMap, GcHashSet, TraceBox};3use crate::gc::{GcHashMap, GcHashSet, TraceBox};3use crate::operator::evaluate_add_op;4use crate::operator::evaluate_add_op;29// Field => This30// Field => This30type CacheKey = (IStr, WeakObjValue);31type CacheKey = (IStr, WeakObjValue);3233#[derive(Trace)]34enum CacheValue {35 Cached(Val),36 NotFound,37 Pending,38 Errored(LocError),39}4031#[derive(Trace)]41#[derive(Trace)]32#[force_tracking]42#[force_tracking]36 assertions_ran: RefCell<GcHashSet<ObjValue>>,46 assertions_ran: RefCell<GcHashSet<ObjValue>>,37 this_obj: Option<ObjValue>,47 this_obj: Option<ObjValue>,38 this_entries: Cc<GcHashMap<IStr, ObjMember>>,48 this_entries: Cc<GcHashMap<IStr, ObjMember>>,39 value_cache: RefCell<GcHashMap<CacheKey, Option<Val>>>,49 value_cache: RefCell<GcHashMap<CacheKey, CacheValue>>,40}50}415142#[derive(Clone, Trace)]52#[derive(Clone, Trace)]234 let cache_key = (key.clone(), WeakObjValue(real_this.0.downgrade()));244 let cache_key = (key.clone(), WeakObjValue(real_this.0.downgrade()));235245236 if let Some(v) = self.0.value_cache.borrow().get(&cache_key) {246 if let Some(v) = self.0.value_cache.borrow().get(&cache_key) {237 return Ok(v.clone());247 return Ok(match v {248 CacheValue::Cached(v) => Some(v.clone()),249 CacheValue::NotFound => None,250 CacheValue::Pending => throw!(InfiniteRecursionDetected),251 CacheValue::Errored(e) => return Err(e.clone()),252 });238 }253 }254 self.0255 .value_cache256 .borrow_mut()257 .insert(cache_key.clone(), CacheValue::Pending);239 let value = match (self.0.this_entries.get(&key), &self.0.super_obj) {258 let value = match (self.0.this_entries.get(&key), &self.0.super_obj) {240 (Some(k), None) => Ok(Some(self.evaluate_this(k, real_this)?)),259 (Some(k), None) => Ok(Some(self.evaluate_this(k, real_this)?)),241 (Some(k), Some(s)) => {260 (Some(k), Some(s)) => {251 }270 }252 (None, Some(s)) => s.get_raw(key, Some(real_this)),271 (None, Some(s)) => s.get_raw(key, Some(real_this)),253 (None, None) => Ok(None),272 (None, None) => Ok(None),254 }?;273 };274 let value = match value {275 Ok(v) => v,276 Err(e) => {277 self.0278 .value_cache279 .borrow_mut()280 .insert(cache_key, CacheValue::Errored(e.clone()));281 return Err(e);282 }283 };255 self.0284 self.0.value_cache.borrow_mut().insert(256 .value_cache257 .borrow_mut()258 .insert(cache_key, value.clone());285 cache_key,286 match &value {287 Some(v) => CacheValue::Cached(v.clone()),288 None => CacheValue::NotFound,289 },290 );259 Ok(value)291 Ok(value)260 }292 }crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth47 match &*self.0.borrow() {47 match &*self.0.borrow() {48 LazyValInternals::Computed(v) => return Ok(v.clone()),48 LazyValInternals::Computed(v) => return Ok(v.clone()),49 LazyValInternals::Errored(e) => return Err(e.clone()),49 LazyValInternals::Errored(e) => return Err(e.clone()),50 LazyValInternals::Pending => return Err(RecursiveLazyValueEvaluation.into()),50 LazyValInternals::Pending => return Err(InfiniteRecursionDetected.into()),51 _ => (),51 _ => (),52 };52 };53 let value = if let LazyValInternals::Waiting(value) =53 let value = if let LazyValInternals::Waiting(value) =