Repository: go
Issue: cmd/link: misc/cgo/test suite crashes on Windows when linked against UCRT with `-linkmode=internal`
Labels: OS-Windows,NeedsInvestigation,compiler/runtime

<!--
Please answer these questions before submitting your issue. Thanks!
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.20.8 windows/amd64
</pre>

### Does this issue reproduce with the latest release?
No. The cgo test suite (moved to package path `cmd/cgo/internal/test`) passes with Go 1.21 when built with `-linkmode=internal` using the same C toolchain.


### 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\ContainerAdministrator\AppData\Local\go-build
set GOENV=C:\Users\ContainerAdministrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.20.8
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=C:\Program Files\Go\misc\go.mod
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\ContainerAdministrator\AppData\Local\Temp\go-build3913134811=/tmp/go-build -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 go.dev/play is best.
-->

```
C:\> docker run --rm -it golang:1.20.8 powershell
PS C:\go> $ProgressPreference='SilentlyContinue'
PS C:\go> Invoke-WebRequest https://github.com/brechtsanders/winlibs_mingw/releases/download/13.2.0-16.0.6-11.0.0-ucrt-r1/winlibs-x86_64-posix-seh-gcc-13.2.0-mingw-w64ucrt-11.0.0-r1.zip -OutFile winlibs-ucrt.zip
PS C:\go> Expand-Archive -Path .\winlibs-ucrt.zip -DestinationPath c:\tools
PS C:\go> $Env:PATH+='C:\tools\mingw64\bin'
PS C:\go> gcc --version
gcc.exe (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

PS C:\go> cd $(go env GOROOT)
PS C:\Program Files\Go> cd .\misc\cgo\test\
PS C:\Program Files\Go\misc\cgo\test> go test -ldflags=-linkmode=internal -tags=internal
```

### What did you expect to see?

```
ok      misc/cgo/test   3.869s
```

### What did you see instead?

```
exit status 0xc0000409
FAIL    misc/cgo/test   2.822s
```

<details><summary><code>go test -v</code></summary>
<p>

``` 
PS C:\Program Files\Go\misc\cgo\test> go test -v -ldflags=-linkmode=internal -tags=internal
=== RUN   Test1328
--- PASS: Test1328 (0.00s)
=== RUN   Test1560
--- PASS: Test1560 (0.00s)
=== RUN   Test1635
scatter = 00000000008522E0
--- PASS: Test1635 (0.00s)
=== RUN   Test3250
    test.go:1277: not applicable on windows
--- SKIP: Test3250 (0.00s)
=== RUN   Test3729
    test.go:1353: skipping on windows
--- SKIP: Test3729 (0.00s)
=== RUN   Test3775
--- PASS: Test3775 (0.00s)
=== RUN   Test4029
--- PASS: Test4029 (0.00s)
=== RUN   Test4339
--- PASS: Test4339 (0.00s)
=== RUN   Test5227
--- PASS: Test5227 (0.00s)
=== RUN   Test5242
--- PASS: Test5242 (0.00s)
=== RUN   Test5337
--- PASS: Test5337 (0.00s)
=== RUN   Test5548
--- PASS: Test5548 (0.00s)
=== RUN   Test5603
--- PASS: Test5603 (0.00s)
=== RUN   Test5986
sqrt is: 0
--- PASS: Test5986 (0.00s)
=== RUN   Test6390
--- PASS: Test6390 (0.00s)
=== RUN   Test6833
--- PASS: Test6833 (0.00s)
=== RUN   Test6907
--- PASS: Test6907 (0.00s)
=== RUN   Test6907Go
--- PASS: Test6907Go (0.00s)
=== RUN   Test7560
--- PASS: Test7560 (0.00s)
=== RUN   Test7665
--- PASS: Test7665 (0.00s)
=== RUN   Test7978
--- PASS: Test7978 (0.67s)
=== RUN   Test8092
--- PASS: Test8092 (0.00s)
=== RUN   Test8517
--- PASS: Test8517 (0.00s)
=== RUN   Test8694
--- PASS: Test8694 (0.00s)
=== RUN   Test8756
--- PASS: Test8756 (0.00s)
=== RUN   Test8811
--- PASS: Test8811 (0.00s)
=== RUN   Test9026
--- PASS: Test9026 (0.00s)
=== RUN   Test9510
--- PASS: Test9510 (0.00s)
=== RUN   Test9557
--- PASS: Test9557 (0.00s)
=== RUN   Test10303
--- PASS: Test10303 (0.00s)
=== RUN   Test11925
--- PASS: Test11925 (0.00s)
=== RUN   Test12030
--- PASS: Test12030 (0.00s)
=== RUN   Test14838
--- PASS: Test14838 (0.00s)
=== RUN   Test17065
--- PASS: Test17065 (0.00s)
=== RUN   Test17537
--- PASS: Test17537 (0.00s)
=== RUN   Test18126
--- PASS: Test18126 (0.00s)
=== RUN   Test18720
--- PASS: Test18720 (0.00s)
=== RUN   Test20129
--- PASS: Test20129 (0.00s)
=== RUN   Test20266
--- PASS: Test20266 (0.00s)
=== RUN   Test20369
--- PASS: Test20369 (0.00s)
=== RUN   Test20910
--- PASS: Test20910 (0.00s)
=== RUN   Test21708
--- PASS: Test21708 (0.00s)
=== RUN   Test21809
--- PASS: Test21809 (0.00s)
=== RUN   Test21897
    issue21897b.go:13: test runs only on darwin+cgo
--- SKIP: Test21897 (0.00s)
=== RUN   Test22906
--- PASS: Test22906 (0.00s)
=== RUN   Test23356
--- PASS: Test23356 (0.00s)
=== RUN   Test24206
    test.go:2028: skipping on windows/amd64
--- SKIP: Test24206 (0.00s)
=== RUN   Test25143
--- PASS: Test25143 (0.00s)
=== RUN   Test26066
--- PASS: Test26066 (0.00s)
=== RUN   Test26213
--- PASS: Test26213 (0.00s)
=== RUN   Test27660
--- PASS: Test27660 (0.63s)
=== RUN   Test28896
--- PASS: Test28896 (0.00s)
=== RUN   Test30065
--- PASS: Test30065 (0.00s)
=== RUN   Test32579
--- PASS: Test32579 (0.00s)
=== RUN   Test31891
--- PASS: Test31891 (0.00s)
=== RUN   Test42018
--- PASS: Test42018 (0.00s)
=== RUN   Test45451
--- PASS: Test45451 (0.00s)
=== RUN   Test49633
--- PASS: Test49633 (0.00s)
=== RUN   TestAlign
--- PASS: TestAlign (0.00s)
=== RUN   TestAtol
--- PASS: TestAtol (0.00s)
=== RUN   TestBlocking
--- PASS: TestBlocking (0.00s)
=== RUN   TestBoolAlign
--- PASS: TestBoolAlign (0.00s)
=== RUN   TestCallGoWithString
--- PASS: TestCallGoWithString (0.00s)
=== RUN   TestCallback
--- PASS: TestCallback (0.00s)
=== RUN   TestCallbackCallers
--- PASS: TestCallbackCallers (0.00s)
=== RUN   TestCallbackGC
--- PASS: TestCallbackGC (0.00s)
=== RUN   TestCallbackPanic
--- PASS: TestCallbackPanic (0.00s)
=== RUN   TestCallbackPanicLocked
--- PASS: TestCallbackPanicLocked (0.00s)
=== RUN   TestCallbackPanicLoop
--- PASS: TestCallbackPanicLoop (0.36s)
=== RUN   TestCallbackStack
--- PASS: TestCallbackStack (0.01s)
=== RUN   TestCflags
--- PASS: TestCflags (0.00s)
=== RUN   TestCheckConst
--- PASS: TestCheckConst (0.00s)
=== RUN   TestConst
--- PASS: TestConst (0.00s)
=== RUN   TestCthread
--- PASS: TestCthread (0.00s)
=== RUN   TestEnum
--- PASS: TestEnum (0.00s)
=== RUN   TestNamedEnum
--- PASS: TestNamedEnum (0.00s)
=== RUN   TestCastToEnum
--- PASS: TestCastToEnum (0.00s)
=== RUN   TestErrno
--- PASS: TestErrno (0.00s)
=== RUN   TestFpVar
--- PASS: TestFpVar (0.00s)
=== RUN   TestGCC68255
--- PASS: TestGCC68255 (0.00s)
=== RUN   TestHandle
--- PASS: TestHandle (0.00s)
=== RUN   TestHelpers
--- PASS: TestHelpers (0.00s)
=== RUN   TestLibgcc
--- PASS: TestLibgcc (0.00s)
=== RUN   TestMultipleAssign
exit status 0xc0000409
FAIL    misc/cgo/test   3.012s
```

</p>
</details>

<details><summary><code>gdb</code> session</summary>
<p>

```
PS C:\Program Files\Go\misc\cgo\test> go test -ldflags=-linkmode=internal -tags=internal -c
PS C:\Program Files\Go\misc\cgo\test> gdb -iex 'set auto-load safe-path /' test.test.exe
GNU gdb (GDB for MinGW-W64 x86_64, built by Brecht Sanders) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-w64-mingw32".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test.test.exe...
Loading Go Runtime support.
(gdb) r -test.run TestMultipleAssign
Starting program: C:\Program Files\Go\misc\cgo\test\test.test.exe -test.run TestMultipleAssign
[New Thread 6928.0x21b4]
[New Thread 6928.0x1828]
[New Thread 6928.0x7f8]
[New Thread 6928.0x1188]
[New Thread 6928.0x1624]
[New Thread 6928.0x21e0]
[New Thread 6928.0x17c0]
gdb: unknown target exception 0xc0000409 at 0x7ffad467b3a8

Thread 1 received signal ?, Unknown signal.
0x00007ffad467b3a8 in ucrtbase!_invoke_watson () from C:\Windows\System32\ucrtbase.dll
(gdb) bt
#0  0x00007ffad467b3a8 in ucrtbase!_invoke_watson () from C:\Windows\System32\ucrtbase.dll
#1  0x00007ffad4660854 in ucrtbase!log2f () from C:\Windows\System32\ucrtbase.dll
#2  0x00007ffad4652e20 in ucrtbase!.intrinsic_setjmpex () from C:\Windows\System32\ucrtbase.dll
#3  0x00007ffad461ff0c in ucrtbase!strtol () from C:\Windows\System32\ucrtbase.dll
#4  0x0000000000c03822 in _cgo_0b47cc75cb3f_Cfunc_strtol ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
```

</p>
</details> 

The cgo test suite passes with `-linkmode=internal` when the MSVCRT runtime variant of the same MinGW-W64 toolchain is used.

The impact of this issue is minimal. External linking would be a viable workaround for those who need [to match up C runtime versions for compatibility with third-party DLLs](https://learn.microsoft.com/en-us/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries). And for those of us (like myself) who are building Go from source and are needing to get `go tool dist test` to pass, switching to a MinGW that links against MSVCRT when building the Go toolchain is a viable workaround as no pre-compiled native code is required in binary distributions of Go 1.20.