diff --git a/packages/storage-file/src/helpers.ts b/packages/storage-file/src/helpers.ts index 69d411efe..6eb678039 100644 --- a/packages/storage-file/src/helpers.ts +++ b/packages/storage-file/src/helpers.ts @@ -37,6 +37,8 @@ export async function readFileRange( let fd: fs.FileHandle | null = null; let res: Buffer; try { + // adjust for symbolic links + filePath = await fs.realpath(filePath); const { size } = await fs.lstat(filePath); // build offset and length as necessary if (suffix !== undefined) { diff --git a/packages/storage-file/test/index.spec.ts b/packages/storage-file/test/index.spec.ts index 8823b753e..c8b20104c 100644 --- a/packages/storage-file/test/index.spec.ts +++ b/packages/storage-file/test/index.spec.ts @@ -163,6 +163,20 @@ test("FileStorage: getRangeMaybeExpired: suffix: returns partial values", async t.is(utf8Decode(getAll?.value), "123456789"); t.deepEqual(getAll?.range, { offset: 0, length: 9 }); }); +test("FileStorage: getRangeMaybeExpired: check that symbolic links are resolved appropriately", async (t) => { + const storage = await storageFactory.factory(t, {}); + await storage.put("inner/key", { value: utf8Encode("value") }); + // create the symbolic link + await fs.symlink( + // @ts-ignore + path.join(storage.root, "inner/key"), + // @ts-ignore + path.join(storage.root, "key") + ); + const getResult = await storage.getRangeMaybeExpired("key", { offset: 0 }); + t.is(utf8Decode(getResult?.value), "value"); + t.deepEqual(getResult?.range, { offset: 0, length: 5 }); +}); async function unsanitisedStorageFactory( t: ExecutionContext