fix(ci): avoid backtracking in concurrency inventory names

Problem: CodeQL reports exponential backtracking in the shared Windows
inventory test-name parser.
Root cause: repeated suffix groups can partition the same slash sequence.
Fix: accept the entire optional non-whitespace suffix once, preserving the
previous accepted language. Cover nested names and a long malformed suffix.
Verification: two Node tests pass; the original regex fails the bounded
regression while the existing contract test passes. Go and inventory bytes
are unchanged; prior exact-head Go qualification remains separate.
This commit is contained in:
SivanCola committed 2026-10-28 14:18:44 +08:00
1 parent 8378f0834c
commit 382016dfe1
2 files changed
+22 -1

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ export function readInventory(directory) {
assert(Array.isArray(group.tests) && group.tests.length > 0, `${file}: empty tests`);
const tests = required.get(group.package) ?? new Set();
for (const test of group.tests) {
assert(typeof test === 'string' && /^Test[A-Za-z0-9_]+(?:\/[^\s]+)*$/.test(test), `${file}: invalid test`);
assert(typeof test === 'string' && /^Test[A-Za-z0-9_]+(?:\/[^\s]+)?$/.test(test), `${file}: invalid test`);
tests.add(test);
}
required.set(group.package, tests);
@@ -2,9 +2,30 @@ import assert from 'node:assert/strict';
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { spawnSync } from 'node:child_process';
import test from 'node:test';
import { readInventory, verifyInventory } from './windows-concurrency-tests.mjs';
test('long invalid subtest suffix is rejected without repeated slash partitioning', () => {
const dir = mkdtempSync(join(tmpdir(), 'concurrency-inventory-'));
try {
const inventory = tests => JSON.stringify([{ package: 'reasonix/internal/example', tests }]);
const file = join(dir, 'names.json');
const valid = ['Test0', 'Test0/a/b', 'Test0/!/', 'Test0//'];
writeFileSync(file, inventory(valid));
assert.deepEqual([...readInventory(dir).values()][0], new Set(valid));
writeFileSync(file, inventory(['Test0', `Test0/${'!/'.repeat(10000)} `]));
const script = `import assert from 'node:assert/strict';
import { readInventory } from ${JSON.stringify(new URL('./windows-concurrency-tests.mjs', import.meta.url).href)};
assert.throws(() => readInventory(process.argv[1]), /invalid test/);`;
const result = spawnSync(process.execPath, ['--input-type=module', '-e', script, dir], { timeout: 5000, encoding: 'utf8' });
assert.ifError(result.error);
assert.equal(result.status, 0, result.stderr);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('additive manifests keep package-qualified requirements', () => {
const dir = mkdtempSync(join(tmpdir(), 'concurrency-inventory-'));
try {