mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 20:55:48 +00:00
Validate UInt hex input
This commit is contained in:
@@ -54,7 +54,7 @@ SerializedObject.from_json = function(obj_) {
|
|||||||
// Create a copy of the object so we don't modify it
|
// Create a copy of the object so we don't modify it
|
||||||
const obj = extend(true, {}, obj_);
|
const obj = extend(true, {}, obj_);
|
||||||
|
|
||||||
let so = new SerializedObject();
|
const so = new SerializedObject();
|
||||||
let typedef;
|
let typedef;
|
||||||
|
|
||||||
if (typeof obj.TransactionType === 'number') {
|
if (typeof obj.TransactionType === 'number') {
|
||||||
@@ -216,7 +216,7 @@ SerializedObject.prototype.to_json = function() {
|
|||||||
|
|
||||||
this.resetPointer();
|
this.resetPointer();
|
||||||
|
|
||||||
let output = { };
|
const output = { };
|
||||||
|
|
||||||
while (this.pointer < this.buffer.length) {
|
while (this.pointer < this.buffer.length) {
|
||||||
const key_and_value = stypes.parse(this);
|
const key_and_value = stypes.parse(this);
|
||||||
@@ -265,10 +265,10 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
|
|||||||
// new Array or Object
|
// new Array or Object
|
||||||
output = new structure.constructor();
|
output = new structure.constructor();
|
||||||
|
|
||||||
let keys = Object.keys(structure);
|
const keys = Object.keys(structure);
|
||||||
|
|
||||||
for (let i = 0, l = keys.length; i < l; i++) {
|
for (let i = 0, l = keys.length; i < l; i++) {
|
||||||
let key = keys[i];
|
const key = keys[i];
|
||||||
output[key] = SerializedObject.jsonify_structure(structure[key], key);
|
output[key] = SerializedObject.jsonify_structure(structure[key], key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ SerializedObject.prototype.serialize = function(typedef, obj) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.prototype.hash = function(prefix) {
|
SerializedObject.prototype.hash = function(prefix) {
|
||||||
let sign_buffer = new SerializedObject();
|
const sign_buffer = new SerializedObject();
|
||||||
|
|
||||||
// Add hashing prefix
|
// Add hashing prefix
|
||||||
if (typeof prefix !== 'undefined') {
|
if (typeof prefix !== 'undefined') {
|
||||||
@@ -310,7 +310,7 @@ SerializedObject.prototype.hash = function(prefix) {
|
|||||||
const bits = sjcl.codec.bytes.toBits(sign_buffer.buffer);
|
const bits = sjcl.codec.bytes.toBits(sign_buffer.buffer);
|
||||||
const sha512hex = sjcl.codec.hex.fromBits(sjcl.hash.sha512.hash(bits));
|
const sha512hex = sjcl.codec.hex.fromBits(sjcl.hash.sha512.hash(bits));
|
||||||
|
|
||||||
return UInt256.from_hex(sha512hex.substr(0, 64));
|
return UInt256.from_hex(sha512hex.substr(0, 64).toUpperCase());
|
||||||
};
|
};
|
||||||
|
|
||||||
// DEPRECATED
|
// DEPRECATED
|
||||||
@@ -334,7 +334,7 @@ SerializedObject.prototype.serialize_field = function(spec, obj) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SerializedObject.get_field_header = function(type_id, field_id) {
|
SerializedObject.get_field_header = function(type_id, field_id) {
|
||||||
let buffer = [0];
|
const buffer = [0];
|
||||||
|
|
||||||
if (type_id > 0xF) {
|
if (type_id > 0xF) {
|
||||||
buffer.push(type_id & 0xFF);
|
buffer.push(type_id & 0xFF);
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
/*eslint new-cap: 1*/
|
/*eslint new-cap: 1*/
|
||||||
|
|
||||||
var utils = require('./utils');
|
const assert = require('assert');
|
||||||
var sjcl = utils.sjcl;
|
const lodash = require('lodash');
|
||||||
|
const utils = require('./utils');
|
||||||
|
const sjcl = utils.sjcl;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Abstract UInt class
|
// Abstract UInt class
|
||||||
@@ -14,7 +16,6 @@ var sjcl = utils.sjcl;
|
|||||||
function UInt() {
|
function UInt() {
|
||||||
// Internal form: NaN or sjcl.bn
|
// Internal form: NaN or sjcl.bn
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
this._update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt.json_rewrite = function(j, opts) {
|
UInt.json_rewrite = function(j, opts) {
|
||||||
@@ -26,6 +27,7 @@ UInt.from_generic = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_generic(j);
|
return (new this()).parse_generic(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ UInt.from_hex = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_hex(j);
|
return (new this()).parse_hex(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,6 +45,7 @@ UInt.from_json = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_json(j);
|
return (new this()).parse_json(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,6 +54,7 @@ UInt.from_bits = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_bits(j);
|
return (new this()).parse_bits(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,6 +63,7 @@ UInt.from_bytes = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_bytes(j);
|
return (new this()).parse_bytes(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +72,7 @@ UInt.from_bn = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_bn(j);
|
return (new this()).parse_bn(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,6 +81,7 @@ UInt.from_number = function(j) {
|
|||||||
if (j instanceof this) {
|
if (j instanceof this) {
|
||||||
return j.clone();
|
return j.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new this()).parse_number(j);
|
return (new this()).parse_number(j);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,34 +138,46 @@ UInt.prototype._update = function() {
|
|||||||
|
|
||||||
// value = NaN on error.
|
// value = NaN on error.
|
||||||
UInt.prototype.parse_generic = function(j) {
|
UInt.prototype.parse_generic = function(j) {
|
||||||
|
const subclass = this.constructor;
|
||||||
|
|
||||||
|
assert(typeof subclass.width === 'number', 'UInt missing width');
|
||||||
|
|
||||||
|
this._value = NaN;
|
||||||
|
|
||||||
switch (j) {
|
switch (j) {
|
||||||
case undefined:
|
case undefined:
|
||||||
case '0':
|
case '0':
|
||||||
case this.constructor.STR_ZERO:
|
case subclass.STR_ZERO:
|
||||||
case this.constructor.ACCOUNT_ZERO:
|
case subclass.ACCOUNT_ZERO:
|
||||||
case this.constructor.HEX_ZERO:
|
case subclass.HEX_ZERO:
|
||||||
this._value = new sjcl.bn(0);
|
this._value = new sjcl.bn(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
case this.constructor.STR_ONE:
|
case subclass.STR_ONE:
|
||||||
case this.constructor.ACCOUNT_ONE:
|
case subclass.ACCOUNT_ONE:
|
||||||
case this.constructor.HEX_ONE:
|
case subclass.HEX_ONE:
|
||||||
this._value = new sjcl.bn(1);
|
this._value = new sjcl.bn(1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (typeof j !== 'string') {
|
if (lodash.isString(j)) {
|
||||||
this._value = NaN;
|
switch (j.length) {
|
||||||
} else if (this.constructor.width === j.length) {
|
case subclass.width:
|
||||||
var hex = utils.arrayToHex(utils.stringToArray(j));
|
const hex = utils.arrayToHex(utils.stringToArray(j));
|
||||||
this._value = new sjcl.bn(hex, 16);
|
this._value = new sjcl.bn(hex, 16);
|
||||||
} else if ((this.constructor.width * 2) === j.length) {
|
break;
|
||||||
// XXX Check char set!
|
case subclass.width * 2:
|
||||||
this._value = new sjcl.bn(j, 16);
|
// Assume hex, check char set
|
||||||
} else {
|
this.parse_hex(j);
|
||||||
this._value = NaN;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (lodash.isNumber(j)) {
|
||||||
|
this.parse_number(j);
|
||||||
|
} else if (lodash.isArray(j)) {
|
||||||
|
// Assume bytes array
|
||||||
|
this.parse_bytes(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._update();
|
this._update();
|
||||||
@@ -166,7 +186,7 @@ UInt.prototype.parse_generic = function(j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.parse_hex = function(j) {
|
UInt.prototype.parse_hex = function(j) {
|
||||||
if (typeof j === 'string' && j.length === (this.constructor.width * 2)) {
|
if (new RegExp(`^[0-9A-Fa-f]{${this.constructor.width * 2}}$`).test(j)) {
|
||||||
this._value = new sjcl.bn(j, 16);
|
this._value = new sjcl.bn(j, 16);
|
||||||
} else {
|
} else {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
@@ -178,12 +198,12 @@ UInt.prototype.parse_hex = function(j) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
UInt.prototype.parse_bits = function(j) {
|
UInt.prototype.parse_bits = function(j) {
|
||||||
if (sjcl.bitArray.bitLength(j) !== this.constructor.width * 8) {
|
if (sjcl.bitArray.bitLength(j) === this.constructor.width * 8) {
|
||||||
this._value = NaN;
|
|
||||||
} else {
|
|
||||||
this._value = sjcl.bn.fromBits(j);
|
this._value = sjcl.bn.fromBits(j);
|
||||||
// var bytes = sjcl.codec.bytes.fromBits(j);
|
// let bytes = sjcl.codec.bytes.fromBits(j);
|
||||||
// this.parse_bytes(bytes);
|
// this.parse_bytes(bytes);
|
||||||
|
} else {
|
||||||
|
this._value = NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._update();
|
this._update();
|
||||||
@@ -193,11 +213,11 @@ UInt.prototype.parse_bits = function(j) {
|
|||||||
|
|
||||||
|
|
||||||
UInt.prototype.parse_bytes = function(j) {
|
UInt.prototype.parse_bytes = function(j) {
|
||||||
if (!Array.isArray(j) || j.length !== this.constructor.width) {
|
if (Array.isArray(j) && j.length === this.constructor.width) {
|
||||||
this._value = NaN;
|
const bits = sjcl.codec.bytes.toBits(j);
|
||||||
} else {
|
|
||||||
var bits = sjcl.codec.bytes.toBits(j);
|
|
||||||
this._value = sjcl.bn.fromBits(bits);
|
this._value = sjcl.bn.fromBits(bits);
|
||||||
|
} else {
|
||||||
|
this._value = NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._update();
|
this._update();
|
||||||
@@ -209,8 +229,7 @@ UInt.prototype.parse_bytes = function(j) {
|
|||||||
UInt.prototype.parse_json = UInt.prototype.parse_hex;
|
UInt.prototype.parse_json = UInt.prototype.parse_hex;
|
||||||
|
|
||||||
UInt.prototype.parse_bn = function(j) {
|
UInt.prototype.parse_bn = function(j) {
|
||||||
if ((j instanceof sjcl.bn) &&
|
if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {
|
||||||
j.bitLength() <= this.constructor.width * 8) {
|
|
||||||
this._value = new sjcl.bn(j);
|
this._value = new sjcl.bn(j);
|
||||||
} else {
|
} else {
|
||||||
this._value = NaN;
|
this._value = NaN;
|
||||||
@@ -238,6 +257,7 @@ UInt.prototype.to_bytes = function() {
|
|||||||
if (!this.is_valid()) {
|
if (!this.is_valid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sjcl.codec.bytes.fromBits(this.to_bits());
|
return sjcl.codec.bytes.fromBits(this.to_bits());
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -245,6 +265,7 @@ UInt.prototype.to_hex = function() {
|
|||||||
if (!this.is_valid()) {
|
if (!this.is_valid()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
|
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -263,7 +284,7 @@ UInt.prototype.to_bn = function() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bits = this.to_bits();
|
const bits = this.to_bits();
|
||||||
|
|
||||||
return sjcl.bn.fromBits(bits);
|
return sjcl.bn.fromBits(bits);
|
||||||
};
|
};
|
||||||
|
|||||||
1675
test/fixtures/uint.json
vendored
Normal file
1675
test/fixtures/uint.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,104 @@
|
|||||||
var assert = require('assert');
|
'use strict';
|
||||||
var UInt128 = require('ripple-lib').UInt128;
|
|
||||||
|
|
||||||
describe('UInt', function() {
|
/* eslint-disable max-len */
|
||||||
describe('128', function() {
|
|
||||||
describe('#parse_number', function () {
|
const assert = require('assert-diff');
|
||||||
it('should create 00000000000000000000000000000000 when called with 0', function () {
|
const lodash = require('lodash');
|
||||||
var val = UInt128.from_number(0);
|
const ripple = require('ripple-lib');
|
||||||
assert.strictEqual(val.to_hex(), '00000000000000000000000000000000');
|
const fixtures = require('./fixtures/uint');
|
||||||
|
|
||||||
|
function resultError(test, result) {
|
||||||
|
function type(e) {
|
||||||
|
return Object.prototype.toString.call(e);
|
||||||
|
}
|
||||||
|
return `Expected ${type(test.input)}: ${test.input} to yield ${type(test.expected)}: ${test.expected === 'null' ? NaN : test.expected}. Actual: ${type(result)}: ${result}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeTests(uIntType) {
|
||||||
|
describe(uIntType, function() {
|
||||||
|
const rippleType = ripple[uIntType];
|
||||||
|
const tests = fixtures[uIntType];
|
||||||
|
|
||||||
|
it('from_json().to_json()', function() {
|
||||||
|
tests['from_json().to_json()'].forEach(function(test) {
|
||||||
|
let result = rippleType.from_json(test.input);
|
||||||
|
assert.strictEqual(result.is_valid(), String(test.expected) !== 'null', `Validity check failed: ${test.input}`);
|
||||||
|
result = result.to_json();
|
||||||
|
|
||||||
|
if (test.expected === 'null') {
|
||||||
|
// XXX
|
||||||
|
// UInt160.to_json() returns NaN rather than null if input is invalid
|
||||||
|
assert.strictEqual(lodash.isNaN(result), true, resultError(test, result));
|
||||||
|
} else {
|
||||||
|
assert.strictEqual(result, test.expected, resultError(test, result));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
it('should create 00000000000000000000000000000001 when called with 1', function () {
|
});
|
||||||
var val = UInt128.from_number(1);
|
it('from_json().to_bytes()', function() {
|
||||||
assert.strictEqual(val.to_hex(), '00000000000000000000000000000001');
|
tests['from_json().to_bytes()'].forEach(function(test) {
|
||||||
|
const result = rippleType.from_json(test.input);
|
||||||
|
assert.strictEqual(result.is_valid(), String(test.expected) !== 'null', `Validity check failed: ${test.input}`);
|
||||||
|
assert.deepEqual(result.to_bytes(), test.expected, resultError(test, result));
|
||||||
});
|
});
|
||||||
it('should create 000000000000000000000000FFFFFFFF when called with 0xFFFFFFFF', function () {
|
});
|
||||||
var val = UInt128.from_number(0xFFFFFFFF);
|
it('from_number().to_json()', function() {
|
||||||
assert.strictEqual(val.to_hex(), '000000000000000000000000FFFFFFFF');
|
tests['from_number().to_json()'].forEach(function(test) {
|
||||||
|
let result = rippleType.from_number(test.input);
|
||||||
|
assert.strictEqual(result.is_valid(), String(test.expected) !== 'null', `Validity check failed: ${test.input}`);
|
||||||
|
result = result.to_json();
|
||||||
|
|
||||||
|
if (test.expected === 'null') {
|
||||||
|
// XXX
|
||||||
|
// UInt160.to_json() returns NaN rather than null if input is invalid
|
||||||
|
assert.strictEqual(lodash.isNaN(result), true, resultError(test, result));
|
||||||
|
} else {
|
||||||
|
assert.strictEqual(result, test.expected, resultError(test, result));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('from_number().to_hex()', function() {
|
||||||
|
tests['from_number().to_hex()'].forEach(function(test) {
|
||||||
|
const result = rippleType.from_number(test.input);
|
||||||
|
assert.strictEqual(result.is_valid(), String(test.expected) !== 'null', `Validity check failed: ${test.input}`);
|
||||||
|
assert.strictEqual(result.to_hex(), test.expected, resultError(test, result));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('from_generic().to_*()', function() {
|
||||||
|
tests['from_generic().to_*()'].forEach(function(test) {
|
||||||
|
let result = rippleType.from_generic(test.input);
|
||||||
|
|
||||||
|
switch (test.input) {
|
||||||
|
// XXX
|
||||||
|
// from_generic() accepts these as "zero"
|
||||||
|
case 0:
|
||||||
|
case '0':
|
||||||
|
case undefined:
|
||||||
|
switch (test.outputMethod) {
|
||||||
|
case 'to_bytes':
|
||||||
|
test.expected = Array(rippleType.width).fill(0);
|
||||||
|
break;
|
||||||
|
case 'to_json':
|
||||||
|
case 'to_hex':
|
||||||
|
test.expected = Array(rippleType.width * 2).fill(0).join('');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.strictEqual(result.is_valid(), String(test.expected) !== 'null',
|
||||||
|
`Validity check failed: ${test.input} > ${test.expected}`);
|
||||||
|
|
||||||
|
result = result[test.outputMethod]();
|
||||||
|
|
||||||
|
if (test.expected === 'null') {
|
||||||
|
// XXX
|
||||||
|
// UInt160.to_json() returns NaN rather than null if input is invalid
|
||||||
|
assert.strictEqual(lodash.isNaN(result), true, resultError(test, result));
|
||||||
|
} else {
|
||||||
|
assert.deepEqual(result, test.expected, resultError(test, result));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
// vim:sw=2:sts=2:ts=8:et
|
['UInt128', 'UInt160', 'UInt256'].forEach(makeTests);
|
||||||
|
|||||||
Reference in New Issue
Block a user