feat(headers.js): allow unknown formats (#131)

Co-authored-by: Kevin Lindsay <klindsay@surge.solutions>
This commit is contained in:
Kevin Lindsay 2020-12-29 05:22:18 -05:00 committed by GitHub
parent 03edcabc53
commit b1531cb695
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 3 deletions

View file

@ -120,7 +120,7 @@ var Extract = function (opts) {
var offset = self._offset
var header
try {
header = self._header = headers.decode(b.slice(0, 512), opts.filenameEncoding)
header = self._header = headers.decode(b.slice(0, 512), opts.filenameEncoding, opts.allowUnknownFormat)
} catch (err) {
self.emit('error', err)
}

View file

@ -237,7 +237,7 @@ exports.encode = function (opts) {
return buf
}
exports.decode = function (buf, filenameEncoding) {
exports.decode = function (buf, filenameEncoding, allowUnknownFormat) {
var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET
var name = decodeStr(buf, 0, 100, filenameEncoding)
@ -270,8 +270,10 @@ exports.decode = function (buf, filenameEncoding) {
// 'gnu'/'oldgnu' format. Similar to ustar, but has support for incremental and
// multi-volume tarballs.
} else {
if (!allowUnknownFormat) {
throw new Error('Invalid tar header: unknown format.')
}
}
// to support old tar versions that use trailing / to indicate dirs
if (typeflag === 0 && name && name[name.length - 1] === '/') typeflag = 5

View file

@ -679,3 +679,77 @@ test('v7 unsupported', function (t) { // correctly fails to parse v7 tarballs
extract.end(fs.readFileSync(fixtures.V7_TAR))
})
test('unknown format doesn\'t extract by default', function (t) {
t.plan(1)
var extract = tar.extract()
extract.on('error', function (err) {
t.ok(!!err)
extract.destroy()
})
extract.end(fs.readFileSync(fixtures.UNKNOWN_FORMAT))
})
test('unknown format attempts to extract if allowed', function (t) {
t.plan(5)
var extract = tar.extract({ allowUnknownFormat: true })
var noEntries = false
var onfile1 = function (header, stream, callback) {
t.deepEqual(header, {
name: 'file-1.txt',
mode: parseInt('644', 8),
uid: 501,
gid: 20,
size: 12,
mtime: new Date(1387580181000),
type: 'file',
linkname: null,
uname: 'maf',
gname: 'staff',
devmajor: 0,
devminor: 0
})
extract.on('entry', onfile2)
stream.pipe(concat(function (data) {
t.same(data.toString(), 'i am file-1\n')
callback()
}))
}
var onfile2 = function (header, stream, callback) {
t.deepEqual(header, {
name: 'file-2.txt',
mode: parseInt('644', 8),
uid: 501,
gid: 20,
size: 12,
mtime: new Date(1387580181000),
type: 'file',
linkname: null,
uname: 'maf',
gname: 'staff',
devmajor: 0,
devminor: 0
})
stream.pipe(concat(function (data) {
noEntries = true
t.same(data.toString(), 'i am file-2\n')
callback()
}))
}
extract.once('entry', onfile1)
extract.on('finish', function () {
t.ok(noEntries)
})
extract.end(fs.readFileSync(fixtures.UNKNOWN_FORMAT))
})

View file

@ -21,5 +21,7 @@ exports.INCOMPLETE_TAR = path.join(__dirname, 'incomplete.tar')
exports.GNU_TAR = path.join(__dirname, 'gnu.tar')
// Created using gnu tar: tar cf gnu-incremental.tar -G --format gnu --owner=myuser:12345 --group=mygroup:67890 test.txt
exports.GNU_INCREMENTAL_TAR = path.join(__dirname, 'gnu-incremental.tar')
// Created from multi-file.tar, removing the magic and recomputing the checksum
exports.UNKNOWN_FORMAT = path.join(__dirname, 'unknown-format.tar')
// Created using gnu tar: tar cf v7.tar --format v7 test.txt
exports.V7_TAR = path.join(__dirname, 'v7.tar')

BIN
test/fixtures/unknown-format.tar vendored Normal file

Binary file not shown.