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
This commit is contained in:
sth 2018-04-26 17:00:57 +02:00 committed by Mathias Buus
parent c0b13f7329
commit 689d3fafd5
5 changed files with 30 additions and 0 deletions

View file

@ -48,6 +48,7 @@ var Extract = function (opts) {
this._offset = 0 this._offset = 0
this._buffer = bl() this._buffer = bl()
this._missing = 0 this._missing = 0
this._partial = false
this._onparse = noop this._onparse = noop
this._header = null this._header = null
this._stream = null this._stream = null
@ -181,6 +182,7 @@ var Extract = function (opts) {
self._parse(header.size, onstreamend) self._parse(header.size, onstreamend)
oncontinue() oncontinue()
} }
this._onheader = onheader
this._parse(512, onheader) this._parse(512, onheader)
} }
@ -200,6 +202,7 @@ Extract.prototype._parse = function (size, onparse) {
if (this._destroyed) return if (this._destroyed) return
this._offset += size this._offset += size
this._missing = size this._missing = size
if (onparse === this._onheader) this._partial = false
this._onparse = onparse this._onparse = onparse
} }
@ -217,6 +220,7 @@ Extract.prototype._write = function (data, enc, cb) {
var s = this._stream var s = this._stream
var b = this._buffer var b = this._buffer
var missing = this._missing var missing = this._missing
if (data.length) this._partial = true
// we do not reach end-of-chunk now. just forward it // we do not reach end-of-chunk now. just forward it
@ -246,4 +250,9 @@ Extract.prototype._write = function (data, enc, cb) {
this._onparse() this._onparse()
} }
Extract.prototype._final = function (cb) {
if (this._partial) cb(new Error('unexpected end of data'))
cb()
}
module.exports = Extract module.exports = Extract

View file

@ -570,3 +570,23 @@ test('latin-1', function (t) { // can unpack filenames encoded in latin-1
extract.end(fs.readFileSync(fixtures.LATIN1_TAR)) 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))
})

Binary file not shown.

BIN
test/fixtures/incomplete.tar vendored Normal file

Binary file not shown.

View file

@ -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.BASE_256_SIZE = path.join(__dirname, 'base-256-size.tar')
exports.HUGE = path.join(__dirname, 'huge.tar.gz') exports.HUGE = path.join(__dirname, 'huge.tar.gz')
exports.LATIN1_TAR = path.join(__dirname, 'latin1.tar') exports.LATIN1_TAR = path.join(__dirname, 'latin1.tar')
exports.INCOMPLETE_TAR = path.join(__dirname, 'incomplete.tar')