@ttsc/darwin-arm64 0.13.0 → 0.14.0-dev.20260528
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/go/VERSION +2 -2
- package/bin/go/bin/go +0 -0
- package/bin/go/bin/gofmt +0 -0
- package/bin/go/pkg/tool/darwin_arm64/asm +0 -0
- package/bin/go/pkg/tool/darwin_arm64/cgo +0 -0
- package/bin/go/pkg/tool/darwin_arm64/compile +0 -0
- package/bin/go/pkg/tool/darwin_arm64/cover +0 -0
- package/bin/go/pkg/tool/darwin_arm64/fix +0 -0
- package/bin/go/pkg/tool/darwin_arm64/link +0 -0
- package/bin/go/pkg/tool/darwin_arm64/preprofile +0 -0
- package/bin/go/pkg/tool/darwin_arm64/vet +0 -0
- package/bin/go/src/archive/tar/format.go +0 -6
- package/bin/go/src/archive/tar/reader.go +4 -24
- package/bin/go/src/builtin/builtin.go +4 -13
- package/bin/go/src/crypto/fips140/fips140.go +0 -6
- package/bin/go/src/crypto/internal/fips140/drbg/rand.go +75 -1
- package/bin/go/src/crypto/tls/conn.go +3 -7
- package/bin/go/src/crypto/tls/handshake_client_tls13.go +2 -2
- package/bin/go/src/crypto/tls/handshake_server_tls13.go +2 -2
- package/bin/go/src/crypto/tls/key_schedule.go +3 -24
- package/bin/go/src/crypto/x509/constraints.go +33 -33
- package/bin/go/src/crypto/x509/verify.go +13 -28
- package/bin/go/src/go/types/builtins.go +2 -2
- package/bin/go/src/go/types/signature.go +0 -3
- package/bin/go/src/go/types/under.go +3 -3
- package/bin/go/src/go.mod +1 -1
- package/bin/go/src/go.sum +2 -2
- package/bin/go/src/html/template/attr_string.go +2 -3
- package/bin/go/src/html/template/context.go +1 -21
- package/bin/go/src/html/template/element_string.go +2 -3
- package/bin/go/src/html/template/escape.go +2 -16
- package/bin/go/src/html/template/js.go +0 -1
- package/bin/go/src/html/template/state_string.go +3 -5
- package/bin/go/src/html/template/transition.go +6 -43
- package/bin/go/src/internal/buildcfg/zbootstrap.go +1 -1
- package/bin/go/src/internal/godebugs/table.go +0 -1
- package/bin/go/src/internal/poll/fd_windows.go +38 -64
- package/bin/go/src/internal/poll/sendfile_windows.go +1 -3
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_386.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_amd64.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm64.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_loong64.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mips64x.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mipsx.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_ppc64x.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_riscv64.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/defs_linux_s390x.go +0 -1
- package/bin/go/src/internal/runtime/syscall/linux/syscall_linux.go +0 -14
- package/bin/go/src/internal/syscall/unix/at.go +17 -0
- package/bin/go/src/internal/syscall/unix/at_sysnum_linux.go +1 -2
- package/bin/go/src/internal/syscall/windows/at_windows.go +3 -20
- package/bin/go/src/internal/syscall/windows/registry/key.go +2 -10
- package/bin/go/src/internal/syscall/windows/registry/value.go +1 -5
- package/bin/go/src/internal/syscall/windows/syscall_windows.go +0 -4
- package/bin/go/src/internal/syscall/windows/types_windows.go +0 -82
- package/bin/go/src/internal/syscall/windows/zsyscall_windows.go +0 -27
- package/bin/go/src/net/cgo_unix.go +1 -4
- package/bin/go/src/net/http/doc.go +1 -0
- package/bin/go/src/net/http/h2_bundle.go +3 -3
- package/bin/go/src/net/http/httputil/reverseproxy.go +0 -14
- package/bin/go/src/net/lookup_windows.go +3 -16
- package/bin/go/src/net/mail/message.go +9 -20
- package/bin/go/src/net/sendfile.go +0 -2
- package/bin/go/src/net/sendfile_stub.go +0 -2
- package/bin/go/src/net/sendfile_windows.go +0 -3
- package/bin/go/src/net/url/url.go +16 -22
- package/bin/go/src/os/dir_darwin.go +2 -2
- package/bin/go/src/os/dir_unix.go +2 -2
- package/bin/go/src/os/file.go +3 -0
- package/bin/go/src/os/file_unix.go +5 -9
- package/bin/go/src/os/removeall_at.go +2 -6
- package/bin/go/src/os/removeall_unix.go +8 -0
- package/bin/go/src/os/removeall_windows.go +4 -0
- package/bin/go/src/os/root_unix.go +0 -1
- package/bin/go/src/os/stat.go +0 -3
- package/bin/go/src/reflect/value.go +2 -3
- package/bin/go/src/runtime/defs_linux_386.go +3 -4
- package/bin/go/src/runtime/defs_linux_arm.go +3 -4
- package/bin/go/src/runtime/defs_linux_mips64x.go +1 -1
- package/bin/go/src/runtime/defs_linux_mipsx.go +4 -5
- package/bin/go/src/runtime/malloc.go +53 -1
- package/bin/go/src/runtime/mem.go +9 -104
- package/bin/go/src/runtime/metrics/doc.go +0 -5
- package/bin/go/src/runtime/os_linux.go +0 -62
- package/bin/go/src/runtime/os_linux32.go +24 -14
- package/bin/go/src/runtime/os_linux64.go +0 -2
- package/bin/go/src/runtime/print.go +4 -16
- package/bin/go/src/runtime/race/README +9 -9
- package/bin/go/src/runtime/race/internal/amd64v1/race_darwin.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_freebsd.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_linux.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v1/race_windows.syso +0 -0
- package/bin/go/src/runtime/race/internal/amd64v3/race_linux.syso +0 -0
- package/bin/go/src/runtime/race/race_darwin_arm64.syso +0 -0
- package/bin/go/src/runtime/race/race_linux_arm64.syso +0 -0
- package/bin/go/src/runtime/race/race_linux_loong64.syso +0 -0
- package/bin/go/src/runtime/race/race_linux_s390x.syso +0 -0
- package/bin/go/src/syscall/syscall_windows.go +1 -5
- package/bin/go/src/vendor/modules.txt +1 -1
- package/bin/ttsc +0 -0
- package/bin/ttscserver +0 -0
- package/package.json +2 -2
- package/bin/go/src/crypto/internal/fips140/drbg/entropy_fips140.go +0 -97
- package/bin/go/src/crypto/internal/fips140/drbg/entropy_wasm.go +0 -11
- package/bin/go/src/internal/poll/fstatat_unix.go +0 -22
- package/bin/go/src/internal/syscall/unix/fchmodat_linux.go +0 -51
- package/bin/go/src/internal/syscall/unix/fchmodat_other.go +0 -29
- package/bin/go/src/os/statat.go +0 -24
- package/bin/go/src/os/statat_other.go +0 -12
- package/bin/go/src/os/statat_unix.go +0 -20
- package/bin/go/src/runtime/race/internal/amd64v1/race_darwin.patch +0 -63
- package/bin/go/src/runtime/race/internal/amd64v1/race_freebsd.patch +0 -63
- package/bin/go/src/runtime/race/internal/amd64v1/race_linux.patch +0 -63
- package/bin/go/src/runtime/race/internal/amd64v1/race_windows.patch +0 -63
- package/bin/go/src/runtime/race/internal/amd64v3/race_linux.patch +0 -63
- package/bin/go/src/runtime/race/race_darwin_arm64.patch +0 -63
- package/bin/go/src/runtime/race/race_linux_arm64.patch +0 -63
- package/bin/go/src/runtime/race/race_linux_loong64.patch +0 -63
- package/bin/go/src/runtime/race/race_linux_s390x.patch +0 -63
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/darwin-arm64",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "macOS arm64 native
|
|
3
|
+
"version": "0.14.0-dev.20260528",
|
|
4
|
+
"description": "macOS arm64 native ttsc/ttscserver binaries and bundled Go compiler for ttsc.",
|
|
5
5
|
"os": [
|
|
6
6
|
"darwin"
|
|
7
7
|
],
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build !wasm
|
|
6
|
-
|
|
7
|
-
// This file contains reading from from entropy sources in FIPS-140
|
|
8
|
-
// mode. It uses a scratch buffer in the BSS section (see below),
|
|
9
|
-
// which usually doesn't cost much, except on Wasm, due to the way
|
|
10
|
-
// the linear memory works. FIPS-140 mode is not supported on Wasm,
|
|
11
|
-
// so we just use a build tag to exclude it. (Could also exclude other
|
|
12
|
-
// platforms that does not support FIPS-140 mode, but as the BSS
|
|
13
|
-
// variable doesn't cost much, don't bother.)
|
|
14
|
-
|
|
15
|
-
package drbg
|
|
16
|
-
|
|
17
|
-
import (
|
|
18
|
-
entropy "crypto/internal/entropy/v1.0.0"
|
|
19
|
-
"crypto/internal/sysrand"
|
|
20
|
-
"sync"
|
|
21
|
-
"sync/atomic"
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
// memory is a scratch buffer that is accessed between samples by the entropy
|
|
25
|
-
// source to expose it to memory access timings.
|
|
26
|
-
//
|
|
27
|
-
// We reuse it and share it between Seed calls to avoid the significant (~500µs)
|
|
28
|
-
// cost of zeroing a new allocation every time. The entropy source accesses it
|
|
29
|
-
// using atomics (and doesn't care about its contents).
|
|
30
|
-
//
|
|
31
|
-
// It should end up in the .noptrbss section, and become backed by physical pages
|
|
32
|
-
// at first use. This ensures that programs that do not use the FIPS 140-3 module
|
|
33
|
-
// do not incur any memory use or initialization penalties.
|
|
34
|
-
var memory entropy.ScratchBuffer
|
|
35
|
-
|
|
36
|
-
func getEntropy() *[SeedSize]byte {
|
|
37
|
-
var retries int
|
|
38
|
-
seed, err := entropy.Seed(&memory)
|
|
39
|
-
for err != nil {
|
|
40
|
-
// The CPU jitter-based SP 800-90B entropy source has a non-negligible
|
|
41
|
-
// chance of failing the startup health tests.
|
|
42
|
-
//
|
|
43
|
-
// Each time it does, it enters a permanent failure state, and we
|
|
44
|
-
// restart it anew. This is not expected to happen more than a few times
|
|
45
|
-
// in a row.
|
|
46
|
-
if retries++; retries > 100 {
|
|
47
|
-
panic("fips140/drbg: failed to obtain initial entropy")
|
|
48
|
-
}
|
|
49
|
-
seed, err = entropy.Seed(&memory)
|
|
50
|
-
}
|
|
51
|
-
return &seed
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// getEntropy is very slow (~500µs), so we don't want it on the hot path.
|
|
55
|
-
// We keep both a persistent DRBG instance and a pool of additional instances.
|
|
56
|
-
// Occasional uses will use drbgInstance, even if the pool was emptied since the
|
|
57
|
-
// last use. Frequent concurrent uses will fill the pool and use it.
|
|
58
|
-
var drbgInstance atomic.Pointer[Counter]
|
|
59
|
-
var drbgPool = sync.Pool{
|
|
60
|
-
New: func() any {
|
|
61
|
-
return NewCounter(getEntropy())
|
|
62
|
-
},
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
func readFromEntropy(b []byte) {
|
|
66
|
-
// At every read, 128 random bits from the operating system are mixed as
|
|
67
|
-
// additional input, to make the output as strong as non-FIPS randomness.
|
|
68
|
-
// This is not credited as entropy for FIPS purposes, as allowed by Section
|
|
69
|
-
// 8.7.2: "Note that a DRBG does not rely on additional input to provide
|
|
70
|
-
// entropy, even though entropy could be provided in the additional input".
|
|
71
|
-
additionalInput := new([SeedSize]byte)
|
|
72
|
-
sysrand.Read(additionalInput[:16])
|
|
73
|
-
|
|
74
|
-
drbg := drbgInstance.Swap(nil)
|
|
75
|
-
if drbg == nil {
|
|
76
|
-
drbg = drbgPool.Get().(*Counter)
|
|
77
|
-
}
|
|
78
|
-
defer func() {
|
|
79
|
-
if !drbgInstance.CompareAndSwap(nil, drbg) {
|
|
80
|
-
drbgPool.Put(drbg)
|
|
81
|
-
}
|
|
82
|
-
}()
|
|
83
|
-
|
|
84
|
-
for len(b) > 0 {
|
|
85
|
-
size := min(len(b), maxRequestSize)
|
|
86
|
-
if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired {
|
|
87
|
-
// See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in
|
|
88
|
-
// Section 9.3.2: if Generate reports a reseed is required, the
|
|
89
|
-
// additional input is passed to Reseed along with the entropy and
|
|
90
|
-
// then nulled before the next Generate call.
|
|
91
|
-
drbg.Reseed(getEntropy(), additionalInput)
|
|
92
|
-
additionalInput = nil
|
|
93
|
-
continue
|
|
94
|
-
}
|
|
95
|
-
b = b[size:]
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build wasm
|
|
6
|
-
|
|
7
|
-
package drbg
|
|
8
|
-
|
|
9
|
-
func readFromEntropy(b []byte) {
|
|
10
|
-
panic("FIPS-140 entropy generation is not supported on Wasm")
|
|
11
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build unix || wasip1
|
|
6
|
-
|
|
7
|
-
package poll
|
|
8
|
-
|
|
9
|
-
import (
|
|
10
|
-
"internal/syscall/unix"
|
|
11
|
-
"syscall"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
func (fd *FD) Fstatat(name string, s *syscall.Stat_t, flags int) error {
|
|
15
|
-
if err := fd.incref(); err != nil {
|
|
16
|
-
return err
|
|
17
|
-
}
|
|
18
|
-
defer fd.decref()
|
|
19
|
-
return ignoringEINTR(func() error {
|
|
20
|
-
return unix.Fstatat(fd.Sysfd, name, s, flags)
|
|
21
|
-
})
|
|
22
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build linux
|
|
6
|
-
|
|
7
|
-
package unix
|
|
8
|
-
|
|
9
|
-
import (
|
|
10
|
-
"internal/strconv"
|
|
11
|
-
"syscall"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
|
|
15
|
-
// On Linux, the fchmodat syscall silently ignores the AT_SYMLINK_NOFOLLOW flag.
|
|
16
|
-
// We need to use fchmodat2 instead.
|
|
17
|
-
// syscall.Fchmodat handles this.
|
|
18
|
-
if err := syscall.Fchmodat(dirfd, path, mode, flags); err != syscall.EOPNOTSUPP {
|
|
19
|
-
return err
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// This kernel doesn't appear to support fchmodat2 (added in Linux 6.6).
|
|
23
|
-
// We can't fall back to Fchmod, because it requires write permissions on the file.
|
|
24
|
-
// Instead, use the same workaround as GNU libc and musl, which is to open the file
|
|
25
|
-
// and then fchmodat the FD in /proc/self/fd.
|
|
26
|
-
// See: https://lwn.net/Articles/939217/
|
|
27
|
-
fd, err := Openat(dirfd, path, O_PATH|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0)
|
|
28
|
-
if err != nil {
|
|
29
|
-
return err
|
|
30
|
-
}
|
|
31
|
-
defer syscall.Close(fd)
|
|
32
|
-
procPath := "/proc/self/fd/" + strconv.Itoa(fd)
|
|
33
|
-
|
|
34
|
-
// Check to see if this file is a symlink.
|
|
35
|
-
// (We passed O_NOFOLLOW above, but O_PATH|O_NOFOLLOW will open a symlink.)
|
|
36
|
-
var st syscall.Stat_t
|
|
37
|
-
if err := syscall.Stat(procPath, &st); err != nil {
|
|
38
|
-
if err == syscall.ENOENT {
|
|
39
|
-
// /proc has probably not been mounted. Give up.
|
|
40
|
-
return syscall.EOPNOTSUPP
|
|
41
|
-
}
|
|
42
|
-
return err
|
|
43
|
-
}
|
|
44
|
-
if st.Mode&syscall.S_IFMT == syscall.S_IFLNK {
|
|
45
|
-
// fchmodat on the proc FD for a symlink apparently gives inconsistent
|
|
46
|
-
// results, so just refuse to try.
|
|
47
|
-
return syscall.EOPNOTSUPP
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return syscall.Fchmodat(AT_FDCWD, procPath, mode, flags&^AT_SYMLINK_NOFOLLOW)
|
|
51
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build dragonfly || freebsd || netbsd || (openbsd && mips64)
|
|
6
|
-
|
|
7
|
-
package unix
|
|
8
|
-
|
|
9
|
-
import (
|
|
10
|
-
"syscall"
|
|
11
|
-
"unsafe"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
|
|
15
|
-
p, err := syscall.BytePtrFromString(path)
|
|
16
|
-
if err != nil {
|
|
17
|
-
return err
|
|
18
|
-
}
|
|
19
|
-
_, _, errno := syscall.Syscall6(fchmodatTrap,
|
|
20
|
-
uintptr(dirfd),
|
|
21
|
-
uintptr(unsafe.Pointer(p)),
|
|
22
|
-
uintptr(mode),
|
|
23
|
-
uintptr(flags),
|
|
24
|
-
0, 0)
|
|
25
|
-
if errno != 0 {
|
|
26
|
-
return errno
|
|
27
|
-
}
|
|
28
|
-
return nil
|
|
29
|
-
}
|
package/bin/go/src/os/statat.go
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build !windows
|
|
6
|
-
|
|
7
|
-
package os
|
|
8
|
-
|
|
9
|
-
import (
|
|
10
|
-
"internal/testlog"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
func (f *File) lstatat(name string) (FileInfo, error) {
|
|
14
|
-
if stathook != nil {
|
|
15
|
-
fi, err := stathook(f, name)
|
|
16
|
-
if fi != nil || err != nil {
|
|
17
|
-
return fi, err
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
if log := testlog.Logger(); log != nil {
|
|
21
|
-
log.Stat(joinPath(f.Name(), name))
|
|
22
|
-
}
|
|
23
|
-
return f.lstatatNolog(name)
|
|
24
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build (js && wasm) || plan9
|
|
6
|
-
|
|
7
|
-
package os
|
|
8
|
-
|
|
9
|
-
func (f *File) lstatatNolog(name string) (FileInfo, error) {
|
|
10
|
-
// These platforms don't have fstatat, so use stat instead.
|
|
11
|
-
return Lstat(f.name + "/" + name)
|
|
12
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 The Go Authors. All rights reserved.
|
|
2
|
-
// Use of this source code is governed by a BSD-style
|
|
3
|
-
// license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
//go:build aix || darwin || dragonfly || freebsd || wasip1 || linux || netbsd || openbsd || solaris
|
|
6
|
-
|
|
7
|
-
package os
|
|
8
|
-
|
|
9
|
-
import (
|
|
10
|
-
"internal/syscall/unix"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
func (f *File) lstatatNolog(name string) (FileInfo, error) {
|
|
14
|
-
var fs fileStat
|
|
15
|
-
if err := f.pfd.Fstatat(name, &fs.sys, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
|
16
|
-
return nil, f.wrapErr("fstatat", err)
|
|
17
|
-
}
|
|
18
|
-
fillFileStatFromSys(&fs, name)
|
|
19
|
-
return &fs, nil
|
|
20
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
-
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
-
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
-
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
-
|
|
6
|
-
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
-
first initialized when the first event is added to the trace, via the
|
|
8
|
-
first call to TraceSwitchPartImpl.
|
|
9
|
-
|
|
10
|
-
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
-
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
-
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
-
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
-
memory are arbitrary.
|
|
15
|
-
|
|
16
|
-
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
-
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
-
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
-
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
-
have no TSan events.
|
|
21
|
-
|
|
22
|
-
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
-
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
-
necessary to poison the ThreadContext allocation like so:
|
|
25
|
-
|
|
26
|
-
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
-
patch. See full commit at
|
|
28
|
-
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
-
|
|
30
|
-
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
-
---
|
|
32
|
-
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
-
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
-
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
-
|
|
36
|
-
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
-
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
-
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
-
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
-
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
-
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
-
void *thr2 = 0;
|
|
43
|
-
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
-
+ // Goroutine that exits without a single event.
|
|
45
|
-
+ void *thr3 = 0;
|
|
46
|
-
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
-
+ __tsan_go_end(thr3);
|
|
48
|
-
__tsan_func_exit(thr0);
|
|
49
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
-
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
-
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
-
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
-
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
-
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
-
Mutex mtx;
|
|
57
|
-
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
-
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
-
- TracePart* local_head;
|
|
60
|
-
+ TracePart* local_head = nullptr;
|
|
61
|
-
// Final position in the last part for finished threads.
|
|
62
|
-
Event* final_pos = nullptr;
|
|
63
|
-
// Number of trace parts allocated on behalf of this trace specifically.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
-
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
-
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
-
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
-
|
|
6
|
-
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
-
first initialized when the first event is added to the trace, via the
|
|
8
|
-
first call to TraceSwitchPartImpl.
|
|
9
|
-
|
|
10
|
-
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
-
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
-
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
-
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
-
memory are arbitrary.
|
|
15
|
-
|
|
16
|
-
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
-
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
-
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
-
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
-
have no TSan events.
|
|
21
|
-
|
|
22
|
-
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
-
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
-
necessary to poison the ThreadContext allocation like so:
|
|
25
|
-
|
|
26
|
-
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
-
patch. See full commit at
|
|
28
|
-
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
-
|
|
30
|
-
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
-
---
|
|
32
|
-
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
-
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
-
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
-
|
|
36
|
-
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
-
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
-
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
-
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
-
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
-
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
-
void *thr2 = 0;
|
|
43
|
-
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
-
+ // Goroutine that exits without a single event.
|
|
45
|
-
+ void *thr3 = 0;
|
|
46
|
-
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
-
+ __tsan_go_end(thr3);
|
|
48
|
-
__tsan_func_exit(thr0);
|
|
49
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
-
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
-
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
-
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
-
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
-
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
-
Mutex mtx;
|
|
57
|
-
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
-
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
-
- TracePart* local_head;
|
|
60
|
-
+ TracePart* local_head = nullptr;
|
|
61
|
-
// Final position in the last part for finished threads.
|
|
62
|
-
Event* final_pos = nullptr;
|
|
63
|
-
// Number of trace parts allocated on behalf of this trace specifically.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
-
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
-
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
-
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
-
|
|
6
|
-
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
-
first initialized when the first event is added to the trace, via the
|
|
8
|
-
first call to TraceSwitchPartImpl.
|
|
9
|
-
|
|
10
|
-
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
-
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
-
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
-
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
-
memory are arbitrary.
|
|
15
|
-
|
|
16
|
-
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
-
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
-
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
-
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
-
have no TSan events.
|
|
21
|
-
|
|
22
|
-
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
-
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
-
necessary to poison the ThreadContext allocation like so:
|
|
25
|
-
|
|
26
|
-
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
-
patch. See full commit at
|
|
28
|
-
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
-
|
|
30
|
-
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
-
---
|
|
32
|
-
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
-
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
-
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
-
|
|
36
|
-
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
-
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
-
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
-
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
-
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
-
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
-
void *thr2 = 0;
|
|
43
|
-
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
-
+ // Goroutine that exits without a single event.
|
|
45
|
-
+ void *thr3 = 0;
|
|
46
|
-
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
-
+ __tsan_go_end(thr3);
|
|
48
|
-
__tsan_func_exit(thr0);
|
|
49
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
-
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
-
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
-
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
-
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
-
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
-
Mutex mtx;
|
|
57
|
-
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
-
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
-
- TracePart* local_head;
|
|
60
|
-
+ TracePart* local_head = nullptr;
|
|
61
|
-
// Final position in the last part for finished threads.
|
|
62
|
-
Event* final_pos = nullptr;
|
|
63
|
-
// Number of trace parts allocated on behalf of this trace specifically.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
-
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
-
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
-
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
-
|
|
6
|
-
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
-
first initialized when the first event is added to the trace, via the
|
|
8
|
-
first call to TraceSwitchPartImpl.
|
|
9
|
-
|
|
10
|
-
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
-
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
-
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
-
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
-
memory are arbitrary.
|
|
15
|
-
|
|
16
|
-
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
-
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
-
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
-
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
-
have no TSan events.
|
|
21
|
-
|
|
22
|
-
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
-
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
-
necessary to poison the ThreadContext allocation like so:
|
|
25
|
-
|
|
26
|
-
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
-
patch. See full commit at
|
|
28
|
-
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
-
|
|
30
|
-
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
-
---
|
|
32
|
-
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
-
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
-
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
-
|
|
36
|
-
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
-
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
-
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
-
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
-
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
-
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
-
void *thr2 = 0;
|
|
43
|
-
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
-
+ // Goroutine that exits without a single event.
|
|
45
|
-
+ void *thr3 = 0;
|
|
46
|
-
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
-
+ __tsan_go_end(thr3);
|
|
48
|
-
__tsan_func_exit(thr0);
|
|
49
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
-
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
-
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
-
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
-
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
-
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
-
Mutex mtx;
|
|
57
|
-
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
-
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
-
- TracePart* local_head;
|
|
60
|
-
+ TracePart* local_head = nullptr;
|
|
61
|
-
// Final position in the last part for finished threads.
|
|
62
|
-
Event* final_pos = nullptr;
|
|
63
|
-
// Number of trace parts allocated on behalf of this trace specifically.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
-
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
-
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
-
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
-
|
|
6
|
-
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
-
first initialized when the first event is added to the trace, via the
|
|
8
|
-
first call to TraceSwitchPartImpl.
|
|
9
|
-
|
|
10
|
-
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
-
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
-
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
-
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
-
memory are arbitrary.
|
|
15
|
-
|
|
16
|
-
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
-
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
-
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
-
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
-
have no TSan events.
|
|
21
|
-
|
|
22
|
-
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
-
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
-
necessary to poison the ThreadContext allocation like so:
|
|
25
|
-
|
|
26
|
-
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
-
patch. See full commit at
|
|
28
|
-
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
-
|
|
30
|
-
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
-
---
|
|
32
|
-
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
-
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
-
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
-
|
|
36
|
-
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
-
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
-
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
-
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
-
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
-
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
-
void *thr2 = 0;
|
|
43
|
-
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
-
+ // Goroutine that exits without a single event.
|
|
45
|
-
+ void *thr3 = 0;
|
|
46
|
-
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
-
+ __tsan_go_end(thr3);
|
|
48
|
-
__tsan_func_exit(thr0);
|
|
49
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
-
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
-
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
-
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
-
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
-
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
-
Mutex mtx;
|
|
57
|
-
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
-
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
-
- TracePart* local_head;
|
|
60
|
-
+ TracePart* local_head = nullptr;
|
|
61
|
-
// Final position in the last part for finished threads.
|
|
62
|
-
Event* final_pos = nullptr;
|
|
63
|
-
// Number of trace parts allocated on behalf of this trace specifically.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
From cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca Mon Sep 17 00:00:00 2001
|
|
2
|
-
From: Michael Pratt <michael@prattmic.com>
|
|
3
|
-
Date: Fri, 12 Dec 2025 16:31:44 +1100
|
|
4
|
-
Subject: [PATCH] [TSan] Zero-initialize Trace.local_head
|
|
5
|
-
|
|
6
|
-
Trace.local_head is currently uninitialized when Trace is created. It is
|
|
7
|
-
first initialized when the first event is added to the trace, via the
|
|
8
|
-
first call to TraceSwitchPartImpl.
|
|
9
|
-
|
|
10
|
-
However, ThreadContext::OnFinished uses local_head, assuming that it is
|
|
11
|
-
initialized. If it has not been initialized, we have undefined behavior,
|
|
12
|
-
likely crashing if the contents are garbage. The allocator (Alloc)
|
|
13
|
-
reuses previously allocations, so the contents of the uninitialized
|
|
14
|
-
memory are arbitrary.
|
|
15
|
-
|
|
16
|
-
In a C/C++ TSAN binary it is likely very difficult for a thread to start
|
|
17
|
-
and exit without a single event inbetween. For Go programs, code running
|
|
18
|
-
in the Go runtime itself is not TSan-instrumented, so goroutines that
|
|
19
|
-
exclusively run runtime code (such as GC workers) can quite reasonably
|
|
20
|
-
have no TSan events.
|
|
21
|
-
|
|
22
|
-
The addition of such a goroutine to the Go test.c is sufficient to
|
|
23
|
-
trigger this case, though for reliable failure (segfault) I've found it
|
|
24
|
-
necessary to poison the ThreadContext allocation like so:
|
|
25
|
-
|
|
26
|
-
(Example patch redacted because patch tries to apply this as a real
|
|
27
|
-
patch. See full commit at
|
|
28
|
-
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca).
|
|
29
|
-
|
|
30
|
-
The fix is trivial: local_head should be zero-initialized.
|
|
31
|
-
---
|
|
32
|
-
compiler-rt/lib/tsan/go/test.c | 4 ++++
|
|
33
|
-
compiler-rt/lib/tsan/rtl/tsan_trace.h | 2 +-
|
|
34
|
-
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
35
|
-
|
|
36
|
-
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
|
|
37
|
-
index d328ab1b331d7..fcd396227a4ab 100644
|
|
38
|
-
--- a/compiler-rt/lib/tsan/go/test.c
|
|
39
|
-
+++ b/compiler-rt/lib/tsan/go/test.c
|
|
40
|
-
@@ -91,6 +91,10 @@ int main(void) {
|
|
41
|
-
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
|
|
42
|
-
void *thr2 = 0;
|
|
43
|
-
__tsan_go_start(thr0, &thr2, (char*)&barfoo + 1);
|
|
44
|
-
+ // Goroutine that exits without a single event.
|
|
45
|
-
+ void *thr3 = 0;
|
|
46
|
-
+ __tsan_go_start(thr0, &thr3, (char*)&barfoo + 1);
|
|
47
|
-
+ __tsan_go_end(thr3);
|
|
48
|
-
__tsan_func_exit(thr0);
|
|
49
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
50
|
-
__tsan_func_enter(thr1, (char*)&foobar + 1);
|
|
51
|
-
diff --git a/compiler-rt/lib/tsan/rtl/tsan_trace.h b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
52
|
-
index 01bb7b34f43a2..1e791ff765fec 100644
|
|
53
|
-
--- a/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
54
|
-
+++ b/compiler-rt/lib/tsan/rtl/tsan_trace.h
|
|
55
|
-
@@ -190,7 +190,7 @@ struct Trace {
|
|
56
|
-
Mutex mtx;
|
|
57
|
-
IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
|
|
58
|
-
// First node non-queued into ctx->trace_part_recycle.
|
|
59
|
-
- TracePart* local_head;
|
|
60
|
-
+ TracePart* local_head = nullptr;
|
|
61
|
-
// Final position in the last part for finished threads.
|
|
62
|
-
Event* final_pos = nullptr;
|
|
63
|
-
// Number of trace parts allocated on behalf of this trace specifically.
|