Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Array.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ class ArrayT extends Base {
}

} else {
// A count larger than the remaining bytes cannot be decoded and would allocate unbounded.
if (length > stream.length - stream.pos) {
throw new Error('Array length exceeds stream length');
}

for (let i = 0, end = length; i < end; i++) {
res.push(this.type.decode(stream, ctx));
}
Expand Down
9 changes: 8 additions & 1 deletion test/Array.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'assert';
import {Array as ArrayT, Pointer, uint8, uint16, DecodeStream, EncodeStream} from 'restructure';
import {Array as ArrayT, String as StringT, Pointer, uint8, uint16, uint32, DecodeStream, EncodeStream} from 'restructure';

describe('Array', function() {
describe('decode', function() {
Expand Down Expand Up @@ -62,6 +62,13 @@ describe('Array', function() {
const array = new ArrayT(uint8);
assert.deepEqual(array.fromBuffer(buffer), [1, 2, 3, 4]);
});

it('should throw when the decoded length exceeds the stream', function() {
// 32-bit count of 100000 elements, but only one byte of payload follows.
const buffer = new Uint8Array([0x00, 0x01, 0x86, 0xa0, 0x00]);
const array = new ArrayT(new StringT(), uint32);
assert.throws(() => array.fromBuffer(buffer), /exceeds stream length/);
});
});

describe('size', function() {
Expand Down
Loading