Browse Source

bufferutils: use verifuint for 64 bit integers

Taken from browserify-buffer.

Also adds a few more tests to assert this is working correctly from both
read and write perspectives.
The assertion in for writePushDataInt in the 32 bit case was
unnecessary as that is handled by buffer.writeUInt32LE anyway.
hk-custom-address
Daniel Cousens 11 years ago
parent
commit
b9bdf21cbe
  1. 20
      src/bufferutils.js
  2. 35
      test/bufferutils.js
  3. 10
      test/fixtures/buffer.json

20
src/bufferutils.js

@ -1,6 +1,14 @@
var assert = require('assert') var assert = require('assert')
var opcodes = require('./opcodes') var opcodes = require('./opcodes')
// https://github.com/feross/buffer/blob/master/index.js#L1127
function verifuint(value, max) {
assert(typeof value === 'number', 'cannot write a non-number as a number')
assert(value >= 0, 'specified a negative value for writing an unsigned value')
assert(value <= max, 'value is larger than maximum value for type')
assert(Math.floor(value) === value, 'value has a fractional component')
}
function pushDataSize(i) { function pushDataSize(i) {
return i < opcodes.OP_PUSHDATA1 ? 1 return i < opcodes.OP_PUSHDATA1 ? 1
: i < 0xff ? 2 : i < 0xff ? 2
@ -47,9 +55,7 @@ function readUInt64LE(buffer, offset) {
var b = buffer.readUInt32LE(offset + 4) var b = buffer.readUInt32LE(offset + 4)
b *= 0x100000000 b *= 0x100000000
// Javascript Safe Integer limitation verifuint(b + a, 0x001fffffffffffff)
// assert(Number.isSafeInteger(value), 'value must be < 2^53')
assert(b + a < 0x0020000000000000, 'value must be < 2^53')
return b + a return b + a
} }
@ -104,10 +110,6 @@ function writePushDataInt(buffer, number, offset) {
// 32 bit // 32 bit
} else { } else {
// Javascript Safe Integer limitation
// assert(Number.isSafeInteger(value), 'value must be < 2^53')
assert(number < 0x0020000000000000, 'value must be < 2^53')
buffer.writeUInt8(opcodes.OP_PUSHDATA4, offset) buffer.writeUInt8(opcodes.OP_PUSHDATA4, offset)
buffer.writeUInt32LE(number, offset + 1) buffer.writeUInt32LE(number, offset + 1)
@ -117,9 +119,7 @@ function writePushDataInt(buffer, number, offset) {
} }
function writeUInt64LE(buffer, value, offset) { function writeUInt64LE(buffer, value, offset) {
// Javascript Safe Integer limitation verifuint(value, 0x001fffffffffffff)
// assert(Number.isSafeInteger(value), 'value must be < 2^53')
assert(value < 0x0020000000000000, 'value must be < 2^53')
buffer.writeInt32LE(value & -1, offset) buffer.writeInt32LE(value & -1, offset)
buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4) buffer.writeUInt32LE(Math.floor(value / 0x100000000), offset + 4)

35
test/bufferutils.js

@ -39,6 +39,16 @@ describe('bufferutils', function() {
assert.equal(number, f.dec) assert.equal(number, f.dec)
}) })
}) })
fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
var buffer = new Buffer(f.hex64, 'hex')
assert.throws(function() {
bufferutils.readUInt64LE(buffer, 0)
}, new RegExp(f.exception))
})
})
}) })
describe('readVarInt', function() { describe('readVarInt', function() {
@ -51,6 +61,16 @@ describe('bufferutils', function() {
assert.equal(d.size, buffer.length) assert.equal(d.size, buffer.length)
}) })
}) })
fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
var buffer = new Buffer(f.hexVI, 'hex')
assert.throws(function() {
bufferutils.readVarInt(buffer, 0)
}, new RegExp(f.exception))
})
})
}) })
describe('varIntSize', function() { describe('varIntSize', function() {
@ -75,17 +95,6 @@ describe('bufferutils', function() {
assert.equal(buffer.slice(0, n).toString('hex'), f.hexPD) assert.equal(buffer.slice(0, n).toString('hex'), f.hexPD)
}) })
}) })
fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
var buffer = new Buffer(5)
buffer.fill(0)
assert.throws(function() {
bufferutils.writePushDataInt(buffer, f.dec, 0)
}, /value must be < 2\^53/)
})
})
}) })
describe('writeUInt64LE', function() { describe('writeUInt64LE', function() {
@ -106,7 +115,7 @@ describe('bufferutils', function() {
assert.throws(function() { assert.throws(function() {
bufferutils.writeUInt64LE(buffer, f.dec, 0) bufferutils.writeUInt64LE(buffer, f.dec, 0)
}, /value must be < 2\^53/) }, new RegExp(f.exception))
}) })
}) })
}) })
@ -129,7 +138,7 @@ describe('bufferutils', function() {
assert.throws(function() { assert.throws(function() {
bufferutils.writeVarInt(buffer, f.dec, 0) bufferutils.writeVarInt(buffer, f.dec, 0)
}, /value must be < 2\^53/) }, new RegExp(f.exception))
}) })
}) })
}) })

10
test/fixtures/buffer.json

@ -85,11 +85,17 @@
"invalid": [ "invalid": [
{ {
"description": "n === 2^53", "description": "n === 2^53",
"value": 9007199254740992 "exception": "value is larger than maximum value for type",
"hex64": "0000000000002000",
"hexVI": "ff0000000000000020",
"dec": 9007199254740992
}, },
{ {
"description": "n > 2^53", "description": "n > 2^53",
"value": 18374686479671624000 "exception": "value is larger than maximum value for type",
"hex64": "0100000000002000",
"hexVI": "ff0100000000000020",
"dec": 9007199254740993
} }
] ]
} }

Loading…
Cancel
Save