Skip to content

Commit

Permalink
Remove paths from dirCache when no longer dirs
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Jul 26, 2021
1 parent 9c393bb commit 85d3a94
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
23 changes: 23 additions & 0 deletions lib/unpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,20 @@ class Unpack extends Parser {
// check if a thing is there, and if so, try to clobber it
[CHECKFS] (entry) {
this[PEND]()

// if we are not creating a directory, and the path is in the dirCache,
// then that means we are about to delete the directory we created
// previously, and it is no longer going to be a directory, and neither
// is any of its children.
if (entry.type !== 'Directory') {
for (const path of this.dirCache.keys()) {
if (path === entry.absolute ||
path.indexOf(entry.absolute + '/') === 0 ||
path.indexOf(entry.absolute + '\\') === 0)
this.dirCache.delete(path)
}
}

this[MKDIR](path.dirname(entry.absolute), this.dmode, er => {
if (er)
return this[ONERROR](er, entry)
Expand Down Expand Up @@ -374,6 +388,15 @@ class UnpackSync extends Unpack {
}

[CHECKFS] (entry) {
if (entry.type !== 'Directory') {
for (const path of this.dirCache.keys()) {
if (path === entry.absolute ||
path.indexOf(entry.absolute + '/') === 0 ||
path.indexOf(entry.absolute + '\\') === 0)
this.dirCache.delete(path)
}
}

const er = this[MKDIR](path.dirname(entry.absolute), this.dmode)
if (er)
return this[ONERROR](er, entry)
Expand Down
52 changes: 52 additions & 0 deletions test/unpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -1890,3 +1890,55 @@ t.test('chown implicit dirs and also the entries', t => {

return tests()
})

t.test('drop entry from dirCache if no longer a directory', t => {
const dir = path.resolve(unpackdir, 'dir-cache-error')
mkdirp.sync(dir + '/sync/y')
mkdirp.sync(dir + '/async/y')
const data = makeTar([
{
path: 'x',
type: 'Directory',
},
{
path: 'x',
type: 'SymbolicLink',
linkpath: './y',
},
{
path: 'x/ginkoid',
type: 'File',
size: 'ginkoid'.length,
},
'ginkoid',
'',
'',
])
t.plan(2)
const WARNINGS = {}
const check = (t, path) => {
t.equal(fs.statSync(path + '/x').isDirectory(), true)
t.equal(fs.lstatSync(path + '/x').isSymbolicLink(), true)
t.equal(fs.statSync(path + '/y').isDirectory(), true)
t.strictSame(fs.readdirSync(path + '/y'), [])
t.throws(() => fs.readFileSync(path + '/x/ginkoid'), { code: 'ENOENT' })
t.strictSame(WARNINGS[path], [
'Cannot extract through symbolic link',
])
t.end()
}
t.test('async', t => {
const path = dir + '/async'
new Unpack({ cwd: path })
.on('warn', (msg) => WARNINGS[path] = [msg])
.on('end', () => check(t, path))
.end(data)
})
t.test('sync', t => {
const path = dir + '/sync'
new UnpackSync({ cwd: path })
.on('warn', (msg) => WARNINGS[path] = [msg])
.end(data)
check(t, path)
})
})

0 comments on commit 85d3a94

Please sign in to comment.