Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] return valid values on multi-byte-wide TypedArray input #23

Merged
merged 1 commit into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
"func-style": "off",
},

"globals": {
"Uint8Array": false,
"Uint16Array": false,
},

"overrides": [
{
"files": [
Expand Down
41 changes: 40 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,47 @@ function CipherBase(hashMode) {
}
inherits(CipherBase, Transform);

var useUint8Array = typeof Uint8Array !== 'undefined';
var useArrayBuffer = typeof ArrayBuffer !== 'undefined'
&& typeof Uint8Array !== 'undefined'
&& ArrayBuffer.isView
&& (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT);

CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
var bufferData = typeof data === 'string' ? Buffer.from(data, inputEnc) : data;
var bufferData;
if (data instanceof Buffer) {
// No need to do anything
bufferData = data;
} else if (typeof data === 'string') {
// Convert strings to Buffer
bufferData = Buffer.from(data, inputEnc);
} else if (useArrayBuffer && ArrayBuffer.isView(data)) {
/*
* Wrap any TypedArray instances and DataViews
* Makes sense only on engines with full TypedArray support -- let Buffer detect that
*/
bufferData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
} else if (useUint8Array && data instanceof Uint8Array) {
/*
* Uint8Array in engines where Buffer.from might not work with ArrayBuffer, just copy over
* Doesn't make sense with other TypedArray instances
*/
bufferData = Buffer.from(data);
} else if (
Buffer.isBuffer(data)
&& data.constructor
&& data.constructor.isBuffer
&& data.constructor.isBuffer(data)
) {
/*
* Old Buffer polyfill on an engine that doesn't have TypedArray support
* Also, this is from a different Buffer polyfill implementation then we have, as instanceof check failed
* Convert to our current Buffer implementation
*/
bufferData = Buffer.from(data);
} else {
throw new Error('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
}

var outData = this._update(bufferData);
if (this.hashMode) {
Expand Down
25 changes: 25 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,28 @@ test('encodings', function (t) {
st.equals(txt, enc);
});
});

test('handle UInt16Array', function (t) {
function Cipher() {
CipherBase.call(this, 'finalName');
this._cache = [];
}
inherits(Cipher, CipherBase);
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input));
this._cache.push(input);
};
Cipher.prototype._final = function () {
return Buffer.concat(this._cache);
};

if (ArrayBuffer.isView && (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT)) {
var cipher = new Cipher();
var final = cipher.update(new Uint16Array([1234, 512])).finalName('hex');
t.equals(final, 'd2040002');
} else {
t.skip('ArrayBuffer.isView and/or TypedArray not fully supported');
}

t.end();
});