Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Go path warning unconditional #1946

Merged
merged 2 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions lib/analyze-action.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/analyze-action.js.map

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions lib/environment.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/environment.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 30 additions & 20 deletions lib/init-action.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/init-action.js.map

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions src/analyze-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,21 +233,23 @@ async function run() {
logger,
);

// Check that `which go` still points at the wrapper script we installed in the `init` Action,
// if the corresponding environment variable is set. This is to ensure that there isn't a step
// in the workflow after the `init` step which installs a different version of Go and takes
// precedence in the PATH, thus potentially circumventing our workaround that allows tracing to work.
const goWrapperPath = process.env[EnvVar.GO_BINARY_LOCATION];
// Check that `which go` still points at the same path it did when the `init` Action ran to ensure that no steps
// in-between performed any setup. We encourage users to perform all setup tasks before initializing CodeQL so that
// the setup tasks do not interfere with our analysis.
// Furthermore, if we installed a wrapper script in the `init` Action, we need to ensure that there isn't a step
// in the workflow after the `init` step which installs a different version of Go and takes precedence in the PATH,
// thus potentially circumventing our workaround that allows tracing to work.
const goInitPath = process.env[EnvVar.GO_BINARY_LOCATION];

if (
process.env[EnvVar.DID_AUTOBUILD_GOLANG] !== "true" &&
goWrapperPath !== undefined
goInitPath !== undefined
) {
const goBinaryPath = await safeWhich("go");

if (goWrapperPath !== goBinaryPath) {
if (goInitPath !== goBinaryPath) {
core.warning(
`Expected \`which go\` to return ${goWrapperPath}, but got ${goBinaryPath}: please ensure that the correct version of Go is installed before the \`codeql-action/init\` Action is used.`,
`Expected \`which go\` to return ${goInitPath}, but got ${goBinaryPath}: please ensure that the correct version of Go is installed before the \`codeql-action/init\` Action is used.`,
);

addDiagnostic(
Expand Down
5 changes: 2 additions & 3 deletions src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ export enum EnvVar {
WORKFLOW_STARTED_AT = "CODEQL_WORKFLOW_STARTED_AT",

/**
* The path where we initially discovered the Go binary in the system path
* before replacing it with a wrapper script. We check this later to ensure
* that it hasn't been tampered with by a late e.g. `setup-go` step.
* The path where we initially discovered the Go binary in the system path.
* We check this later to ensure that it hasn't been tampered with by a late e.g. `setup-go` step.
*/
GO_BINARY_LOCATION = "CODEQL_ACTION_GO_BINARY",
}
78 changes: 45 additions & 33 deletions src/init-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,49 +336,61 @@ async function run() {
);
}

// Go 1.21 and above ships with statically linked binaries on Linux. CodeQL cannot currently trace custom builds
// where the entry point is a statically linked binary. Until that is fixed, we work around the problem by
// replacing the `go` binary with a shell script that invokes the actual `go` binary. Since the shell is typically
// dynamically linked, this provides a suitable entry point for the CodeQL tracer.
if (
config.languages.includes(Language.go) &&
process.platform === "linux" &&
!isSupportedToolsFeature(
versionInfo,
ToolsFeature.IndirectTracingSupportsStaticBinaries,
)
process.platform === "linux"
) {
try {
const goBinaryPath = await safeWhich("go");
const fileOutput = await getFileType(goBinaryPath);

if (fileOutput.includes("statically linked")) {
logger.debug(`Applying static binary workaround for Go`);

// Create a directory that we can add to the system PATH.
const tempBinPath = path.resolve(
getTemporaryDirectory(),
"codeql-action-go-tracing",
"bin",
);
fs.mkdirSync(tempBinPath, { recursive: true });
core.addPath(tempBinPath);

// Write the wrapper script to the directory we just added to the PATH.
const goWrapperPath = path.resolve(tempBinPath, "go");
fs.writeFileSync(
goWrapperPath,
`#!/bin/bash\n\nexec ${goBinaryPath} "$@"`,
);
fs.chmodSync(goWrapperPath, "755");

// Store the original location of our wrapper script somewhere where we can
// later retrieve it from and cross-check that it hasn't been changed.
core.exportVariable(EnvVar.GO_BINARY_LOCATION, goWrapperPath);
// Go 1.21 and above ships with statically linked binaries on Linux. CodeQL cannot currently trace custom builds
// where the entry point is a statically linked binary. Until that is fixed, we work around the problem by
// replacing the `go` binary with a shell script that invokes the actual `go` binary. Since the shell is
// typically dynamically linked, this provides a suitable entry point for the CodeQL tracer.
if (
fileOutput.includes("statically linked") &&
!isSupportedToolsFeature(
versionInfo,
ToolsFeature.IndirectTracingSupportsStaticBinaries,
)
) {
try {
logger.debug(`Applying static binary workaround for Go`);

// Create a directory that we can add to the system PATH.
const tempBinPath = path.resolve(
getTemporaryDirectory(),
"codeql-action-go-tracing",
"bin",
);
fs.mkdirSync(tempBinPath, { recursive: true });
core.addPath(tempBinPath);

// Write the wrapper script to the directory we just added to the PATH.
const goWrapperPath = path.resolve(tempBinPath, "go");
fs.writeFileSync(
goWrapperPath,
`#!/bin/bash\n\nexec ${goBinaryPath} "$@"`,
);
fs.chmodSync(goWrapperPath, "755");

// Store the original location of our wrapper script somewhere where we can
// later retrieve it from and cross-check that it hasn't been changed.
core.exportVariable(EnvVar.GO_BINARY_LOCATION, goWrapperPath);
} catch (e) {
logger.warning(
`Analyzing Go on Linux, but failed to install wrapper script. Tracing custom builds may fail: ${e}`,
);
}
} else {
// Store the location of the original Go binary, so we can check that no setup tasks were performed after the
// `init` Action ran.
core.exportVariable(EnvVar.GO_BINARY_LOCATION, goBinaryPath);
}
} catch (e) {
logger.warning(
`Analyzing Go on Linux, but failed to install wrapper script. Tracing custom builds may fail: ${e}`,
`Failed to determine the location of the Go binary: ${e}`,
);
}
}
Expand Down
Loading