From 72278dcf14d839b25b87644bb90a426751368584 Mon Sep 17 00:00:00 2001 From: Mani Maghsoudlou Date: Mon, 13 May 2019 00:39:10 -0700 Subject: [PATCH] util/stat: resolve paths before parsing --- lib/util/__tests__/stat.test.js | 80 +++++++++++++++++++++++++++++++++ lib/util/stat.js | 13 +++--- 2 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 lib/util/__tests__/stat.test.js diff --git a/lib/util/__tests__/stat.test.js b/lib/util/__tests__/stat.test.js new file mode 100644 index 00000000..223832ff --- /dev/null +++ b/lib/util/__tests__/stat.test.js @@ -0,0 +1,80 @@ +'use strict' + +const fs = require(process.cwd()) +const os = require('os') +const path = require('path') +const assert = require('assert') +const semver = require('semver') +const stat = require('../stat.js') + +const NODE_VERSION_WITH_BIGINT = '10.5.0' + +/* global beforeEach, afterEach, describe, it */ + +describe('util/stat', () => { + let TEST_DIR + + beforeEach(done => { + TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'util-stat') + fs.emptyDir(TEST_DIR, done) + }) + + afterEach(done => fs.remove(TEST_DIR, done)) + + describe('should use stats with bigint type for node versions >= 10.5.0 and number type for older versions', done => { + it('stat.checkPaths()', () => { + const nodeVersion = process.versions.node + const src = path.join(TEST_DIR, 'src') + const dest = path.join(TEST_DIR, 'dest') + fs.ensureFileSync(src) + fs.ensureFileSync(dest) + stat.checkPaths(src, dest, 'copy', (err, stats) => { + assert.ifError(err) + const { srcStat } = stats + if (semver.gte(nodeVersion, NODE_VERSION_WITH_BIGINT)) { + assert.strictEqual(typeof srcStat.ino, 'bigint') + } else { + assert.strictEqual(typeof srcStat.ino, 'number') + } + }) + }) + + it('stat.checkPathsSync()', () => { + const nodeVersion = process.versions.node + const src = path.join(TEST_DIR, 'src') + const dest = path.join(TEST_DIR, 'dest') + fs.ensureFileSync(src) + fs.ensureFileSync(dest) + const { srcStat } = stat.checkPathsSync(src, dest, 'copy') + if (semver.gte(nodeVersion, NODE_VERSION_WITH_BIGINT)) { + assert.strictEqual(typeof srcStat.ino, 'bigint') + } else { + assert.strictEqual(typeof srcStat.ino, 'number') + } + }) + }) + + describe('should stop at src or root path and not throw max call stack size error', done => { + it('stat.checkParentPaths()', () => { + const src = path.join(TEST_DIR, 'src') + let dest = path.join(TEST_DIR, 'dest') + fs.ensureFileSync(src) + fs.ensureFileSync(dest) + dest = path.basename(dest) + const srcStat = fs.statSync(src) + stat.checkParentPaths(src, srcStat, dest, 'copy', err => { + assert.ifError(err) + }) + }) + + it('stat.checkParentPathsSync()', () => { + const src = path.join(TEST_DIR, 'src') + let dest = path.join(TEST_DIR, 'dest') + fs.ensureFileSync(src) + fs.ensureFileSync(dest) + dest = path.basename(dest) + const srcStat = fs.statSync(src) + stat.checkParentPathsSync(src, srcStat, dest, 'copy') + }) + }) +}) diff --git a/lib/util/stat.js b/lib/util/stat.js index 5896a2bf..20049b73 100644 --- a/lib/util/stat.js +++ b/lib/util/stat.js @@ -104,11 +104,9 @@ function checkPathsSync (src, dest, funcName) { // checks the src and dest inodes. It starts from the deepest // parent and stops once it reaches the src parent or the root path. function checkParentPaths (src, srcStat, dest, funcName, cb) { - const destParent = path.dirname(dest) - if (destParent && - (destParent === path.dirname(src) || - destParent === path.parse(destParent).root) - ) return cb() + const srcParent = path.resolve(path.dirname(src)) + const destParent = path.resolve(path.dirname(dest)) + if (destParent === srcParent || destParent === path.parse(destParent).root) return cb() if (nodeSupportsBigInt()) { fs.stat(destParent, { bigint: true }, (err, destStat) => { if (err) { @@ -135,8 +133,9 @@ function checkParentPaths (src, srcStat, dest, funcName, cb) { } function checkParentPathsSync (src, srcStat, dest, funcName) { - const destParent = path.dirname(dest) - if (destParent && (destParent === path.dirname(src) || destParent === path.parse(destParent).root)) return + const srcParent = path.resolve(path.dirname(src)) + const destParent = path.resolve(path.dirname(dest)) + if (destParent === srcParent || destParent === path.parse(destParent).root) return let destStat try { if (nodeSupportsBigInt()) {