From f10404244c28cc89ff0569cf9feef7963ff03cbc Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Mon, 1 Feb 2021 19:06:13 +0100 Subject: [PATCH 1/3] interp: fix nil value check in case of interface A wrong logic was leading to panic in recover. Simplify the workflow for clarity. Fixes #1022. --- _test/issue-1022.go | 17 +++++ interp/run.go | 148 +++++++++++++++++++++++++------------------- 2 files changed, 102 insertions(+), 63 deletions(-) create mode 100644 _test/issue-1022.go diff --git a/_test/issue-1022.go b/_test/issue-1022.go new file mode 100644 index 000000000..ddbbdb2bc --- /dev/null +++ b/_test/issue-1022.go @@ -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! diff --git a/interp/run.go b/interp/run.go index caca54911..436cd4193 100644 --- a/interp/run.go +++ b/interp/run.go @@ -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) { @@ -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 } } From c0c5a9703256afe77e58dbdc25444bd71efeda2d Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Mon, 1 Feb 2021 19:15:40 +0100 Subject: [PATCH 2/3] fix lint error --- interp/run.go | 1 - 1 file changed, 1 deletion(-) diff --git a/interp/run.go b/interp/run.go index 436cd4193..dc2092755 100644 --- a/interp/run.go +++ b/interp/run.go @@ -3432,7 +3432,6 @@ func isNil(n *node) { dest(f).SetBool(false) return fnext } - } func isNotNil(n *node) { From 9bb4f388a5373d1167311423f48c660cdb536dbc Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 2 Feb 2021 12:07:16 +0100 Subject: [PATCH 3/3] apply review remarks --- _test/issue-1022.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_test/issue-1022.go b/_test/issue-1022.go index ddbbdb2bc..6aa1a388c 100644 --- a/_test/issue-1022.go +++ b/_test/issue-1022.go @@ -5,7 +5,7 @@ import "fmt" func main() { defer func() { r := recover() - if r != nil { // <- panic here + if r != nil { fmt.Println(r) } }()