-
Notifications
You must be signed in to change notification settings - Fork 30k
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
tls: fix convertALPNProtocols accepting ArrayBufferViews #43211
tls: fix convertALPNProtocols accepting ArrayBufferViews #43211
Conversation
Review requested:
|
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
403e1e3
to
15930c1
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
@@ -143,9 +146,13 @@ exports.convertALPNProtocols = function convertALPNProtocols(protocols, out) { | |||
// If protocols is Array - translate it into buffer | |||
if (ArrayIsArray(protocols)) { | |||
out.ALPNProtocols = convertProtocols(protocols); | |||
} else if (isArrayBufferView(protocols)) { | |||
} else if (Buffer.isBuffer(protocols) || isUint8Array(protocols)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is isUint8Array()
faster than isArrayBufferView()
? If not we can remove it as it would be handled by the isArrayBufferView()
check below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question here is, is Buffer.from(buffer)
faster or better than Buffer.from(arrayBuffer, byteOffset, length)
? Having Buffer
or Uint8Array
here is expected in most cases, otherwise we would got bugreports for this.
I don't really know but my guess is "yes, it should be faster" because Buffer
tends to use shared pools, and by doing buffer.slice()
we would copy the whole pool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really know but my guess is "yes, it should be faster" because
Buffer
tends to use shared pools, and by doingbuffer.slice()
we would copy the whole pool.
We should keep it as is when protocols
is a Buffer
but when it is an Uint8Array
I'm not sure. AFAIK there is no pool for Uint8Array
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway it is not very important, it would only slightly improve readability by removing the OR condition. Feel free to ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, tested it and
const { Buffer } = require('node:buffer');
console.log(Buffer.from(new Uint8Array([1,2,3])).buffer.byteLength);
Shows 8192 😕
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ node
Welcome to Node.js v18.2.0.
Type ".help" for more information.
> const arr = new Uint8Array([1,2,3]);
undefined
> arr.buffer.byteLength
3
> const buf = Buffer.from(arr.slice(), arr.byteOffset, arr.byteLength);
undefined
> buf.buffer.byteLength
8192
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ ./node
Welcome to Node.js v19.0.0-pre.
Type ".help" for more information.
> const arr = new Uint8Array([1,2,3]);
undefined
> const buf = Buffer.from(arr.buffer.slice(), arr.byteOffset, arr.byteLength);
undefined
> buf.buffer.byteLength
3
The one above uses Uint8Array
directly rather than ArrayBuffer
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, sorry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't that the point of speedup? I mean, because of that in practice we should prefer doing Buffer.from(arr) directly so it will be able to reuse preallocated pool.
Yes, it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it was the right direction, applicable to the next branch. I forgot that TypedArray.prototype.slice().buffer
, unlike Buffer
's version, does exactly what's needed there. Calling .buffer.slice()
without arguments is in fact a huge mistake.
Unfortunately, DataView
is not a TypedArray
and supporting it requires slightly different approach.
Synthetic microbenchmarking shows ~50% speedup for TypedArray
way over DataView
, and ~700% for Buffer|Uint8Array
way over DataView
for me.
If readability suffered too much from that, last else if (isArrayBufferView)
branch can be removed. Otherwise it seems to be the most correct workaround (at least until Buffer.from(anyArrayBufferView)
is somehow supported 😄).
This comment was marked as outdated.
This comment was marked as outdated.
PR-URL: nodejs#43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
220bc10
to
15a682c
Compare
Landed in 15a682c |
The tls/convertprotocols.js benchmark is showing a ~7.5% performance regression after this commit. Looking at the changes, do we really need |
The node/benchmark/tls/convertprotocols.js Line 11 in d72dcb0
Which is covered by the very first condition; so I'm not sure as well. As long as it doesn't affect readability, yes, it's worth a try to remove |
PR-URL: #43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs#43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: #43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: #43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: #43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#43211 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Fix for
ArrayBufferView
s that are notUint8Array
.I believe it should be eventually adjusted on
buffer
side, but not sure if it would be easy or worth potential breakage.Audit through
make test
gave me two misuses, both test-only and safe:node/test/parallel/test-buffer-alloc.js
Lines 46 to 47 in a346572
node/test/parallel/test-webcrypto-random.js
Lines 50 to 51 in a346572
However, there could still be similar bugs within
crypto
in places whereBuffer.from(buffer)
is used./cc @nodejs/crypto