From 4a25320995a51bd1a551067f7db5180f7af4c9e8 Mon Sep 17 00:00:00 2001 From: Daniel Chao Date: Wed, 29 Apr 2026 20:20:49 -0700 Subject: [PATCH] Fix import/read verification when encountering glob wildcards (#1559) Fixes an issue where the import verifier can possibly throw when packaging on Windows due to `*` being an invalid filename. --- .../org/pkl/cli/CliProjectPackagerTest.kt | 37 +++++++++++++++++++ .../org/pkl/core/project/ProjectPackager.java | 15 ++++---- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/pkl-cli/src/test/kotlin/org/pkl/cli/CliProjectPackagerTest.kt b/pkl-cli/src/test/kotlin/org/pkl/cli/CliProjectPackagerTest.kt index a5670ac1..b057b663 100644 --- a/pkl-cli/src/test/kotlin/org/pkl/cli/CliProjectPackagerTest.kt +++ b/pkl-cli/src/test/kotlin/org/pkl/cli/CliProjectPackagerTest.kt @@ -763,6 +763,43 @@ class CliProjectPackagerTest { ) } + @Test + fun `import path verification with glob imports`(@TempDir tempDir: Path) { + tempDir.writeFile( + "main.pkl", + """ + import* "**.pkl" as foo + + res = foo + """ + .trimIndent(), + ) + tempDir.writeFile( + "PklProject", + """ + amends "pkl:Project" + + package { + name = "mypackage" + version = "1.0.0" + baseUri = "package://example.com/mypackage" + packageZipUrl = "https://foo.com" + } + """ + .trimIndent(), + ) + + CliProjectPackager( + CliBaseOptions(workingDir = tempDir), + listOf(tempDir), + CliTestOptions(), + ".out/%{name}@%{version}", + skipPublishCheck = true, + consoleWriter = StringWriter(), + ) + .run() + } + @Test @DisabledOnOs(OS.WINDOWS) fun `import path verification -- absolute read from root dir`(@TempDir tempDir: Path) { diff --git a/pkl-core/src/main/java/org/pkl/core/project/ProjectPackager.java b/pkl-core/src/main/java/org/pkl/core/project/ProjectPackager.java index 70a799dc..95c2a343 100644 --- a/pkl-core/src/main/java/org/pkl/core/project/ProjectPackager.java +++ b/pkl-core/src/main/java/org/pkl/core/project/ProjectPackager.java @@ -393,9 +393,6 @@ public final class ProjectPackager { */ public void validateImportsAndReads(Project project, Path pklModulePath) { var imports = getImportsAndReads(pklModulePath); - if (imports == null) { - return; - } for (var importContext : imports) { var importStr = importContext.stringValue(); var sourceSection = importContext.sourceSection(); @@ -420,14 +417,14 @@ public final class ProjectPackager { .toPklException(stackFrameTransformer, color); } var currentPath = pklModulePath.getParent(); - var importPath = Path.of(importUri.getPath()); + var importPath = importUri.getPath().split("/"); // It's not good enough to just check the normalized path to see whether it exists within the // root dir. // It's possible that the import path resolves to a path outside the project dir, // and then back inside the project dir. - for (var i = 0; i < importPath.getNameCount(); i++) { - var segment = importPath.getName(i); - currentPath = currentPath.resolve(segment); + for (var segment : importPath) { + // replace any possibly reserved filename characters with underscore. + currentPath = currentPath.resolve(sanitizePathSegment(segment)); var normalized = currentPath.normalize(); if (!normalized.startsWith(project.getProjectDir())) { throw new VmExceptionBuilder() @@ -440,6 +437,10 @@ public final class ProjectPackager { } } + private String sanitizePathSegment(String segment) { + return segment.replaceAll("[\\\\<>:\"|?*]", "_"); + } + private List getImportsAndReads(Path pklModulePath) { try { var moduleKey = ModuleKeys.file(pklModulePath);