Skip to content

Commit

Permalink
Enforce supported bits param values.
Browse files Browse the repository at this point in the history
- The current get/put implementations only support a limited set of bit
  values. Enforce this by checking the param.
  • Loading branch information
davidlehn committed Jan 27, 2017
1 parent aee4865 commit 9a2f976
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 8 deletions.
41 changes: 33 additions & 8 deletions js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@ util.isArrayBufferView = function(x) {
return x && util.isArrayBuffer(x.buffer) && x.byteLength !== undefined;
};

/**
* Ensure a bits param is 8, 16, 24, or 32. Used to validate input for
* algorithms where bit manipulation, JavaScript limitations, and/or algorithm
* design only allow for byte operations of a limited size.
*
* @param n number of bits.
*
* Throw Error if n invalid.
*/
function _checkBitsParam(n) {
if(!(n === 8 || n === 16 || n === 24 || n === 32)) {
throw new Error('Only 8, 16, 24, or 32 bits supported: ' + n);
}
}

// TODO: set ByteBuffer to best available backing
util.ByteBuffer = ByteStringBuffer;

Expand Down Expand Up @@ -351,11 +366,12 @@ util.ByteStringBuffer.prototype.putInt32Le = function(i) {
* Puts an n-bit integer in this buffer in big-endian order.
*
* @param i the n-bit integer.
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return this buffer.
*/
util.ByteStringBuffer.prototype.putInt = function(i, n) {
_checkBitsParam(n);
var bytes = '';
do {
n -= 8;
Expand All @@ -369,11 +385,12 @@ util.ByteStringBuffer.prototype.putInt = function(i, n) {
* complement representation is used.
*
* @param i the n-bit integer.
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return this buffer.
*/
util.ByteStringBuffer.prototype.putSignedInt = function(i, n) {
// putInt checks n
if(i < 0) {
i += 2 << (n - 1);
}
Expand Down Expand Up @@ -492,15 +509,17 @@ util.ByteStringBuffer.prototype.getInt32Le = function() {

/**
* Gets an n-bit integer from this buffer in big-endian order and advances the
* read pointer by n/8.
* read pointer by ceil(n/8).
*
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return the integer.
*/
util.ByteStringBuffer.prototype.getInt = function(n) {
_checkBitsParam(n);
var rval = 0;
do {
// TODO: Use (rval * 0x100) if adding support for 33 to 53 bits.
rval = (rval << 8) + this.data.charCodeAt(this.read++);
n -= 8;
} while(n > 0);
Expand All @@ -511,11 +530,12 @@ util.ByteStringBuffer.prototype.getInt = function(n) {
* Gets a signed n-bit integer from this buffer in big-endian order, using
* two's complement, and advances the read pointer by n/8.
*
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return the integer.
*/
util.ByteStringBuffer.prototype.getSignedInt = function(n) {
// getInt checks n
var x = this.getInt(n);
var max = 2 << (n - 2);
if(x >= max) {
Expand Down Expand Up @@ -1032,11 +1052,12 @@ util.DataBuffer.prototype.putInt32Le = function(i) {
* Puts an n-bit integer in this buffer in big-endian order.
*
* @param i the n-bit integer.
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return this buffer.
*/
util.DataBuffer.prototype.putInt = function(i, n) {
_checkBitsParam(n);
this.accommodate(n / 8);
do {
n -= 8;
Expand All @@ -1055,6 +1076,7 @@ util.DataBuffer.prototype.putInt = function(i, n) {
* @return this buffer.
*/
util.DataBuffer.prototype.putSignedInt = function(i, n) {
_checkBitsParam(n);
this.accommodate(n / 8);
if(i < 0) {
i += 2 << (n - 1);
Expand Down Expand Up @@ -1151,13 +1173,15 @@ util.DataBuffer.prototype.getInt32Le = function() {
* Gets an n-bit integer from this buffer in big-endian order and advances the
* read pointer by n/8.
*
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return the integer.
*/
util.DataBuffer.prototype.getInt = function(n) {
_checkBitsParam(n);
var rval = 0;
do {
// TODO: Use (rval * 0x100) if adding support for 33 to 53 bits.
rval = (rval << 8) + this.data.getInt8(this.read++);
n -= 8;
} while(n > 0);
Expand All @@ -1168,11 +1192,12 @@ util.DataBuffer.prototype.getInt = function(n) {
* Gets a signed n-bit integer from this buffer in big-endian order, using
* two's complement, and advances the read pointer by n/8.
*
* @param n the number of bits in the integer.
* @param n the number of bits in the integer (8, 16, 24, or 32).
*
* @return the integer.
*/
util.DataBuffer.prototype.getSignedInt = function(n) {
// getInt checks n
var x = this.getInt(n);
var max = 2 << (n - 2);
if(x >= max) {
Expand Down
69 changes: 69 additions & 0 deletions nodejs/test/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,75 @@ function Tests(ASSERT, UTIL) {
ASSERT.equal(b.getSignedInt(n), x);
});

it('should getInt(8) from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('12'));
ASSERT.equal(b.getInt(8), 0x12);
ASSERT.equal(b.length(), 0);
});

it('should getInt(8)x2 from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('1221'));
ASSERT.equal(b.getInt(8), 0x12);
ASSERT.equal(b.getInt(8), 0x21);
ASSERT.equal(b.length(), 0);
});

it('should getInt(16) from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('1234'));
ASSERT.equal(b.getInt(16), 0x1234);
ASSERT.equal(b.length(), 0);
});

it('should getInt(16)x2 from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('12344321'));
ASSERT.equal(b.getInt(16), 0x1234);
ASSERT.equal(b.getInt(16), 0x4321);
ASSERT.equal(b.length(), 0);
});

it('should getInt(24) from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('123456'));
ASSERT.equal(b.getInt(24), 0x123456);
ASSERT.equal(b.length(), 0);
});

it('should getInt(24)x2 from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('123456654321'));
ASSERT.equal(b.getInt(24), 0x123456);
ASSERT.equal(b.getInt(24), 0x654321);
ASSERT.equal(b.length(), 0);
});

it('should getInt(32) from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('12345678'));
ASSERT.equal(b.getInt(32), 0x12345678);
ASSERT.equal(b.length(), 0);
});

it('should getInt(32)x2 from buffer', function() {
var b = UTIL.createBuffer(UTIL.hexToBytes('1234567887654321'));
ASSERT.equal(b.getInt(32), 0x12345678);
// FIXME: getInt bit shifts create signed int
ASSERT.equal(b.getInt(32), 0x87654321<<0);
ASSERT.equal(b.length(), 0);
});

it('should throw for getInt(1) from buffer', function() {
var b = UTIL.createBuffer();
ASSERT.throws(function() {
b.getInt(1);
});
});

it('should throw for getInt(33) from buffer', function() {
var b = UTIL.createBuffer();
ASSERT.throws(function() {
b.getInt(33);
});
});

// TODO: add get/put tests at limits of signed/unsigned types

it('should base64 encode some bytes', function() {
var s1 = '00010203050607080A0B0C0D0F1011121415161719';
var s2 = 'MDAwMTAyMDMwNTA2MDcwODBBMEIwQzBEMEYxMDExMTIxNDE1MTYxNzE5';
Expand Down

0 comments on commit 9a2f976

Please sign in to comment.