Closed odeke-em closed 4 years ago
Good find.
That is a big test struct. Can you remove parts of it until there is a minimal testcase? I assume it is from one of the name or payment strings, but which?
Thanks odeke-em. Agreed that a minimal test case will help. Will you be taking this on or should we?
Sorry for the late replies @ethanfrey and @aaronc!
The offending payment string is "«íC∆ù≈≠Âííp\u0026«∏Á∂∏N√X8i�£ùuq". But in retrospect, the thing might be that what produced that string is a fuzz mutation of the actual byte content directly, so perhaps we might be chasing an issue that can't be reproduced.
The offending bytes have a control character ^X
and here is something that can point towards the fault in it: a use of "%q" to serialize strings for JSON. This playground link https://play.golang.org/p/EuWm_nXDSDk or inlined below
package main
import (
"encoding/json"
"fmt"
)
func main() {
// The original string: "«íC∆ù≈≠Âííp\u0026«∏Á∂∏N√X8i£ùuq"
b := []byte("«íC∆ù≈≠Âííp\u0026«∏Á∂∏N√X8i£ùuq")
type Customer struct {
Payment string
}
c1 := &Customer{Payment: string(b)}
fmt.Printf("%#v\n", c1)
blob, err := json.Marshal(c1)
if err != nil {
panic(err)
}
cs := new(Customer)
if err := json.Unmarshal(blob, &cs); err != nil {
panic(err)
}
fmt.Printf("%#v\nOK: %t\n", cs, cs.Payment == string(b))
var g string
dx := fmt.Sprintf("%q", b)
if err := json.Unmarshal([]byte(dx), &g); err != nil {
panic(err)
}
fmt.Printf("G: %#v\n", g)
}
Shows where it errors, so we just need to audit JSON serializing code to ensure that we don't invoke fmt.Sprintf("%q", str)
to JSON serialize strings, and if there are no instances, we can safely then close this bug. To examine the bytes unhindered by the poor rendering of Github's output, please visit the Gist or the raw contents of this message.
I took sometime today to investigate this code in every possible code path, and given that in this library we use jsonpb, which invokes encoding/json, I've examined all the code paths and this seems unlikely. We arrived to this path because:
The only way that this problem can ever happen is if someone uses "%q" to mistakenly JSON marshal a string, but there isn't ANY code path that uses "%q" so not a problem.
The code to generate the structs as corpus is here under "details"
My apologies, we can close this as false positive.
Summary of Bug
Coming here from fuzzing ProtoCodec, I generated a serialized version of a struct that was successfully produced by ProtoCodec.MarshalJSON'd Given this JSON that was created from a fuzzed struct
and the following program to unmarshal it and compare
where proto definitions in testutil/testdata/proto.proto are
Running this program produces
Version
928f7fccff1d574c5a23f3584e539aae74c8406a
For Admin Use