Skip to content

Commit

Permalink
fix: checks that value implements a binary type in type assert
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes committed Apr 3, 2020
1 parent e78650d commit b20ad3a
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 12 deletions.
55 changes: 55 additions & 0 deletions _test/issue-558.go
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions _test/type20.go
Original file line number Diff line number Diff line change
@@ -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
33 changes: 21 additions & 12 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,56 +121,63 @@ 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
}
}
}

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
}
Expand All @@ -195,13 +202,15 @@ 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
}
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
Expand Down

0 comments on commit b20ad3a

Please sign in to comment.