From 9ce5b12cb90c06fc1b0e3343c3e65bb977578591 Mon Sep 17 00:00:00 2001 From: v-mahabaleshwars <147705296+v-mahabaleshwars@users.noreply.github.com> Date: Sat, 14 Nov 2026 09:34:15 +0530 Subject: [PATCH] Architecture validation for JDK file installs (#1324) * Enhance architecture validation and error handling * Improve architecture normalization and validation for custom tokens * Refactor architecture validation to consolidate error handling for invalid tokens --- .../distributors/semeru-installer.test.ts | 2 +- __tests__/java-platform-contract.test.ts | 30 +++++++++++++++++++ dist/setup/index.js | 13 ++++++-- docs/advanced-usage.md | 9 +++--- src/distributions/platform-types.ts | 24 ++++++++++++--- 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/__tests__/distributors/semeru-installer.test.ts b/__tests__/distributors/semeru-installer.test.ts index 7dde47d0..b1785e85 100644 --- a/__tests__/distributors/semeru-installer.test.ts +++ b/__tests__/distributors/semeru-installer.test.ts @@ -272,7 +272,7 @@ describe('findPackageForDownload', () => { } ); - it.each(['zos', 'z/OS', 'z/os', 'test0987654321=', '++=++', 'myArch'])( + it.each(['zos', 'myArch'])( 'incorrect Semeru `%s` architecture throws', async (arch: string) => { const distribution = new SemeruDistribution({ diff --git a/__tests__/java-platform-contract.test.ts b/__tests__/java-platform-contract.test.ts index 57a0df65..6dd9784f 100644 --- a/__tests__/java-platform-contract.test.ts +++ b/__tests__/java-platform-contract.test.ts @@ -31,6 +31,36 @@ describe('Java platform capabilities', () => { expect(normalizeArchitecture(input)).toBe(expected); }); + it.each(['constructor', 'Constructor'])( + 'preserves custom architecture token %s for jdkfile', + architecture => { + expect(normalizeArchitecture(architecture)).toBe(architecture); + expect(validateJavaPlatform('jdkfile', 'linux', architecture, '17')).toBe( + architecture + ); + } + ); + + it.each([ + 'x64< { + const message = `Unsupported architecture value: ${JSON.stringify(architecture)}`; + + expect(() => normalizeArchitecture(architecture)).toThrow(message); + expect(() => + validateJavaPlatform('jdkfile', 'linux', architecture, '17') + ).toThrow(message); + }); + it.each([ ['linux', false, 'linux-glibc'], ['linux', true, 'linux-musl'], diff --git a/dist/setup/index.js b/dist/setup/index.js index de5a3f6e..34e0b09e 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -31545,6 +31545,8 @@ const CANONICAL_ARCHITECTURES = [ 'riscv64', 's390x' ]; +// Used in environment-variable names and tool-cache paths. +const ARCHITECTURE_TOKEN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/; const PLATFORM_ALIASES = { darwin: 'macos', linux: 'linux', @@ -31554,10 +31556,17 @@ const PLATFORM_ALIASES = { function normalizeArchitecture(architecture) { const trimmedArchitecture = architecture.trim(); const normalizedArchitecture = trimmedArchitecture.toLowerCase(); - return (ARCHITECTURE_ALIASES[normalizedArchitecture] ?? + const alias = Object.prototype.hasOwnProperty.call(ARCHITECTURE_ALIASES, normalizedArchitecture) + ? ARCHITECTURE_ALIASES[normalizedArchitecture] + : undefined; + const result = alias ?? (CANONICAL_ARCHITECTURES.includes(normalizedArchitecture) ? normalizedArchitecture - : trimmedArchitecture)); + : trimmedArchitecture); + if (!ARCHITECTURE_TOKEN.test(result)) { + throw new Error(`Unsupported architecture value: ${JSON.stringify(architecture)}`); + } + return result; } function normalizePlatform(platform) { return PLATFORM_ALIASES[platform]; diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 627c9d44..f1b74153 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -659,9 +659,10 @@ runner, distribution, JDK size, network, and cache eviction pressure. The `architecture` input is normalized before setup-java checks the tool cache or contacts a vendor. `amd64`, `ia32`, `arm`, and `arm64` are accepted aliases -for `x64`, `x86`, `armv7`, and `aarch64`. The table lists the combinations -setup-java validates up front; an individual Java patch release can still be -absent from a vendor catalog. +for `x64`, `x86`, `armv7`, and `aarch64`. Every value must be one token that +starts with a letter or digit and contains only letters, digits, `_`, or `-`. +The table lists the combinations setup-java validates up front; an individual +Java patch release can still be absent from a vendor catalog. | Distribution | Linux | macOS | Windows | Other / version restrictions | | --- | --- | --- | --- | --- | @@ -1651,4 +1652,4 @@ Notes and caveats: - On **self-hosted runners**, importing into a tool-cache JDK persists for as long as that cached version remains on the runner; if you want it to survive JDK reinstalls, pre-seed the CA into your runner image or re-run the import step each time. - Prefer giving the certificate a stable, descriptive `-alias` so re-runs are idempotent (re-importing the same alias will fail; add `keytool -delete -alias internal-ca ...` first if you re-run within a long-lived runner). -This documents the post-install workflow; there is no dedicated action input for supplying a custom `cacerts` file. +This documents the post-install workflow; there is no dedicated action input for supplying a custom `cacerts` file. \ No newline at end of file diff --git a/src/distributions/platform-types.ts b/src/distributions/platform-types.ts index 5e65c726..c338f1b5 100644 --- a/src/distributions/platform-types.ts +++ b/src/distributions/platform-types.ts @@ -192,6 +192,9 @@ const CANONICAL_ARCHITECTURES: readonly JavaArchitecture[] = [ 's390x' ]; +// Used in environment-variable names and tool-cache paths. +const ARCHITECTURE_TOKEN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/; + const PLATFORM_ALIASES: Readonly< Partial> > = { @@ -204,14 +207,27 @@ const PLATFORM_ALIASES: Readonly< export function normalizeArchitecture(architecture: string): string { const trimmedArchitecture = architecture.trim(); const normalizedArchitecture = trimmedArchitecture.toLowerCase(); - return ( - ARCHITECTURE_ALIASES[normalizedArchitecture] ?? + const alias = Object.prototype.hasOwnProperty.call( + ARCHITECTURE_ALIASES, + normalizedArchitecture + ) + ? ARCHITECTURE_ALIASES[normalizedArchitecture] + : undefined; + const result = + alias ?? (CANONICAL_ARCHITECTURES.includes( normalizedArchitecture as JavaArchitecture ) ? normalizedArchitecture - : trimmedArchitecture) - ); + : trimmedArchitecture); + + if (!ARCHITECTURE_TOKEN.test(result)) { + throw new Error( + `Unsupported architecture value: ${JSON.stringify(architecture)}` + ); + } + + return result; } export function normalizePlatform(