From 689d3fafd5def71a29610e9b0f2c5ff470a19a05 Mon Sep 17 00:00:00 2001 From: sth Date: Thu, 26 Apr 2018 17:00:57 +0200 Subject: [PATCH] Trigger an error if there is an incomplete entry at the end of stream (#83) * Check if there is an incomplete entry at the end of the input An error will be raised if the last entry wans't complete. This will only work in node >= v8, since that's where _final() was introduced. Older node versions will ignore that function and will be unaffected. * Add padding at the end of gnu-long-path.tar This test case file was actually to short. The new code checking for unexpected end of file rejected it. Gnu tar agrees, it also failed to extract it with "Unexpected EOF in archive". * Added test case to check handling of incomplete data This tests that an error event is created when the input file is incomplete. * Check callback directly instead of passing extra parameter --- extract.js | 9 +++++++++ test/extract.js | 20 ++++++++++++++++++++ test/fixtures/gnu-long-path.tar | Bin 7594 -> 7680 bytes test/fixtures/incomplete.tar | Bin 0 -> 1000 bytes test/fixtures/index.js | 1 + 5 files changed, 30 insertions(+) create mode 100644 test/fixtures/incomplete.tar diff --git a/extract.js b/extract.js index 0d37cf7..aa0830f 100644 --- a/extract.js +++ b/extract.js @@ -48,6 +48,7 @@ var Extract = function (opts) { this._offset = 0 this._buffer = bl() this._missing = 0 + this._partial = false this._onparse = noop this._header = null this._stream = null @@ -181,6 +182,7 @@ var Extract = function (opts) { self._parse(header.size, onstreamend) oncontinue() } + this._onheader = onheader this._parse(512, onheader) } @@ -200,6 +202,7 @@ Extract.prototype._parse = function (size, onparse) { if (this._destroyed) return this._offset += size this._missing = size + if (onparse === this._onheader) this._partial = false this._onparse = onparse } @@ -217,6 +220,7 @@ Extract.prototype._write = function (data, enc, cb) { var s = this._stream var b = this._buffer var missing = this._missing + if (data.length) this._partial = true // we do not reach end-of-chunk now. just forward it @@ -246,4 +250,9 @@ Extract.prototype._write = function (data, enc, cb) { this._onparse() } +Extract.prototype._final = function (cb) { + if (this._partial) cb(new Error('unexpected end of data')) + cb() +} + module.exports = Extract diff --git a/test/extract.js b/test/extract.js index 09887b5..343a45a 100644 --- a/test/extract.js +++ b/test/extract.js @@ -570,3 +570,23 @@ test('latin-1', function (t) { // can unpack filenames encoded in latin-1 extract.end(fs.readFileSync(fixtures.LATIN1_TAR)) }) + +test('incomplete', function (t) { + t.plan(2) + + var extract = tar.extract() + + extract.on('entry', function (header, stream, callback) { + callback() + }) + + extract.on('error', function (err) { + t.same(err.message, 'unexpected end of data') + }) + + extract.on('finish', function () { + t.ok(true) + }) + + extract.end(fs.readFileSync(fixtures.INCOMPLETE_TAR)) +}) diff --git a/test/fixtures/gnu-long-path.tar b/test/fixtures/gnu-long-path.tar index efb204c4e341d2805c646513cbf61014d113b41f..e3ecd9510ecc3e016157370fc839227d33a52886 100644 GIT binary patch delta 10 RcmZ2w-C(m}mF&cYVE`GH1fc)` delta 7 OcmZp$S!KOpl`H@Zt^*kW diff --git a/test/fixtures/incomplete.tar b/test/fixtures/incomplete.tar new file mode 100644 index 0000000000000000000000000000000000000000..99c5587453423c2fdef57e00483354c02dca2a77 GIT binary patch literal 1000 zcmYex%t_TX)GMhdVW1f>FfcGPF;QRu(&lESVA{Y4!UqZgfuV_lp^=fPsiBFfiIJ&- zfuWI^fe}z0&0K_JaA|Q#ViC}3xru2=qL@sevNU`uAU=V3&cHwc(}2M#lBtlGtB?jx P1YCpDg`=*bMhE}^HP;zU literal 0 HcmV?d00001 diff --git a/test/fixtures/index.js b/test/fixtures/index.js index 1e2901c..7d5aa14 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -16,3 +16,4 @@ exports.LARGE_UID_GID = path.join(__dirname, 'large-uid-gid.tar') exports.BASE_256_SIZE = path.join(__dirname, 'base-256-size.tar') exports.HUGE = path.join(__dirname, 'huge.tar.gz') exports.LATIN1_TAR = path.join(__dirname, 'latin1.tar') +exports.INCOMPLETE_TAR = path.join(__dirname, 'incomplete.tar')