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

cmd/compile: Type confusion vulnerability on identically named generic structs #54456

Closed
polarina opened this issue Aug 15, 2022 · 4 comments
Closed
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. generics Issue is related to generics NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@polarina
Copy link
Contributor

polarina commented Aug 15, 2022

What version of Go are you using (go version)?

$ go version
go version go1.19 linux/amd64

Does this issue reproduce with the latest release?

This issue affects the latest version. I have tested Go 1.18 and Go 1.18.5, in addition to Go 1.19, both of which are affected as well.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/mce-gabrielp/.cache/go-build"
GOENV="/home/mce-gabrielp/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/mce-gabrielp/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/mce-gabrielp/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.19"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3251415554=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Compile and execute the following program: https://go.dev/play/p/54u9Z1S7oUZ

package main

import "fmt"

func foo() {
	type data[T any] struct {
		A T
		B []T
	}

	v := data[int]{}
	fmt.Println(v)
}

func bar() {
	type data[T any] struct {
		A T
	}

	v := data[int]{}
	fmt.Println(v)
}

func main() {
	foo()
	bar()
}

What did you expect to see?

The following output:

$ go run repro.go 
{0 []}
{0}

What did you see instead?

$ go run repro.go 
{0 []}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x1 pc=0x45dd49]

goroutine 1 [running]:
reflect.typedmemmove(0xc0000061a0?, 0x487de0?, 0x47de01?)
	/usr/local/go/src/runtime/mbarrier.go:191 +0x19
reflect.packEface({0x488ae0?, 0x1?, 0x0?})
	/usr/local/go/src/reflect/value.go:123 +0x65
reflect.valueInterface({0x488ae0?, 0x1?, 0x0?}, 0x30?)
	/usr/local/go/src/reflect/value.go:1508 +0xbb
reflect.Value.Interface(...)
	/usr/local/go/src/reflect/value.go:1478
fmt.(*pp).printValue(0xc00010c270, {0x488ae0?, 0x1?, 0x4?}, 0x76, 0x2)
	/usr/local/go/src/fmt/print.go:753 +0xa5
fmt.(*pp).printValue(0xc00010c270, {0x487de0?, 0x51c7a8?, 0x441186?}, 0x76, 0x1)
	/usr/local/go/src/fmt/print.go:896 +0x16b2
fmt.(*pp).printValue(0xc00010c270, {0x48e280?, 0x51c7a0?, 0x7?}, 0x76, 0x0)
	/usr/local/go/src/fmt/print.go:837 +0x12b4
fmt.(*pp).printArg(0xc00010c270, {0x48e280?, 0x51c7a0}, 0x76)
	/usr/local/go/src/fmt/print.go:743 +0x756
fmt.(*pp).doPrintln(0xc00010c270, {0xc000104f50?, 0x1, 0x0?})
	/usr/local/go/src/fmt/print.go:1200 +0x150
fmt.Fprintln({0x4b8008, 0xc000012018}, {0xc000104f50, 0x1, 0x1})
	/usr/local/go/src/fmt/print.go:284 +0x4f
fmt.Println(...)
	/usr/local/go/src/fmt/print.go:294
main.bar()
	/home/mce-gabrielp/repro.go:23 +0x5e
main.main()
	/home/mce-gabrielp/repro.go:28 +0x1c
exit status 2
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Aug 15, 2022
@cuonglm cuonglm added the generics Issue is related to generics label Aug 15, 2022
@cuonglm cuonglm added this to the Go1.20 milestone Aug 15, 2022
@cuonglm
Copy link
Member

cuonglm commented Aug 15, 2022

It run ok with Unified IR.

@randall77
Copy link
Contributor

randall77 commented Aug 15, 2022

Yeah, we need to add uniqifiers to the names of internal types when they are generic.

There's an easy workaround, make the names unique yourself. So probably not worth backporting. So this may be a case where we just wait for unified IR to fix it.

@joedian joedian added the NeedsFix The path to resolution is known, but the work has not been done. label Aug 15, 2022
@mdempsky
Copy link
Member

mdempsky commented Aug 18, 2022

Unified IR correctly handles the type identity here, but the scope disambiguation number is ending up visible in the rtype info.

This program should print *main.T *main.T[int]:

package main

import "fmt"

func one() any { type T int; return new(T) }
func two() any { type T[_ any] int; return new(T[int]) }

func main() {
	fmt.Printf("%T %T\n", one(), two())
}

It does correctly with GOEXPERIMENT=nounified. But with GOEXPERIMENT=unified, it prints *main.T *main.T·2[int].

I think it's because this code in types/fmt.go only knows to trim the dot suffix from the end of the symbol:

// In unified IR, function-scope defined types will have a ·N
// suffix embedded directly in their Name. Trim this off for
// non-fmtTypeID modes.
sym := t.Sym()
if mode != fmtTypeID {
i := len(sym.Name)
for i > 0 && sym.Name[i-1] >= '0' && sym.Name[i-1] <= '9' {
i--
}
const dot = "·"
if i >= len(dot) && sym.Name[i-len(dot):i] == dot {
sym = &Sym{Pkg: sym.Pkg, Name: sym.Name[:i-len(dot)]}
}
}
sconv2(b, sym, verb, mode)

The easiest, most robust solution is to change unified IR's mangling to use main.T[int]·2 instead.

Alternatively, types/fmt.go could know to look for the dot-suffix in the middle of the name, not just at the end. But I worry that has subtle failure cases when anonymous struct types are present (because of struct tags).

@gopherbot
Copy link

gopherbot commented Aug 18, 2022

Change https://go.dev/cl/424901 mentions this issue: cmd/compile: fix reflect naming of local generic types

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. generics Issue is related to generics NeedsFix The path to resolution is known, but the work has not been done.
Projects
Status: Done
Development

No branches or pull requests

6 participants