diff --git a/lib/internal/fs/cp/cp.js b/lib/internal/fs/cp/cp.js index 1ec5a2d89cac..0c4338711690 100644 --- a/lib/internal/fs/cp/cp.js +++ b/lib/internal/fs/cp/cp.js @@ -398,8 +398,7 @@ async function onLink(destStat, src, dest, opts) { // Do not copy if src is a subdir of dest since unlinking // dest in this case would result in removing src contents // and therefore a broken symlink would be created. - const srcStat = await stat(src); - if (srcStat.isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) { + if (srcIsDir && isSrcSubdir(resolvedDest, resolvedSrc)) { throw new ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY({ message: `cannot overwrite ${resolvedDest} with ${resolvedSrc}`, path: dest, diff --git a/test/parallel/test-fs-cp-async-dangling-symlink-over-symlink.mjs b/test/parallel/test-fs-cp-async-dangling-symlink-over-symlink.mjs new file mode 100644 index 000000000000..e69686bdd502 --- /dev/null +++ b/test/parallel/test-fs-cp-async-dangling-symlink-over-symlink.mjs @@ -0,0 +1,16 @@ +import { mustNotMutateObjectDeep } from '../common/index.mjs'; +import { nextdir } from '../common/fs.js'; +import assert from 'node:assert'; +import { promises, readlinkSync, symlinkSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import tmpdir from '../common/tmpdir.js'; + +tmpdir.refresh(); + +const src = nextdir(); +const dest = nextdir(); +symlinkSync('missing', src); +symlinkSync(process.execPath, dest); + +await promises.cp(src, dest, mustNotMutateObjectDeep({ force: true })); +assert.strictEqual(readlinkSync(dest), resolve(dirname(src), 'missing'));