Skip to content

Commit

Permalink
[Fix] support multi-byte wide typed arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
ChALkeR authored and ljharb committed Nov 26, 2024
1 parent 00c7f23 commit f76e123
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
12 changes: 12 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,17 @@
"max-lines-per-function": "off",
},
},
{
"files": "hash.js",
"globals": {
"Uint8Array": false,
},
},
{
"files": "test/test.js",
"globals": {
"Uint16Array": false,
},
},
],
}
34 changes: 33 additions & 1 deletion hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

var Buffer = require('safe-buffer').Buffer;

var useArrayBuffer = typeof ArrayBuffer !== 'undefined'
&& typeof Uint8Array !== 'undefined'
&& ArrayBuffer.isView;

// prototype class for hash functions
function Hash(blockSize, finalSize) {
this._block = Buffer.alloc(blockSize);
Expand All @@ -12,9 +16,37 @@ function Hash(blockSize, finalSize) {

Hash.prototype.update = function (data, enc) {
/* eslint no-param-reassign: 0 */
if (typeof data === 'string') {
if (data instanceof Uint8Array) {
/*
* Fast path
* Already single-byte wide and 0-255
*/
} else if (typeof data === 'string') {
enc = enc || 'utf8';
data = Buffer.from(data, enc);
} else if (useArrayBuffer && ArrayBuffer.isView(data)) {
// Convert all TypedArray and DataView instances to single-byte-wide Uint8Array views
var oldSize = data.byteLength;
data = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);

if (!(data.byteLength === oldSize && data.byteLength === data.length)) {
throw new Error('Unexpected: broken Uint8Array');
}
} else {
if (!data || typeof data !== 'object' || typeof data.length !== 'number') {
throw new TypeError('Not an array-like');
}

// non-negative 32-bit integer
if ((data.length >>> 0) !== data.length) {
throw new RangeError('Invalid length');
}

for (var j = 0; j < data.length; j++) {
if ((data[j] & 255) !== data[j]) {
throw new TypeError('Not a byte array');
}
}
}

var block = this._block;
Expand Down
32 changes: 28 additions & 4 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ var inputs = [
['123456789abcdef123456789abcdef123456789abcdef123456789ab', 'ascii'],
['0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde', 'ascii'],
['0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', 'ascii'],
['foobarbaz', 'ascii']
];
['foobarbaz', 'ascii'],
typeof Uint16Array === 'function' ? [new Uint16Array([1, 2, 3])] : null
].filter(Boolean);

tape("hash is the same as node's crypto", function (t) {
inputs.forEach(function (v) {
Expand All @@ -35,7 +36,7 @@ tape('call update multiple times', function (t) {
var sha1hash = crypto.createHash('sha1');

for (var i = 0; i < v[0].length; i = (i + 1) * 2) {
var s = v[0].substring(i, (i + 1) * 2);
var s = v[0].slice(i, (i + 1) * 2);
hash.update(s, v[1]);
sha1hash.update(s, v[1]);
}
Expand Down Expand Up @@ -74,7 +75,7 @@ tape('hex encoding', function (t) {
var sha1hash = crypto.createHash('sha1');

for (var i = 0; i < v[0].length; i = (i + 1) * 2) {
var s = v[0].substring(i, (i + 1) * 2);
var s = v[0].slice(i, (i + 1) * 2);
hash.update(Buffer.from(s, 'ascii').toString('hex'), 'hex');
sha1hash.update(Buffer.from(s, 'ascii').toString('hex'), 'hex');
}
Expand All @@ -88,6 +89,29 @@ tape('hex encoding', function (t) {
t.end();
});

tape('throws on invalid input', function (t) {
var invalid = [
{}, // non-arrayish
{ length: 20 }, // undefined values
[NaN], // non-numbers
[[]], // non-numbers
[1, 1.5], // non-integers
[1, 256], // out of bounds
[-1, 0] // out of bounds
];

invalid.forEach(function (input) {
var hash = new Sha1();

t['throws'](function () {
hash.update(input);
hash.digest('hex');
});
});

t.end();
});

tape('call digest for more than MAX_UINT32 bits of data', function (t) {
var sha1hash = crypto.createHash('sha1');
var hash = new Sha1();
Expand Down

0 comments on commit f76e123

Please sign in to comment.