Skip to content

Commit

Permalink
interp: fix nil value check in case of interface
Browse files Browse the repository at this point in the history
A wrong logic was leading to panic in recover. Simplify the
workflow for clarity.

Fixes #1022.
  • Loading branch information
mvertes committed Feb 1, 2021
1 parent ccb8072 commit eaebe14
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 63 deletions.
17 changes: 17 additions & 0 deletions _test/issue-1022.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import "fmt"

func main() {
defer func() {
r := recover()
if r != nil { // <- panic here
fmt.Println(r)
}
}()

panic("Ho Ho Ho!")
}

// Output:
// Ho Ho Ho!
148 changes: 85 additions & 63 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3381,47 +3381,58 @@ func isNil(n *node) {
tnext := getExec(n.tnext)
dest := genValue(n)

if n.fnext != nil {
fnext := getExec(n.fnext)
if c0.typ.cat == interfaceT {
if n.fnext == nil {
if c0.typ.cat != interfaceT {
n.exec = func(f *frame) bltn {
v := value(f)
vi, ok := v.Interface().(valueInterface)
if ok && (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) || v.IsNil() {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
dest(f).SetBool(value(f).IsNil())
return tnext
}
} else {
n.exec = func(f *frame) bltn {
if value(f).IsNil() {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
return
}
n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
dest(f).SetBool(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
} else {
dest(f).SetBool(v.IsNil())
}
return tnext
}
} else {
if c0.typ.cat == interfaceT {
n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
dest(f).SetBool(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
} else {
dest(f).SetBool(v.IsNil())
}
return
}

fnext := getExec(n.fnext)

if c0.typ.cat != interfaceT {
n.exec = func(f *frame) bltn {
if value(f).IsNil() {
dest(f).SetBool(true)
return tnext
}
} else {
n.exec = func(f *frame) bltn {
dest(f).SetBool(value(f).IsNil())
dest(f).SetBool(false)
return fnext
}
return
}

n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
if (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
if v.IsNil() {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}

}

func isNotNil(n *node) {
Expand All @@ -3435,46 +3446,57 @@ func isNotNil(n *node) {
tnext := getExec(n.tnext)
dest := genValue(n)

if n.fnext != nil {
fnext := getExec(n.fnext)
if c0.typ.cat == interfaceT {
if n.fnext == nil {
if c0.typ.cat != interfaceT {
n.exec = func(f *frame) bltn {
v := value(f)
vi, ok := v.Interface().(valueInterface)
if ok && (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) || v.IsNil() {
dest(f).SetBool(false)
return fnext
}
dest(f).SetBool(true)
dest(f).SetBool(!value(f).IsNil())
return tnext
}
} else {
n.exec = func(f *frame) bltn {
if value(f).IsNil() {
dest(f).SetBool(false)
return fnext
}
dest(f).SetBool(true)
return tnext
return
}

n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
dest(f).SetBool(!(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT))
} else {
dest(f).SetBool(!v.IsNil())
}
return tnext
}
} else {
if c0.typ.cat == interfaceT {
n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
dest(f).SetBool(!(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT))
} else {
dest(f).SetBool(!v.IsNil())
}
return tnext
return
}

fnext := getExec(n.fnext)

if c0.typ.cat != interfaceT {
n.exec = func(f *frame) bltn {
if value(f).IsNil() {
dest(f).SetBool(false)
return fnext
}
} else {
n.exec = func(f *frame) bltn {
dest(f).SetBool(!value(f).IsNil())
return tnext
dest(f).SetBool(true)
return tnext
}
return
}

n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
if (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) {
dest(f).SetBool(false)
return fnext
}
dest(f).SetBool(true)
return tnext
}
if v.IsNil() {
dest(f).SetBool(false)
return fnext
}
dest(f).SetBool(true)
return tnext
}
}

Expand Down

0 comments on commit eaebe14

Please sign in to comment.