From b1531cb6957d29ec4a80b7ef7a9b9b04824e045b Mon Sep 17 00:00:00 2001 From: Kevin Lindsay Date: Tue, 29 Dec 2020 05:22:18 -0500 Subject: [PATCH] feat(headers.js): allow unknown formats (#131) Co-authored-by: Kevin Lindsay --- extract.js | 2 +- headers.js | 6 ++- test/extract.js | 74 +++++++++++++++++++++++++++++++ test/fixtures/index.js | 2 + test/fixtures/unknown-format.tar | Bin 0 -> 3072 bytes 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/unknown-format.tar diff --git a/extract.js b/extract.js index 6278c38..11b13b7 100644 --- a/extract.js +++ b/extract.js @@ -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) } diff --git a/headers.js b/headers.js index 2787cfd..aba4ca4 100644 --- a/headers.js +++ b/headers.js @@ -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,7 +270,9 @@ exports.decode = function (buf, filenameEncoding) { // 'gnu'/'oldgnu' format. Similar to ustar, but has support for incremental and // multi-volume tarballs. } else { - throw new Error('Invalid tar header: unknown format.') + if (!allowUnknownFormat) { + throw new Error('Invalid tar header: unknown format.') + } } // to support old tar versions that use trailing / to indicate dirs diff --git a/test/extract.js b/test/extract.js index e2f92bd..30ad2e1 100644 --- a/test/extract.js +++ b/test/extract.js @@ -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)) +}) diff --git a/test/fixtures/index.js b/test/fixtures/index.js index 879de1f..569d9ab 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -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') diff --git a/test/fixtures/unknown-format.tar b/test/fixtures/unknown-format.tar new file mode 100644 index 0000000000000000000000000000000000000000..397db9b273617844f5ce9b7098b2939f05294179 GIT binary patch literal 3072 zcmeHHF$%*l49uKY=mQBSRZ8CDp@u*+)kB|O$6f*n-3+Eki>yNyr?cd^y`B@#>63x<^Vch?fJY> t*eRAF7<=aF+}bEmo?bfK|KopX)AC(a-~UN`|L-QlF;~D9a0UKUfiJY{E