git.delta.rocks / jrsonnet / refs/commits / 9c0fa0107dd8

difftreelog

feat detect infinite recursion in object evaluation

Yaroslav Bolyukin2022-04-20parent: #5a22275.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
106 #[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")]
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
1use 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 => This
30type CacheKey = (IStr, WeakObjValue);31type CacheKey = (IStr, WeakObjValue);
32
33#[derive(Trace)]
34enum CacheValue {
35 Cached(Val),
36 NotFound,
37 Pending,
38 Errored(LocError),
39}
40
31#[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}
4151
42#[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()));
235245
236 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.0
255 .value_cache
256 .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.0
278 .value_cache
279 .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_cache
257 .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 }
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
47 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) =