Files
kjol/tools/tsgo/internal/lsp/stack_sanitizer_test.go
2026-07-09 16:50:43 -04:00

133 lines
7.8 KiB
Go

package lsp
import (
"regexp"
"strings"
"testing"
"github.com/microsoft/typescript-go/internal/testutil/baseline"
)
// This test uses non-trimmed paths to emulate debug builds.
// Most users won't actually see this.
func TestSanitizedDebugStackTraceCompletionsRequest(t *testing.T) {
t.Parallel()
input := `goroutine 1196 [running]:
runtime/debug.Stack()
/usr/local/go/src/runtime/debug/stack.go:26 +0x8e
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0xc0001dae08, {0x14bc418, 0xc00bc60960}, 0xc00baf16e0)
/workspaces/typescript-go/internal/lsp/server.go:777 +0x65
panic({0x1077b40?, 0x1abcb70?})
/usr/local/go/src/runtime/panic.go:783 +0x136
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData.func15()
/workspaces/typescript-go/internal/ls/completions.go:1303 +0xfa
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData.func18()
/workspaces/typescript-go/internal/ls/completions.go:1548 +0x2df
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData(0xc004b08240, {0x14bc418, 0xc00bc60a20}, 0xc0069ef908, 0xc000272008, 0x1b, 0xc002b28e00)
/workspaces/typescript-go/internal/ls/completions.go:1581 +0x2b92
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionsAtPosition(0xc004b08240, {0x14bc418, 0xc00bc60a20}, 0xc000272008, 0x1b, 0x0)
/workspaces/typescript-go/internal/ls/completions.go:347 +0x690
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).ProvideCompletion(0xc004b08240, {0x14bc418, 0xc00bc60a20}, {0xc0092e02a0, 0x28}, {0x2, 0x4}, 0xc004580c30)
/workspaces/typescript-go/internal/ls/completions.go:47 +0x207
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleCompletion(0xc0001dae08, {0x14bc418, 0xc00bc60960}, 0xc004b08240, 0xc00baf14d0)
/workspaces/typescript-go/internal/lsp/server.go:1102 +0xe5
github.com/microsoft/typescript-go/internal/lsp.registerLanguageServiceWithAutoImportsRequestHandler[...].func1({0x14bc418, 0xc00bc60960}, 0xc00baf16e0)
/workspaces/typescript-go/internal/lsp/server.go:682 +0x32a
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleRequestOrNotification(0xc0001dae08, {0x14bc418, 0xc00bc60960}, 0xc00baf16e0)
/workspaces/typescript-go/internal/lsp/server.go:531 +0x11e
github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop.func1()
/workspaces/typescript-go/internal/lsp/server.go:414 +0x65
created by github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop in goroutine 19
/workspaces/typescript-go/internal/lsp/server.go:438 +0x60`
baseline.Run(t, "completionsDebugStackTrace.md", sanitizedStackTraceBaselineContents(t, input, sanitizeStackTrace(input)), baseline.Options{
Subfolder: "lsp/stackSanitizer/",
})
}
func TestSanitizedReleaseStackTraceCompletionsRequest(t *testing.T) {
t.Parallel()
input := `runtime error: invalid memory address or nil pointer dereference
goroutine 2331 [running]:
runtime/debug.Stack()
runtime/debug/stack.go:26 +0x5e
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0xc0001c6e08, {0x441ae5?, 0xc000e976c0?}, 0xc00ab6c7b0)
github.com/microsoft/typescript-go/internal/lsp/server.go:777 +0x58
panic({0xc323a0?, 0x1780b90?})
runtime/panic.go:783 +0x132
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData.func15()
github.com/microsoft/typescript-go/internal/ls/completions.go:1303 +0xba
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData.func18(...)
github.com/microsoft/typescript-go/internal/ls/completions.go:1548
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData(0xc008329200, {0x10f6688, 0xc00c2871d0}, 0xc00190b308, 0xc0001fe008, 0x1b, 0xc0008a2f00)
github.com/microsoft/typescript-go/internal/ls/completions.go:1581 +0x1ed4
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionsAtPosition(0xc008329200, {0x10f6688, 0xc00c2871d0}, 0xc0001fe008, 0x1b, 0x0)
github.com/microsoft/typescript-go/internal/ls/completions.go:347 +0x35f
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).ProvideCompletion(0xc008329200, {0x10f6688, 0xc00c287110}, {0xc00b472030?, 0xc00c287110?}, {0xb472030?, 0xc0?}, 0xc00c3ea000)
github.com/microsoft/typescript-go/internal/ls/completions.go:47 +0x11c
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleCompletion(0x418834?, {0x10f6688?, 0xc00c287110?}, 0xc00b472030?, 0x10f6688?)
github.com/microsoft/typescript-go/internal/lsp/server.go:1105 +0x39
github.com/microsoft/typescript-go/internal/lsp.init.func1.registerLanguageServiceWithAutoImportsRequestHandler[...].28({0x10f6688, 0xc00c287110}, 0xc00ab6c7b0)
github.com/microsoft/typescript-go/internal/lsp/server.go:682 +0x16c
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleRequestOrNotification(0xc0001c6e08, {0x10f66c0?, 0xc006589180?}, 0xc00ab6c7b0)
github.com/microsoft/typescript-go/internal/lsp/server.go:531 +0x1c6
github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop.func1()
github.com/microsoft/typescript-go/internal/lsp/server.go:414 +0x3a
created by github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop in goroutine 35
github.com/microsoft/typescript-go/internal/lsp/server.go:438 +0x9f1`
baseline.Run(t, "completionsReleaseStackTrace.md", sanitizedStackTraceBaselineContents(t, input, sanitizeStackTrace(input)), baseline.Options{
Subfolder: "lsp/stackSanitizer/",
})
}
func sanitizedStackTraceBaselineContents(t *testing.T, input string, output string) string {
builder := strings.Builder{}
builder.WriteString("Test name: `")
builder.WriteString(t.Name())
builder.WriteString("`\n\n# Unsanitized input:\n\n````\n")
builder.WriteString(input)
builder.WriteString("\n````\n\n# Sanitized output:\n\n````\n")
builder.WriteString(output)
builder.WriteString("\n````\n")
return builder.String()
}
// Mirror of the "Generic Secret" pattern from VS Code's
// removePropertiesWithPossibleUserInfo. If this matches the sanitized output,
// VS Code's telemetry pipeline will replace the entire string with
// `<REDACTED: Generic Secret>`, destroying the stack trace.
var vscodeGenericSecretRegex = regexp.MustCompile(`(?i)(key|token|sig|secret|signature|password|passwd|pwd|android:value)[^a-zA-Z0-9]`)
func TestSanitizedStackTraceDefeatsVSCodeGenericSecretRegex(t *testing.T) {
t.Parallel()
// Frame names contain identifiers that contain trigger keywords:
// `getSignatureHelp` (signature), `LookupKey` (key), `validateToken` (token),
// `signRequest` (sig), `setPwd` (pwd), and a file `signature.go`.
input := `goroutine 7 [running]:
runtime/debug.Stack()
runtime/debug/stack.go:26 +0x5e
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getSignatureHelp(0x1)
github.com/microsoft/typescript-go/internal/ls/signature.go:42 +0x10
github.com/microsoft/typescript-go/internal/ls.LookupKey(0x2)
github.com/microsoft/typescript-go/internal/ls/keys.go:7 +0x10
github.com/microsoft/typescript-go/internal/ls.validateToken(0x3)
github.com/microsoft/typescript-go/internal/ls/token.go:9 +0x10
github.com/microsoft/typescript-go/internal/ls.signRequest(0x4)
github.com/microsoft/typescript-go/internal/ls/sig.go:11 +0x10
github.com/microsoft/typescript-go/internal/ls.setPwd(0x5)
github.com/microsoft/typescript-go/internal/ls/pwd.go:13 +0x10`
output := sanitizeStackTrace(input)
if loc := vscodeGenericSecretRegex.FindStringIndex(output); loc != nil {
t.Fatalf("sanitized stack trace would be redacted by VS Code's Generic Secret regex at %v: %q\nfull output:\n%s", loc, output[loc[0]:loc[1]], output)
}
baseline.Run(t, "genericSecretWorkaround.md", sanitizedStackTraceBaselineContents(t, input, output), baseline.Options{
Subfolder: "lsp/stackSanitizer/",
})
}