From f4e91b3d753d2355efca5567f93fe18f88d24a9b Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Sat, 5 Nov 2022 13:00:31 +0100 Subject: [PATCH 1/7] fix: gracefully handle forbidden filesystem access --- packages/vite/src/node/plugins/resolve.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index fcbd7644b6d857..c99eb0e4a35b03 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -546,7 +546,7 @@ function tryResolveFile( const resolved = resolvePackageEntry(file, pkg, targetWeb, options) return resolved } catch (e) { - if (e.code !== 'ENOENT') { + if (e.code !== 'ENOENT' && e.code !== 'EACCES') { throw e } } From 8076849b22fd4853387d1420e4d862eb35514e0d Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Tue, 8 Nov 2022 09:15:19 +0100 Subject: [PATCH 2/7] chore: improve fix --- packages/vite/src/node/utils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index f8aab87a13d96b..20e200648a081e 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -544,6 +544,8 @@ export function writeFile( export function isFileReadable(filename: string): boolean { try { const stat = fs.statSync(filename, { throwIfNoEntry: false }) + // Test user permission. Throws error if no permission. + fs.accessSync(filename, fs.constants.R_OK) return !!stat } catch { return false From 32b7c880088bdc9d65a573ab101c6f00b7dc57e8 Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Tue, 8 Nov 2022 09:46:32 +0100 Subject: [PATCH 3/7] chore: add tests --- .../vite/src/node/__tests__/utils.spec.ts | 27 +++++++++++++++++++ .../utils/isFileReadable/permission-test-file | 0 2 files changed, 27 insertions(+) create mode 100644 packages/vite/src/node/__tests__/utils/isFileReadable/permission-test-file diff --git a/packages/vite/src/node/__tests__/utils.spec.ts b/packages/vite/src/node/__tests__/utils.spec.ts index 34ede1f5be2303..24d5a0205d58c5 100644 --- a/packages/vite/src/node/__tests__/utils.spec.ts +++ b/packages/vite/src/node/__tests__/utils.spec.ts @@ -1,3 +1,4 @@ +import fs from 'node:fs' import { describe, expect, test } from 'vitest' import { asyncFlatten, @@ -5,6 +6,7 @@ import { getLocalhostAddressIfDiffersFromDNS, getPotentialTsSrcPaths, injectQuery, + isFileReadable, isWindows, posToNumber, resolveHostname @@ -236,3 +238,28 @@ describe('asyncFlatten', () => { expect(arr).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]) }) }) + +describe('isFileReadable', () => { + test("file doesn't exist", async () => { + expect(isFileReadable('/does_not_exist')).toBe(false) + }) + + const testFile = require.resolve( + './utils/isFileReadable/permission-test-file' + ) + test('file with normal permission', async () => { + expect(isFileReadable(testFile)).toBe(true) + }) + + if (process.platform !== 'win32') { + test('file with read-only permission', async () => { + fs.chmodSync(testFile, '400') + expect(isFileReadable(testFile)).toBe(true) + }) + test('file without read permission', async () => { + fs.chmodSync(testFile, '044') + expect(isFileReadable(testFile)).toBe(false) + fs.chmodSync(testFile, '644') + }) + } +}) diff --git a/packages/vite/src/node/__tests__/utils/isFileReadable/permission-test-file b/packages/vite/src/node/__tests__/utils/isFileReadable/permission-test-file new file mode 100644 index 00000000000000..e69de29bb2d1d6 From c1380cda14695ab93e9c27386cf4f2b436782f39 Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Tue, 8 Nov 2022 09:50:37 +0100 Subject: [PATCH 4/7] chore: improve fix --- packages/vite/src/node/plugins/resolve.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index c99eb0e4a35b03..fcbd7644b6d857 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -546,7 +546,7 @@ function tryResolveFile( const resolved = resolvePackageEntry(file, pkg, targetWeb, options) return resolved } catch (e) { - if (e.code !== 'ENOENT' && e.code !== 'EACCES') { + if (e.code !== 'ENOENT') { throw e } } From 343e2061914233cf275c3e038af058336b8f8213 Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Tue, 8 Nov 2022 09:54:59 +0100 Subject: [PATCH 5/7] chore: remove confusing comment --- packages/vite/src/node/plugins/resolve.ts | 3 --- packages/vite/src/node/utils.ts | 6 ------ 2 files changed, 9 deletions(-) diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index fcbd7644b6d857..cbe3ff26f3c5a7 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -531,9 +531,6 @@ function tryResolveFile( tryPrefix?: string, skipPackageJson?: boolean ): string | undefined { - // #2051 if we don't have read permission on a directory, existsSync() still - // works and will result in massively slow subsequent checks (which are - // unnecessary in the first place) if (isFileReadable(file)) { if (!fs.statSync(file).isDirectory()) { return getRealPath(file, options.preserveSymlinks) + postfix diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 20e200648a081e..cb646ec8adfb57 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -535,12 +535,6 @@ export function writeFile( fs.writeFileSync(filename, content) } -/** - * Use fs.statSync(filename) instead of fs.existsSync(filename) - * #2051 if we don't have read permission on a directory, existsSync() still - * works and will result in massively slow subsequent checks (which are - * unnecessary in the first place) - */ export function isFileReadable(filename: string): boolean { try { const stat = fs.statSync(filename, { throwIfNoEntry: false }) From 8246327e226b8303329e6393a939cf836f3a2258 Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Tue, 8 Nov 2022 09:56:38 +0100 Subject: [PATCH 6/7] chore: improve fix --- packages/vite/src/node/utils.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index cb646ec8adfb57..6e395d98b61140 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -537,10 +537,8 @@ export function writeFile( export function isFileReadable(filename: string): boolean { try { - const stat = fs.statSync(filename, { throwIfNoEntry: false }) - // Test user permission. Throws error if no permission. fs.accessSync(filename, fs.constants.R_OK) - return !!stat + return true } catch { return false } From 284d373de6c15b6e750cf55440b91f9cf6ee3302 Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Tue, 8 Nov 2022 10:53:27 +0100 Subject: [PATCH 7/7] chore: re-run CI