fs: fix realpath inode link caching

The `fs.realpath` / `fs.realpathSync` cache already seen symbolic links
using the inode number which may be longer that max supported
JS number (2**53) and will therefore be incorrectly handled by possibly
entering infinite loop of calling stat on the same node.

This PR changes those functions (where appropriate) to use
bigint for inode numbers.

Fixes: https://github.com/nodejs/node/issues/33936

PR-URL: https://github.com/nodejs/node/pull/33945
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
Denys Otrishko
2020-06-18 18:49:59 +03:00
committed by James M Snell
parent 5a0c6a6b5d
commit bd8a7196fc

View File

@@ -31,6 +31,7 @@ const kIoMaxLength = 2 ** 31 - 1;
const {
Map,
MathMax,
Number,
NumberIsSafeInteger,
ObjectCreate,
ObjectDefineProperties,
@@ -182,7 +183,10 @@ const isFd = isUint32;
function isFileType(stats, fileType) {
// Use stats array directly to avoid creating an fs.Stats instance just for
// our internal use.
return (stats[1/* mode */] & S_IFMT) === fileType;
let mode = stats[1];
if (typeof mode === 'bigint')
mode = Number(mode);
return (mode & S_IFMT) === fileType;
}
function access(path, mode, callback) {
@@ -1672,7 +1676,7 @@ function realpathSync(p, options) {
const baseLong = pathModule.toNamespacedPath(base);
const ctx = { path: base };
const stats = binding.lstat(baseLong, false, undefined, ctx);
const stats = binding.lstat(baseLong, true, undefined, ctx);
handleErrorFromBinding(ctx);
if (!isFileType(stats, S_IFLNK)) {
@@ -1805,7 +1809,7 @@ function realpath(p, options, callback) {
return process.nextTick(LOOP);
}
return fs.lstat(base, gotStat);
return fs.lstat(base, { bigint: true }, gotStat);
}
function gotStat(err, stats) {