Skip to content

Commit

Permalink
Prevent negative allocations when decoding corrupt fixed data
Browse files Browse the repository at this point in the history
  • Loading branch information
mtth committed Oct 15, 2019
1 parent 497c410 commit 45ac127
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
33 changes: 30 additions & 3 deletions lib/utils.js
Expand Up @@ -270,6 +270,9 @@ function BufferPool(len) {
}

BufferPool.prototype.alloc = function (len) {
if (len < 0) {
throw new Error('negative length');
}
var maxLen = this._len;
if (len > maxLen) {
return newBuffer(len);
Expand Down Expand Up @@ -448,6 +451,8 @@ function Tap(buf, pos) {
*/
Tap.prototype.isValid = function () { return this.pos <= this.buf.length; };

Tap.prototype._invalidate = function () { this.pos = this.buf.length + 1; };

// Read, skip, write methods.
//
// These should fail silently when the buffer overflows. Note this is only
Expand Down Expand Up @@ -522,7 +527,7 @@ Tap.prototype.readFloat = function () {
var pos = this.pos;
this.pos += 4;
if (this.pos > buf.length) {
return;
return 0;
}
return this.buf.readFloatLE(pos);
};
Expand All @@ -544,7 +549,7 @@ Tap.prototype.readDouble = function () {
var pos = this.pos;
this.pos += 8;
if (this.pos > buf.length) {
return;
return 0;
}
return this.buf.readDoubleLE(pos);
};
Expand Down Expand Up @@ -585,11 +590,20 @@ Tap.prototype.writeFixed = function (buf, len) {
};

Tap.prototype.readBytes = function () {
return this.readFixed(this.readLong());
var len = this.readLong();
if (len < 0) {
this._invalidate();
return;
}
return this.readFixed(len);
};

Tap.prototype.skipBytes = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return;
}
this.pos += len;
};

Expand All @@ -604,6 +618,10 @@ if (typeof Buffer.prototype.utf8Slice == 'function') {
// Use this optimized function when available.
Tap.prototype.readString = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return '';
}
var pos = this.pos;
var buf = this.buf;
this.pos += len;
Expand All @@ -615,6 +633,10 @@ if (typeof Buffer.prototype.utf8Slice == 'function') {
} else {
Tap.prototype.readString = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return '';
}
var pos = this.pos;
var buf = this.buf;
this.pos += len;
Expand All @@ -627,6 +649,10 @@ if (typeof Buffer.prototype.utf8Slice == 'function') {

Tap.prototype.skipString = function () {
var len = this.readLong();
if (len < 0) {
this._invalidate();
return;
}
this.pos += len;
};

Expand Down Expand Up @@ -872,6 +898,7 @@ module.exports = {
toMap: toMap,
singleIndexOf: singleIndexOf,
hasDuplicates: hasDuplicates,
BufferPool: BufferPool,
Lcg: Lcg,
OrderedQueue: OrderedQueue,
Tap: Tap
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "avsc",
"version": "5.4.14",
"version": "5.4.15",
"description": "Avro for JavaScript",
"homepage": "https://github.com/mtth/avsc",
"keywords": [
Expand Down
17 changes: 17 additions & 0 deletions test/test_utils.js
Expand Up @@ -143,6 +143,23 @@ suite('utils', function () {

});

suite('Tap', function () {

var BufferPool = utils.BufferPool;

test('alloc negative length', function () {
var pool = new BufferPool(16);
assert.throws(function () { pool.alloc(-1); });
});

test('alloc beyond pool size', function () {
var pool = new BufferPool(4);
assert.equal(pool.alloc(3).length, 3);
assert.equal(pool.alloc(2).length, 2);
});

});

suite('Tap', function () {

var Tap = utils.Tap;
Expand Down

0 comments on commit 45ac127

Please sign in to comment.