Skip to content
Draft
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
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ go_sdk.download(version = "1.26.4")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")
use_repo(go_deps, "com_github_stretchr_testify", "org_golang_x_mod", "org_golang_x_tools")
use_repo(go_deps, "com_github_stretchr_testify", "org_golang_x_mod", "org_golang_x_sys", "org_golang_x_tools")

ripunzip_archive = use_repo_rule("//misc/ripunzip:ripunzip.bzl", "ripunzip_archive")

Expand Down
14 changes: 7 additions & 7 deletions csharp/ql/integration-tests/windows/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
| code/Program.cs:0:0:0:0 | code/Program.cs | |
| code/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs:0:0:0:0 | code/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs | |
| code/obj/Debug/net9.0/dotnet_build.AssemblyInfo.cs:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.AssemblyInfo.cs | |
| code/obj/Debug/net9.0/dotnet_build.GlobalUsings.g.cs:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.GlobalUsings.g.cs | |
| code/obj/Debug/net9.0/dotnet_build.dll:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.dll | |
| code/Program.cs:0:0:0:0 | code/Program.cs | relative |
| code/dotnet_build.csproj:0:0:0:0 | code/dotnet_build.csproj | relative |
| code/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs:0:0:0:0 | code/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs | relative |
| code/obj/Debug/net9.0/dotnet_build.AssemblyInfo.cs:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.AssemblyInfo.cs | relative |
| code/obj/Debug/net9.0/dotnet_build.GlobalUsings.g.cs:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.GlobalUsings.g.cs | relative |
| code/obj/Debug/net9.0/dotnet_build.dll:0:0:0:0 | code/obj/Debug/net9.0/dotnet_build.dll | relative |
| code/obj/dotnet_build.csproj.nuget.g.props:0:0:0:0 | code/obj/dotnet_build.csproj.nuget.g.props | relative |
| file://:0:0:0:0 | | |
| file://Z:/dotnet_build.csproj:0:0:0:0 | Z:/dotnet_build.csproj | relative |
| file://Z:/obj/dotnet_build.csproj.nuget.g.props:0:0:0:0 | Z:/obj/dotnet_build.csproj.nuget.g.props | relative |
2 changes: 1 addition & 1 deletion go/extractor/extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ func normalizedPath(ast *ast.File, fset *token.FileSet) string {
file := fset.File(ast.Package).Name()
path, err := filepath.EvalSymlinks(file)
if err != nil {
return file
return util.ResolvePath(file)
}
return path
}
Expand Down
5 changes: 4 additions & 1 deletion go/extractor/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ require (
golang.org/x/tools v0.47.0
)

require github.com/stretchr/testify v1.11.1
require (
github.com/stretchr/testify v1.11.1
golang.org/x/sys v0.46.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go/extractor/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
Expand Down
11 changes: 10 additions & 1 deletion go/extractor/util/BUILD.bazel

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

6 changes: 6 additions & 0 deletions go/extractor/util/subst_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//go:build !windows

package util

// ResolvePath is a no-op on non-Windows platforms.
func ResolvePath(path string) string { return path }
87 changes: 87 additions & 0 deletions go/extractor/util/subst_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//go:build windows

package util

import (
"os"
"path/filepath"
"syscall"
"unsafe"

"golang.org/x/sys/windows"
)

var (
dll *syscall.DLL
procResolve *syscall.Proc
procFree *syscall.Proc
available bool
)

func init() {
dist := os.Getenv("CODEQL_DIST")
if dist == "" {
return
}
dllPath := filepath.Join(dist, "tools", "win64", "canonicalize.dll")
d, err := syscall.LoadDLL(dllPath)
if err != nil {
return
}
p, err := d.FindProc("resolve_subst_u8")
if err != nil {
return
}
f, _ := d.FindProc("resolve_subst_free_u8")
dll = d
procResolve = p
procFree = f
available = true
}

// If "path" is an absolute path starting with a "subst"ed drive letter, return an
// equivalent path with the drive letter replaced by its target. Otherwise return
// "path" unchanged.
func ResolvePath(path string) string {
if len(path) < 3 {
return path
}
if path[1] != ':' {
return path
}
if path[2] != '\\' && path[2] != '/' {
return path
}
c := path[0]
if !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
return path
}

resolved, ok := resolveDrive(path[:3])
if !ok {
return path
}
return resolved + path[2:]
}

