Repository: go
Issue: debug/macho: panic on invalid dynamic symbol table command with overflowing
Labels: NeedsFix

These days I'm learning how to fix this vulnerability `CVE-2021-41771` at [issue #48990](https://github.com/golang/go/issues/48990) and [CL355990](https://go-review.googlesource.com/c/go/+/355990/). 

I noticed that the variables `hdr.Iundefsym` and `hdr.Nundefsym` are read directly from the macho executable.

Therefore, based on the existing test files, I constructed a new test file, where `hdr.Iundefsym=9`, `hdr.Nundefsym=0xFF_FF_FF_FF`, the overflow after addition is `8`, but `uint32(len(f.Symtab.Syms))==11`.

The judgment condition `hdr.Iundefsym+hdr.Nundefsym > uint32(len(f.Symtab.Syms))` in the  [CL355990](https://go-review.googlesource.com/c/go/+/355990/)  can be bypassed due to integer addition overflow. 

Therefore, panic will still occur when calling `ImportedSymbols()` method.

This seems to be the same level of security problem as `CVE-2021-41771`.

The new test file was provided in this zip file: 
[testdata.zip](https://github.com/golang/go/files/7600096/testdata.zip)

<!--
Please answer these questions before submitting your issue. Thanks!
For questions please use one of our forums: https://github.com/golang/go/wiki/Questions
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.17.3 windows/amd64
</pre>
### Does this issue reproduce with the latest release?

Yes

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\ZJ\AppData\Local\go-build
set GOENV=C:\Users\ZJ\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=E:\Code\Go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=E:\Code\Go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn
set GOROOT=E:\Code\Go\go\go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=E:\Code\Go\go\go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.16.4
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=E:\Code\Go\go\go\src\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fmessage-length=0 -fdebug-prefix-map=C:\Users\ZJ\AppData\Local\Temp\go-build488652189=/tmp/go-bui
ld -gno-record-gcc-switches
</pre></details>

### What did you do?

<!--
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.
-->

Use the newly constructed test file and run the test in the `debug/macho` Directory:

```
func TestOpenBadDysymCmd2(t *testing.T) {
	f, err := openObscured("testdata/gcc-amd64-darwin-exec-with-bad-dysym-2.base64")
	if err == nil {
		f.ImportedSymbols()
		return
	}
	if _, ok := err.(*FormatError); !ok {
		t.Fatalf("opening invalid dynamic symbol table command file got %v, want FormatError", err)
	}
}
```

### What did you expect to see?

Test PASS

### What did you see instead?

```bash
panic: runtime error: slice bounds out of range [9:8] [recovered]
        panic: runtime error: slice bounds out of range [9:8]

goroutine 6 [running]:
testing.tRunner.func1.2({0x52c5a0, 0xc0000142b8})
        E:/Code/Go/go/go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
        E:/Code/Go/go/go/src/testing/testing.go:1212 +0x218
panic({0x52c5a0, 0xc0000142b8})
        E:/Code/Go/go/go/src/runtime/panic.go:1038 +0x215
debug/macho.(*File).ImportedSymbols(0x543ab6)
        E:/Code/Go/go/go/src/debug/macho/file.go:685 +0x1cb
debug/macho.TestOpenBadDysymCmd2(0xc00002fba0)
        E:/Code/Go/go/go/src/debug/macho/file_test.go:440 +0x8c
testing.tRunner(0xc00002fba0, 0x5454e0)
        E:/Code/Go/go/go/src/testing/testing.go:1259 +0x102
created by testing.(*T).Run
        E:/Code/Go/go/go/src/testing/testing.go:1306 +0x35a
```