diff --git a/lib/filesystem.js b/lib/filesystem.js index 27b00a1..d921c50 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -100,9 +100,10 @@ class Filesystem { insertLink (p) { const symlink = fs.readlinkSync(p) - const parentPath = path.dirname(p) + // /var => /private/var + const parentPath = fs.realpathSync(path.dirname(p)) const link = path.relative(fs.realpathSync(this.src), path.join(parentPath, symlink)) - if (link.substr(0, 2) === '..') { + if (link.startsWith('..')) { throw new Error(`${p}: file "${link}" links out of the package`) } const node = this.searchNodeFromPath(p) diff --git a/test/filesystem-spec.js b/test/filesystem-spec.js new file mode 100644 index 0000000..8ac357d --- /dev/null +++ b/test/filesystem-spec.js @@ -0,0 +1,41 @@ +'use strict' + +const assert = require('assert') +const fs = require('../lib/wrapped-fs') +const path = require('path') +const rimraf = require('rimraf') + +const Filesystem = require('../lib/filesystem') + +describe('filesystem', function () { + beforeEach(() => { rimraf.sync(path.join(__dirname, '..', 'tmp'), fs) }) + + it('should does not throw an error when the src path includes a symbol link', async () => { + /** + * Directory structure: + * tmp + * ├── private + * │ └── var + * │ ├── app + * │ │ └── file.txt -> ../file.txt + * │ └── file.txt + * └── var -> private/var + */ + const tmpPath = path.join(__dirname, '..', 'tmp') + const privateVarPath = path.join(tmpPath, 'private', 'var') + const varPath = path.join(tmpPath, 'var') + fs.mkdirSync(privateVarPath, { recursive: true }) + fs.symlinkSync(path.relative(tmpPath, privateVarPath), varPath) + + const originFilePath = path.join(varPath, 'file.txt') + fs.writeFileSync(originFilePath, 'hello world') + const appPath = path.join(varPath, 'app') + fs.mkdirpSync(appPath) + fs.symlinkSync('../file.txt', path.join(appPath, 'file.txt')) + + const filesystem = new Filesystem(varPath) + assert.doesNotThrow(() => { + filesystem.insertLink(path.join(appPath, 'file.txt')) + }) + }) +})