// Given a drive root like "X:\" (or "X:/"), returns the path that drive is
// "subst"ed to and true. Returns false is the drive is not "subst"ed or an
// error occurred.
func resolveDrive(driveRoot string) (string, bool) {
if !available {
return "", false
}
driveBytes, err := windows.ByteSliceFromString(driveRoot)
if err != nil {
return "", false
}
ret, _, _ := procResolve.Call(uintptr(unsafe.Pointer(&driveBytes[0])))
if ret == 0 {
return "", false
}
result := windows.BytePtrToString((*byte)(unsafe.Pointer(ret)))
if procFree != nil {
procFree.Call(ret)
}
return result, true
}
2 changes: 1 addition & 1 deletion go/ql/integration-tests/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1 +1 @@
| file://Z:/main.go:0:0:0:0 | Z:/main.go | relative |
| file://Z:/main.go:0:0:0:0 | Z:/main.go | |
Original file line number Diff line number Diff line change
Expand Up @@ -1237,13 +1237,14 @@ public static String relativePathLink (File f, File base)

/**
* Try to convert a file into a canonical file. Handles the possible IO exception by just making
* the path absolute.
* the path absolute. Also resolves subst drives on Windows.
*/
public static File tryMakeCanonical (File f)
{
try {
return f.getCanonicalFile();
}
// getCanonicalFile does not canonicalize subst drives on Windows, so do this separately. This
// is a no-op on non-Windows platforms.
return SubstResolver.resolve(f.getCanonicalFile()); }
catch (IOException ignored) {
Exceptions.ignore(ignored, "Can't log error: Could be too verbose.");
return new File(simplifyPath(f));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.semmle.util.files;

import java.io.File;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
* Resolves Windows {@code subst}ed drive letters to their underlying paths. On non-Windows
* platforms, or when the native library failed to load, resolving will be a no-op.
*/
public class SubstResolver {
private static final boolean available;

static {
boolean loaded = false;
if (File.separatorChar == '\\') {
String dist = System.getenv("CODEQL_DIST");
if (dist != null && !dist.isEmpty()) {
try {
Path library = Paths.get(dist).resolve("tools")
.resolve("win64").resolve("canonicalize.dll").toAbsolutePath();
System.load(library.toString());
loaded = true;
} catch (RuntimeException | UnsatisfiedLinkError ignored) {
}
}
}
available = loaded;
}

private SubstResolver() {}

/**
* Given a drive root like {@code "X:\\"} (or {@code "X:/"}), returns the path that drive is
* {@code subst}ed to, or {@code null} if the drive root was not subst drive or if an internal
* error occurred.
*/
private static native String nativeResolveSubst(String driveRoot);

/**
* If {@code f} is an absolute path starting with a {@code subst}ed drive letter, return an
* equivalent path with the drive letter replaced by its target. Otherwise return {@code f}
* unchanged.
*/
public static File resolve(File f) {
if (!available) {
return f;
}
String path = f.getPath();
if (path.length() < 3 || path.charAt(1) != ':') {
return f;
}
char sep = path.charAt(2);
if (sep != '\\' && sep != '/') {
return f;
}
if (!isDriveLetter(path.charAt(0))) {
return f;
}

String resolved = nativeResolveSubst(path.substring(0, 3));
if (resolved == null) {
return f;
}

// Append the remainder of the original path. The native side strips away
// any trailing separator.
return new File(resolved + path.substring(2));
}

private static boolean isDriveLetter(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
}
6 changes: 3 additions & 3 deletions java/ql/integration-tests/java/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
| code/Test.class:0:0:0:0 | Test | relative |
| code/test1.java:0:0:0:0 | test1 | relative |
| code/test2.kt:0:0:0:0 | test2 | relative |
| file://:0:0:0:0 | | |
| file://:0:0:0:0 | | |
| file://Z:/Test.class:0:0:0:0 | Test | relative |
| file://Z:/test1.java:0:0:0:0 | test1 | relative |
| file://Z:/test2.kt:0:0:0:0 | test2 | relative |
4 changes: 2 additions & 2 deletions javascript/ql/integration-tests/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| file://Z:/main.js:0:0:0:0 | Z:/main.js | relative |
| file://Z:/test.ts:0:0:0:0 | Z:/test.ts | relative |
| code/main.js:0:0:0:0 | code/main.js | relative |
| code/test.ts:0:0:0:0 | code/test.ts | relative |
2 changes: 1 addition & 1 deletion python/ql/integration-tests/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1 +1 @@
| code/main.py:0:0:0:0 | code/main.py | |
| code/main.py:0:0:0:0 | code/main.py | relative |
2 changes: 1 addition & 1 deletion ruby/ql/integration-tests/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| code/test.rb:0:0:0:0 | code/test.rb | |
| code/test.rb:0:0:0:0 | code/test.rb | relative |
| file://:0:0:0:0 | | |
2 changes: 1 addition & 1 deletion rust/ql/integration-tests/subst/file.expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| code/test.rs:0:0:0:0 | code/test.rs | |
| code/test.rs:0:0:0:0 | code/test.rs | relative |
| file://:0:0:0:0 | | |
Loading