Skip to content

Commit

Permalink
fix: strip absolute paths more comprehensively
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Jul 23, 2021
1 parent 65edb39 commit efc6bb0
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 20 deletions.
14 changes: 14 additions & 0 deletions lib/strip-absolute-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// unix absolute paths are also absolute on win32, so we use this for both
const { isAbsolute, parse } = require('path').win32

// returns [root, stripped]
module.exports = path => {
let r = ''
while (isAbsolute(path)) {
// windows will think that //x/y/z has a "root" of //x/y/
const root = path.charAt(0) === '/' ? '/' : parse(path).root
path = path.substr(root.length)
r += root
}
return [r, path]
}
9 changes: 5 additions & 4 deletions lib/unpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const path = require('path')
const mkdir = require('./mkdir.js')
const mkdirSync = mkdir.sync
const wc = require('./winchars.js')
const stripAbsolutePath = require('./strip-absolute-path.js')

const ONENTRY = Symbol('onEntry')
const CHECKFS = Symbol('checkFs')
Expand Down Expand Up @@ -195,10 +196,10 @@ class Unpack extends Parser {

// absolutes on posix are also absolutes on win32
// so we only need to test this one to get both
if (path.win32.isAbsolute(p)) {
const parsed = path.win32.parse(p)
this.warn('stripping ' + parsed.root + ' from absolute path', p)
entry.path = p.substr(parsed.root.length)
const s = stripAbsolutePath(p)
if (s[0]) {
entry.path = s[1]
this.warn(`stripping ${s[0]} from absolute path`, p)
}
}

Expand Down
29 changes: 16 additions & 13 deletions lib/write-entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const CLOSE = Symbol('close')
const MODE = Symbol('mode')
const warner = require('./warn-mixin.js')
const winchars = require('./winchars.js')
const stripAbsolutePath = require('./strip-absolute-path.js')

const modeFix = require('./mode-fix.js')

Expand Down Expand Up @@ -54,12 +55,12 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
if (typeof opt.onwarn === 'function')
this.on('warn', opt.onwarn)

if (!this.preservePaths && path.win32.isAbsolute(p)) {
// absolutes on posix are also absolutes on win32
// so we only need to test this one to get both
const parsed = path.win32.parse(p)
this.warn('stripping ' + parsed.root + ' from absolute path', p)
this.path = p.substr(parsed.root.length)
if (!this.preservePaths) {
const s = stripAbsolutePath(this.path)
if (s[0]) {
this.path = s[1]
this.warn('stripping ' + s[0] + ' from absolute path', p)
}
}

this.win32 = !!opt.win32 || process.platform === 'win32'
Expand Down Expand Up @@ -343,13 +344,15 @@ const WriteEntryTar = warner(class WriteEntryTar extends MiniPass {
if (typeof opt.onwarn === 'function')
this.on('warn', opt.onwarn)

if (path.isAbsolute(this.path) && !this.preservePaths) {
const parsed = path.parse(this.path)
this.warn(
'stripping ' + parsed.root + ' from absolute path',
this.path
)
this.path = this.path.substr(parsed.root.length)
if (!this.preservePaths) {
const s = stripAbsolutePath(this.path)
if (s[0]) {
this.warn(
'stripping ' + s[0] + ' from absolute path',
this.path
)
this.path = s[1]
}
}

this.remain = readEntry.size
Expand Down
14 changes: 14 additions & 0 deletions test/strip-absolute-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const t = require('tap')
const stripAbsolutePath = require('../lib/strip-absolute-path.js')

const cases = {
'/': ['/', ''],
'////': ['////', ''],
'c:///a/b/c': ['c:///', 'a/b/c'],
'\\\\foo\\bar\\baz': ['\\\\foo\\bar\\', 'baz'],
'//foo//bar//baz': ['//', 'foo//bar//baz'],
'c:\\c:\\c:\\c:\\\\d:\\e/f/g': ['c:\\c:\\c:\\c:\\\\d:\\', 'e/f/g'],
}

for (const [input, [root, stripped]] of Object.entries(cases))
t.strictSame(stripAbsolutePath(input), [root, stripped], input)
9 changes: 6 additions & 3 deletions test/write-entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,10 @@ t.test('nonexistent file', t => {
})

t.test('absolute path', t => {
const f = path.resolve(files, '512-bytes.txt')
const absolute = path.resolve(files, '512-bytes.txt')
const { root } = path.parse(absolute)
const f = root + root + root + absolute
const warn = root + root + root + root
t.test('preservePaths=false strict=false', t => {
const warnings = []
const ws = new WriteEntry(f, {
Expand All @@ -375,13 +378,13 @@ t.test('absolute path', t => {
out = Buffer.concat(out)
t.equal(out.length, 1024)
t.match(warnings, [[
/stripping .* from absolute path/, f
'stripping ' + warn + ' from absolute path', f
]])

t.match(ws.header, {
cksumValid: true,
needPax: false,
path: f.replace(/^(\/|[a-z]:\\\\)/, ''),
path: f.replace(/^(\/|[a-z]:\\\\){4}/, ''),
mode: 0o644,
size: 512,
linkpath: null,
Expand Down

0 comments on commit efc6bb0

Please sign in to comment.