mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-30 12:25:49 +00:00
fix(web): reject superscript Windows device names in archives
This commit is contained in:
1 parent
18c438b109
commit
3397e873bc
3 files changed
+33
-1
No files matched your search
@@ -18,7 +18,7 @@ class BoundedBlobReader extends BlobReader {
|
||||
export function validPath(name) {
|
||||
if (!name || name.includes("\\") || /[\x00-\x1f<>:"|?*]/u.test(name)) throw new Error(`Unsafe ZIP path: ${name}`);
|
||||
const parts = name.replace(/\/$/u, "").split("/");
|
||||
if (parts.some(part => !part || part === "." || part === ".." || /[. ]$/u.test(part) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu.test(part))) throw new Error(`Unsafe ZIP path: ${name}`);
|
||||
if (parts.some(part => !part || part === "." || part === ".." || /[. ]$/u.test(part) || /^(con|prn|aux|nul|com[1-9\u00b9\u00b2\u00b3]|lpt[1-9\u00b9\u00b2\u00b3])(?:\.|$)/iu.test(part))) throw new Error(`Unsafe ZIP path: ${name}`);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { register } from "node:module";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import path from "node:path";
|
||||
|
||||
register("./cdn-loader.mjs", import.meta.url, { data: { url: process.env.ANYPS5_TEST_ZIP_URL, path: process.env.ANYPS5_TEST_ZIP_PATH } });
|
||||
const { Archive, validPath } = await import(pathToFileURL(path.join(process.argv[2], "archive.mjs")));
|
||||
const { BlobWriter, Uint8ArrayReader, ZipWriter } = await import(process.env.ANYPS5_TEST_ZIP_URL);
|
||||
const header = new Uint8Array([127, 69, 76, 70]);
|
||||
|
||||
for (const prefix of ["COM", "lpt"]) {
|
||||
for (const digit of ["\u00b9", "\u00b2", "\u00b3"]) {
|
||||
for (const name of [prefix + digit, prefix + digit + ".txt", "content/" + prefix + digit + "/data.bin"]) {
|
||||
assert.throws(() => validPath(name), /Unsafe ZIP path/);
|
||||
const folder = new Archive([{ path: "main.elf", file: new Blob([header]) }, { path: name, file: new Blob(["resource"]) }]);
|
||||
try { await assert.rejects(folder.inspect(() => {}), /Unsafe ZIP path/); }
|
||||
finally { await folder.close(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const writer = new ZipWriter(new BlobWriter(), { useWebWorkers: false, useCompressionStream: false });
|
||||
await writer.add("main.elf", new Uint8ArrayReader(header));
|
||||
await writer.add("content/COM\u00b9.txt", new Uint8ArrayReader(new Uint8Array([1])));
|
||||
const archive = new Archive(await writer.close());
|
||||
try { await assert.rejects(archive.inspect(() => {}), /Unsafe ZIP path/); }
|
||||
finally { await archive.close(); }
|
||||
|
||||
for (const name of ["COM10", "COM\u2074.txt", "COM\u00b9-extra", "content/ordinary.txt"]) {
|
||||
assert.equal(validPath(name), name);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ register("./cdn-loader.mjs", import.meta.url, { data: { url: process.env.ANYPS5_
|
||||
const site = name => pathToFileURL(path.join(process.argv[2], name)).href;
|
||||
const { Archive, memoryEstimate, MEMORY_LIMIT, packageArchive } = await import(site("archive.mjs"));
|
||||
const { BlobReader, BlobWriter, Uint8ArrayReader, Uint8ArrayWriter, ZipReader, ZipWriter } = await import(process.env.ANYPS5_TEST_ZIP_URL);
|
||||
await import("./archive-reserved.test.mjs");
|
||||
const { default: createRelinker } = await import(site("native/relinker_wasm.mjs"));
|
||||
const native = await createRelinker();
|
||||
const executable = new Uint8Array(await readFile(path.join(process.argv[3], "main.elf")));
|
||||
|
||||
Reference in new issue
Block a user