fix: checks that value implements a binary type in type assert

This commit is contained in:
Marc Vertes
2020-04-03 04:02:04 +02:00
committed by GitHub
parent e78650d359
commit b20ad3a01d
3 changed files with 94 additions and 12 deletions

55
_test/issue-558.go Normal file
View File

@@ -0,0 +1,55 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"strings"
)
type readAutoCloser struct {
r io.ReadCloser
}
func (a readAutoCloser) Read(b []byte) (n int, err error) {
if a.r == nil {
return 0, io.EOF
}
n, err = a.r.Read(b)
if err == io.EOF {
a.Close()
}
return n, err
}
func (a readAutoCloser) Close() error {
if a.r == nil {
return nil
}
return a.r.(io.Closer).Close()
}
type pipe struct {
Reader readAutoCloser
}
func newReadAutoCloser(r io.Reader) readAutoCloser {
if _, ok := r.(io.Closer); !ok {
return readAutoCloser{ioutil.NopCloser(r)}
}
return readAutoCloser{r.(io.ReadCloser)}
}
func main() {
p := &pipe{}
p.Reader = newReadAutoCloser(strings.NewReader("test"))
b, err := ioutil.ReadAll(p.Reader)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
// Output:
// test

18
_test/type20.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"io"
"strings"
)
func isCloser(r io.Reader) bool {
_, ok := r.(io.Closer)
return ok
}
func main() {
println(isCloser(strings.NewReader("test")))
}
// Output:
// false

View File

@@ -121,30 +121,33 @@ func runCfg(n *node, f *frame) {
}
func typeAssertStatus(n *node) {
value := genValue(n.child[0]) // input value
c0, c1 := n.child[0], n.child[1]
value := genValue(c0) // input value
value1 := genValue(n.anc.child[1]) // returned status
typ := c1.typ.rtype // type to assert
next := getExec(n.tnext)
switch {
case n.child[0].typ.cat == valueT:
case c0.typ.cat == valueT:
n.exec = func(f *frame) bltn {
if !value(f).IsValid() || value(f).IsNil() {
v := value(f)
if !v.IsValid() || v.IsNil() {
value1(f).SetBool(false)
}
value1(f).SetBool(true)
value1(f).SetBool(v.Type().Implements(typ))
return next
}
case n.child[1].typ.cat == interfaceT:
case c1.typ.cat == interfaceT:
n.exec = func(f *frame) bltn {
_, ok := value(f).Interface().(valueInterface)
//value0(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
// TODO: verify that value(f) implements asserted type.
value1(f).SetBool(ok)
return next
}
default:
n.exec = func(f *frame) bltn {
_, ok := value(f).Interface().(valueInterface)
//value0(f).Set(v.value)
// TODO: verify that value(f) implements asserted type.
value1(f).SetBool(ok)
return next
}
@@ -152,25 +155,29 @@ func typeAssertStatus(n *node) {
}
func typeAssert(n *node) {
value := genValue(n.child[0]) // input value
dest := genValue(n) // returned result
c0, c1 := n.child[0], n.child[1]
value := genValue(c0) // input value
dest := genValue(n) // returned result
next := getExec(n.tnext)
switch {
case n.child[0].typ.cat == valueT:
case c0.typ.cat == valueT:
n.exec = func(f *frame) bltn {
dest(f).Set(value(f).Elem())
v := value(f)
dest(f).Set(v.Elem())
return next
}
case n.child[1].typ.cat == interfaceT:
case c1.typ.cat == interfaceT:
n.exec = func(f *frame) bltn {
v := value(f).Interface().(valueInterface)
// TODO: verify that value(f) implements asserted type.
dest(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
return next
}
default:
n.exec = func(f *frame) bltn {
v := value(f).Interface().(valueInterface)
// TODO: verify that value(f) implements asserted type.
dest(f).Set(v.value)
return next
}
@@ -195,6 +202,7 @@ func typeAssert2(n *node) {
case n.child[1].typ.cat == interfaceT:
n.exec = func(f *frame) bltn {
v, ok := value(f).Interface().(valueInterface)
// TODO: verify that value(f) implements asserted type.
value0(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
value1(f).SetBool(ok)
return next
@@ -202,6 +210,7 @@ func typeAssert2(n *node) {
default:
n.exec = func(f *frame) bltn {
v, ok := value(f).Interface().(valueInterface)
// TODO: verify that value(f) implements asserted type.
value0(f).Set(v.value)
value1(f).SetBool(ok)
return next