From dbce3c9a199d0a1892412d3527fb9650ec413bb2 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 12 Oct 2020 16:46:01 +0300 Subject: [PATCH] compiler: do not DROP unary expression value inside IF stmt We dropped values from such calls because they where marked as unused (consequently, were followed by DROP instructions). Example: if !foo() { <--- panic here ... } This commit prevents the following runtime error during script execution: ``` "error encountered at instruction ** (NOT): runtime error: invalid memory address or nil pointer dereference" ``` --- pkg/compiler/func_scope.go | 5 +++++ pkg/compiler/if_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/pkg/compiler/func_scope.go b/pkg/compiler/func_scope.go index 3e977c42e..e8b6c9d25 100644 --- a/pkg/compiler/func_scope.go +++ b/pkg/compiler/func_scope.go @@ -112,6 +112,11 @@ func (c *funcScope) analyzeVoidCalls(node ast.Node) bool { if ok { c.voidCalls[ce] = false } + case *ast.UnaryExpr: + ce, ok := n.X.(*ast.CallExpr) + if ok { + c.voidCalls[ce] = false + } case *ast.IfStmt: // we can't just return `false`, because we still need to process body ce, ok := n.Cond.(*ast.CallExpr) diff --git a/pkg/compiler/if_test.go b/pkg/compiler/if_test.go index 038c8fe92..5ee1c420e 100644 --- a/pkg/compiler/if_test.go +++ b/pkg/compiler/if_test.go @@ -121,3 +121,32 @@ func TestInitIF(t *testing.T) { }) }) } + +func TestCallExpIF(t *testing.T) { + t.Run("Call", func(t *testing.T) { + src := `package foo + func someFunc() bool { + return true + } + func Main() int { + if someFunc() { + return 5 + } + return 6 + }` + eval(t, src, big.NewInt(5)) + }) + t.Run("CallWithUnaryExpression", func(t *testing.T) { + src := `package foo + func someFunc() bool { + return false + } + func Main() int { + if !someFunc() { + return 5 + } + return 6 + }` + eval(t, src, big.NewInt(5)) + }) +}