Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encoding/json: Unmarshalling *websocket.Conn over a websocket with JSON crashes #14665

Closed
dolanor opened this issue Mar 6, 2016 · 3 comments

Comments

Projects
None yet
5 participants
@dolanor
Copy link

commented Mar 6, 2016

  1. What version of Go are you using (go version)?
    go version go1.6 linux/amd64
  2. What operating system and processor architecture are you using (go env)?
    GOARCH="amd64"
    GOBIN=""
    GOEXE=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOOS="linux"
    GOPATH="/home/dolanor/.local/gopath/"
    GORACE=""
    GOROOT="/usr/local/go"
    GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
    GO15VENDOREXPERIMENT="1"
    CC="gcc"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
    CXX="g++"
    CGO_ENABLED="1"
  3. What did you do?
    I sent a *websocket.Conn on a websocket in JSON (by pure laziness, without caring about having it on the other side).
  4. What did you expect to see?
    I expected to get unmarshalling kind of working, even if the *websocket.Conn wouldn't work: I didn't really wanted to get this information on the other side, but it was part of a struct I wanted to send over the wire.

If I put this *websocket.Conn to nil, then I don't get problems on the other side.

  1. What did you see instead?
    panic: reflect: reflect.Value.Set using value obtained using unexported field [recovered]
        panic: interface conversion: string is not error: missing method Error

    goroutine 7 [running]:
    panic(0x752c40, 0xc820010680)
        /usr/local/go/src/runtime/panic.go:464 +0x3e6
    encoding/json.(*decodeState).unmarshal.func1(0xc8200dbd98)
        /usr/local/go/src/encoding/json/decode.go:156 +0xba
    panic(0x6c2ba0, 0xc8200e8650)
        /usr/local/go/src/runtime/panic.go:426 +0x4e9
    reflect.flag.mustBeAssignable(0x1d4)
        /usr/local/go/src/reflect/value.go:226 +0x161
    reflect.Value.Set(0x762fa0, 0xc82008c430, 0x1d4, 0x762fa0, 0xc8200e8640, 0x94)
        /usr/local/go/src/reflect/value.go:1328 +0x25
    encoding/json.(*decodeState).literalStore(0xc820106000, 0xc8201040f9, 0x4, 0x507, 0x762fa0, 0xc82008c430, 0x1d4, 0xc8200da700)
        /usr/local/go/src/encoding/json/decode.go:786 +0x3549
    encoding/json.(*decodeState).literal(0xc820106000, 0x762fa0, 0xc82008c430, 0x1d4)
        /usr/local/go/src/encoding/json/decode.go:717 +0xe9
    encoding/json.(*decodeState).value(0xc820106000, 0x762fa0, 0xc82008c430, 0x1d4)
        /usr/local/go/src/encoding/json/decode.go:370 +0x37b
    encoding/json.(*decodeState).object(0xc820106000, 0x7a7320, 0xc82008c3f0, 0x199)
        /usr/local/go/src/encoding/json/decode.go:684 +0x116a
    encoding/json.(*decodeState).value(0xc820106000, 0x7a9260, 0xc820010648, 0x196)
        /usr/local/go/src/encoding/json/decode.go:367 +0x3a1
    encoding/json.(*decodeState).object(0xc820106000, 0x795d40, 0xc820010640, 0x199)
        /usr/local/go/src/encoding/json/decode.go:684 +0x116a
    encoding/json.(*decodeState).value(0xc820106000, 0x7a19e0, 0xc8200c5da0, 0x196)
        /usr/local/go/src/encoding/json/decode.go:367 +0x3a1
    encoding/json.(*decodeState).array(0xc820106000, 0x6c3220, 0xc8200c5d60, 0x197)
        /usr/local/go/src/encoding/json/decode.go:518 +0xa6b
    encoding/json.(*decodeState).value(0xc820106000, 0x6c3220, 0xc8200c5d60, 0x197)
        /usr/local/go/src/encoding/json/decode.go:364 +0x3c1
    encoding/json.(*decodeState).object(0xc820106000, 0x741a80, 0xc8200c5d60, 0x199)
        /usr/local/go/src/encoding/json/decode.go:684 +0x116a
    encoding/json.(*decodeState).value(0xc820106000, 0x6a6400, 0xc820056b78, 0x196)
        /usr/local/go/src/encoding/json/decode.go:367 +0x3a1
    encoding/json.(*decodeState).object(0xc820106000, 0x79e600, 0xc820056b60, 0x199)
        /usr/local/go/src/encoding/json/decode.go:684 +0x116a
    encoding/json.(*decodeState).value(0xc820106000, 0x6a61c0, 0xc820056b60, 0x16)
        /usr/local/go/src/encoding/json/decode.go:367 +0x3a1
    encoding/json.(*decodeState).unmarshal(0xc820106000, 0x6a61c0, 0xc820056b60, 0x0, 0x0)
        /usr/local/go/src/encoding/json/decode.go:168 +0x196
    encoding/json.Unmarshal(0xc820104000, 0x23b, 0x600, 0x6a61c0, 0xc820056b60, 0x0, 0x0)
        /usr/local/go/src/encoding/json/decode.go:96 +0x12b
    golang.org/x/net/websocket.jsonUnmarshal(0xc820104000, 0x23b, 0x600, 0x201, 0x6a61c0, 0xc820056b60, 0x0, 0x0)
        /home/dolanor/.local/gopath/src/golang.org/x/net/websocket/websocket.go:390 +0x57
    golang.org/x/net/websocket.Codec.Receive(0x861560, 0x861568, 0xc82008c240, 0x6a61c0, 0xc820056b60, 0x0, 0x0)
        /home/dolanor/.local/gopath/src/golang.org/x/net/websocket/websocket.go:331 +0x34d

@mikioh mikioh changed the title Unmarshalling *websocket.Conn over a websocket with JSON crashes encoding/json: Unmarshalling *websocket.Conn over a websocket with JSON crashes Apr 3, 2016

@mikioh

This comment has been minimized.

Copy link
Contributor

commented Apr 3, 2016

I have no strong opinion on how unexposed, non-assignable fields should be treated in encoding/json package.

@OneOfOne

This comment has been minimized.

Copy link
Contributor

commented Apr 3, 2016

the json package maybe should just check if a field is exported or not for the internal type cache?

@bradfitz

This comment has been minimized.

Copy link
Member

commented Apr 10, 2016

I am unable to reproduce this.

Do you have a repro?

I tried:

package main

import (
        "encoding/json"
        "fmt"
        "log"

        "golang.org/x/net/websocket"
)

func main() {
        type T struct {
                Foo  string
                conn *websocket.Conn
        }
        t := &T{"bar", new(websocket.Conn)}
        enc, err := json.Marshal(t)
        if err != nil {
                log.Fatalf("Marshal: %v", err)
        }
        var t2 T
        if err := json.Unmarshal(enc, &t2); err != nil {
                log.Fatalf("Unmarshal: %v", err)
        }
        fmt.Printf("%#v\n", t2)
}

But it works at tip, Go 1.6, and Go 1.5 just fine with:

main.T{Foo:"bar", conn:(*websocket.Conn)(nil)}

Let me know and I can reopen this.

@bradfitz bradfitz closed this Apr 10, 2016

@golang golang locked and limited conversation to collaborators Apr 10, 2017

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.