Skip to content

cmd/compile: order mishandles "defer delete(m, k)" when k is a "slow" map key type #24259

@mdempsky

Description

@mdempsky

https://play.golang.org/p/2JNMRctSmRr

The above program prints "3\n2\n", but it should print "3\n0\n". (And it does if K is changed to a "fast" map key type like uint32.)

The problem is that, for "slow" map key types, order.go rewrites

defer delete(m, k)

into

ktmp := k
defer mapdelete(m, &ktmp)

but we never mark ktmp as escaping (because escape analysis happens earlier). So in the playground example above, this loop:

for _, k := range ks {
	defer delete(m, k)
}

is effectively rewritten into:

    var ktmp K
    for _, k := range ks {
            ktmp = k
            defer delete(m, &ktmp)
    }

So when the defers finally execute at function return, they all try to delete the last k value.

A similar issue affects go delete(m, k), but there's no way to use this construct in legitimate code.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions