runtime/secret: fix cgo crashes inside of secret.Do

Fixes #78999

Change-Id: I9fba1fd771f06fc57de1ecb70d9f9cb8bc8078fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/771640
Reviewed-by: Daniel Morsing <daniel.morsing@gmail.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
Neal Patel 2026-04-28 11:21:40 -04:00
parent c8b14e157f
commit 1dd2bef375
3 changed files with 58 additions and 0 deletions

View file

@ -942,6 +942,11 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
JEQ nosecret
CALL ·secretEraseRegisters(SB)
get_tls(CX)
MOVQ g(CX), DI
MOVQ g_m(DI), R8
MOVQ m_g0(R8), SI
nosecret:
#endif
MOVQ fn+0(FP), AX

View file

@ -15,6 +15,7 @@ import (
"internal/testenv"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
@ -118,6 +119,27 @@ func TestCgoCallbackX15(t *testing.T) {
}
}
func TestSecretCgo(t *testing.T) {
t.Parallel()
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
exe := filepath.Join(t.TempDir(), "secretcgo.exe")
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe)
cmd.Dir = "testdata/testprogcgo"
cmd = testenv.CleanCmdEnv(cmd)
cmd.Env = append(cmd.Env, "GOEXPERIMENT=runtimesecret")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("building testprogcgo with runtimesecret: %v\n%s", err, out)
}
got := runBuiltTestProg(t, exe, "SecretCgo")
if want := "OK\n"; got != want {
t.Fatalf("expected %q, got:\n%s", want, got)
}
}
func TestCgoExternalThreadPanic(t *testing.T) {
t.Parallel()
if runtime.GOOS == "plan9" {

View file

@ -0,0 +1,31 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build goexperiment.runtimesecret
package main
/*
static int cAdd(int a, int b) { return a + b; }
*/
import "C"
import (
"fmt"
"runtime/secret"
)
func init() {
register("SecretCgo", SecretCgo)
}
func SecretCgo() {
secret.Do(func() {
r := C.cAdd(1, 2)
if r != 3 {
panic(fmt.Sprintf("got %d, want 3", r))
}
})
fmt.Println("OK")
}