Skip to content

Commit 8fd1364

Browse files
ChALkeRljharb
authored andcommitted
[Fix] return valid values on multi-byte-wide TypedArray input
1 parent 66387d7 commit 8fd1364

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

.eslintrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
"func-style": "off",
88
},
99

10+
"globals": {
11+
"Uint8Array": false,
12+
"Uint16Array": false,
13+
},
14+
1015
"overrides": [
1116
{
1217
"files": [

index.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,47 @@ function CipherBase(hashMode) {
2222
}
2323
inherits(CipherBase, Transform);
2424

25+
var useUint8Array = typeof Uint8Array !== 'undefined';
26+
var useArrayBuffer = typeof ArrayBuffer !== 'undefined'
27+
&& typeof Uint8Array !== 'undefined'
28+
&& ArrayBuffer.isView
29+
&& (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT);
30+
2531
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
26-
var bufferData = typeof data === 'string' ? Buffer.from(data, inputEnc) : data;
32+
var bufferData;
33+
if (data instanceof Buffer) {
34+
// No need to do anything
35+
bufferData = data;
36+
} else if (typeof data === 'string') {
37+
// Convert strings to Buffer
38+
bufferData = Buffer.from(data, inputEnc);
39+
} else if (useArrayBuffer && ArrayBuffer.isView(data)) {
40+
/*
41+
* Wrap any TypedArray instances and DataViews
42+
* Makes sense only on engines with full TypedArray support -- let Buffer detect that
43+
*/
44+
bufferData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
45+
} else if (useUint8Array && data instanceof Uint8Array) {
46+
/*
47+
* Uint8Array in engines where Buffer.from might not work with ArrayBuffer, just copy over
48+
* Doesn't make sense with other TypedArray instances
49+
*/
50+
bufferData = Buffer.from(data);
51+
} else if (
52+
Buffer.isBuffer(data)
53+
&& data.constructor
54+
&& data.constructor.isBuffer
55+
&& data.constructor.isBuffer(data)
56+
) {
57+
/*
58+
* Old Buffer polyfill on an engine that doesn't have TypedArray support
59+
* Also, this is from a different Buffer polyfill implementation then we have, as instanceof check failed
60+
* Convert to our current Buffer implementation
61+
*/
62+
bufferData = Buffer.from(data);
63+
} else {
64+
throw new Error('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
65+
}
2766

2867
var outData = this._update(bufferData);
2968
if (this.hashMode) {

test/index.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,28 @@ test('encodings', function (t) {
128128
st.equals(txt, enc);
129129
});
130130
});
131+
132+
test('handle UInt16Array', function (t) {
133+
function Cipher() {
134+
CipherBase.call(this, 'finalName');
135+
this._cache = [];
136+
}
137+
inherits(Cipher, CipherBase);
138+
Cipher.prototype._update = function (input) {
139+
t.ok(Buffer.isBuffer(input));
140+
this._cache.push(input);
141+
};
142+
Cipher.prototype._final = function () {
143+
return Buffer.concat(this._cache);
144+
};
145+
146+
if (ArrayBuffer.isView && (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT)) {
147+
var cipher = new Cipher();
148+
var final = cipher.update(new Uint16Array([1234, 512])).finalName('hex');
149+
t.equals(final, 'd2040002');
150+
} else {
151+
t.skip('ArrayBuffer.isView and/or TypedArray not fully supported');
152+
}
153+
154+
t.end();
155+
});

0 commit comments

Comments
 (0)