Skip to content

Commit

Permalink
prevent aliases upstack/avoid indirect loops; fix caching bug and add…
Browse files Browse the repository at this point in the history
… test for it using 2 level deep rand()
  • Loading branch information
ldemailly committed Sep 3, 2024
1 parent 55f3acf commit e893b40
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 1 deletion.
2 changes: 2 additions & 0 deletions eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,8 @@ func (s *State) applyFunction(name string, fn object.Object, args []object.Objec
}
if after != before {
log.Debugf("Cache miss for %s %v, %d get misses", function.CacheKey, args, after-before)
// A miss here is a miss upstack
s.env.TriggerNoCache()
return res
}
// Don't cache errors, as it could be due to binding for instance.
Expand Down
13 changes: 13 additions & 0 deletions eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1009,3 +1009,16 @@ func TestSelfRef(t *testing.T) {
t.Errorf("wrong result, got %q", res.Inspect())
}
}

func TestAliasTwice(t *testing.T) {
inp := `a=1; b=2;()=>{a=b}();b=5;()=>{a=b}()` // should not crash
s := eval.NewState()
res, err := eval.EvalString(s, inp, false)
if err != nil {
t.Errorf("should not have errored: %v", err)
}
expected := "5"
if res.Inspect() != expected {
t.Errorf("wrong result, got %q", res.Inspect())
}
}
14 changes: 14 additions & 0 deletions examples/random.gr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Really this checks we don't cache functions that call non cacheable functions.

func deepRand() {
() => {
rand()
}()
}

a1 = deepRand(); log("a1", a1)
a2 = deepRand(); log("a2", a2)

if a1 == a2 {
error("a1 and a2 should be different")
}
4 changes: 4 additions & 0 deletions main_test.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ stdout '^42$'
grol -quiet -c 'a=-3; b=5; ()=>{b=a;a=b;b++;a++}();[a,b]'
stdout '^\[-2,-2\]$'

# 2nd aliasing crashes
grol -quiet -c 'a=1; b=2;()=>{a=b}();()=>{a=b;println(type(a),type(b))}()'
stdout '&a.\(INTEGER\) &b.\(INTEGER\)'

-- json_output --
{
"63": 63,
Expand Down
2 changes: 1 addition & 1 deletion object/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func (e *Environment) SetNoChecks(name string, val Object, create bool) Object {
// New name... let's see if it's really new or making it a ref.
if ref, ok := e.makeRef(name); ok {
log.Debugf("SetNoChecks(%s) created ref %s in %d", name, ref.Name, ref.RefEnv.depth)
ref.RefEnv.store[ref.Name] = val
ref.RefEnv.store[ref.Name] = Value(val) // kinda neat to make aliases but it can create loops, so not for now.
return val
}
log.Debugf("SetNoChecks(%s) brand new to %d and above", name, e.depth)
Expand Down

0 comments on commit e893b40

Please sign in to comment.