Skip to content

expvar: Map.String can make invalid JSON with low ASCII bytes #59040

@bradfitz

Description

@bradfitz

Go 1.20:

https://go.dev/play/p/b0A7ivMg0wn

func main() {
	m := expvar.NewMap("foo")
	m.Add("\x01", 1)
	fmt.Println(m.String())

	out := map[string]int64{}
	err := json.Unmarshal([]byte(m.String()), &out)
	if err != nil {
		log.Fatal(err)
	}
}

=>

{"\x01": 1}
2009/11/10 23:00:00 invalid character 'x' in string escape code

The (*expvar.Map).String method is implemented using fmt %q to print strings:

func (v *Map) String() string {
	var b strings.Builder
	fmt.Fprintf(&b, "{")
	first := true
	v.Do(func(kv KeyValue) {
		if !first {
			fmt.Fprintf(&b, ", ")
		}
		fmt.Fprintf(&b, "%q: ", kv.Key)
		if kv.Value != nil {
			fmt.Fprintf(&b, "%v", kv.Value)
		} else {
			fmt.Fprint(&b, "null")
		}
		first = false
	})
	fmt.Fprintf(&b, "}")
	return b.String()
}

But Go's %q doesn't make valid JSON when there are bytes under 0x20.

/cc @dsnet @maisem

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions