-
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
crypto: fix memory leak, reduce heap allocations, clean up #14122
Conversation
8047566
to
67911e3
Compare
I added a commit that fixes the DH memory leak reported in #8377. |
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.
Largely rubber-stamp LGTM. Looked through the code and didn't see anything that stood out but didn't do a thorough review.
67911e3
to
eaf2825
Compare
Bumped DH key size in test to 1024 to pacify FIPS. New CI: https://ci.nodejs.org/job/node-test-pull-request/9094/ |
Don't allocate + copy + free; allocate and fill in place, then hand off the pointer to Buffer::New(). Avoids unnecessary heap allocations in the following methods: - crypto.Cipher#final() - crypto.Cipher#update() - crypto.Cipheriv#final() - crypto.Cipheriv#update() - crypto.Decipher#final() - crypto.Decipher#update() - crypto.Decipheriv#final() - crypto.Decipheriv#update() - crypto.privateDecrypt() - crypto.privateEncrypt() - crypto.publicDecrypt() - crypto.publicEncrypt()
Put the 8 kB initial buffer on the stack first and don't copy it to the heap until its exact size is known (which is normally much smaller.)
Fix a memory leak by removing the heap allocation altogether. Fixes: nodejs#13917
The EVP_CIPHER can be reconstructed from the EVP_CIPHER_CTX instance, no need to store it separately. This brought to light the somewhat dubious practice of accessing the EVP_CIPHER after the EVP_CIPHER_CTX instance had been destroyed. It's mostly harmless due to the static nature of built-in EVP_CIPHER instances but it segfaults when the cipher is provided by an ENGINE and the ENGINE is unloaded because its reference count drops to zero.
The cipher kind doesn't change over the lifetime of the cipher so make it const.
Don't allocate + copy + free; allocate and fill in place, then hand off the pointer to Buffer::New(). Avoids unnecessary heap allocations in the following methods: - crypto.CryptoStream#getSession() - tls.TLSSocket#getSession()
Add a test that ensures the second call to .digest() returns an empty HMAC, like it did before. No comment on whether that is the right behavior or not.
Replace allocate + Encode() + free patterns by calls to Malloc + the Buffer::New() overload that takes ownership of the pointer. Avoids unnecessary heap allocations and copying around of data. DRY the accessor functions for the prime, generator, public key and private key properties; deletes about 40 lines of quadruplicated code.
This also renames a misnamed variable `error_` to `success_`.
Fix a memory leak in dh.setPublicKey() and dh.setPrivateKey() where the old keys weren't freed. Fixes: nodejs#8377
eaf2825
to
e4ac1b6
Compare
One more rebase + CI: https://ci.nodejs.org/job/node-test-pull-request/9192/ |
Stress test to see if the async-hooks/test-tlswrap failure on the osx1010 bot is a flake or not: https://ci.nodejs.org/job/node-stress-single-test/1319/ |
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Don't allocate + copy + free; allocate and fill in place, then hand off the pointer to Buffer::New(). Avoids unnecessary heap allocations in the following methods: - crypto.Cipher#final() - crypto.Cipher#update() - crypto.Cipheriv#final() - crypto.Cipheriv#update() - crypto.Decipher#final() - crypto.Decipher#update() - crypto.Decipheriv#final() - crypto.Decipheriv#update() - crypto.privateDecrypt() - crypto.privateEncrypt() - crypto.publicDecrypt() - crypto.publicEncrypt() PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Put the 8 kB initial buffer on the stack first and don't copy it to the heap until its exact size is known (which is normally much smaller.) PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
The EVP_CIPHER can be reconstructed from the EVP_CIPHER_CTX instance, no need to store it separately. This brought to light the somewhat dubious practice of accessing the EVP_CIPHER after the EVP_CIPHER_CTX instance had been destroyed. It's mostly harmless due to the static nature of built-in EVP_CIPHER instances but it segfaults when the cipher is provided by an ENGINE and the ENGINE is unloaded because its reference count drops to zero. PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
The cipher kind doesn't change over the lifetime of the cipher so make it const. PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Don't allocate + copy + free; allocate and fill in place, then hand off the pointer to Buffer::New(). Avoids unnecessary heap allocations in the following methods: - crypto.CryptoStream#getSession() - tls.TLSSocket#getSession() PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Add a test that ensures the second call to .digest() returns an empty HMAC, like it did before. No comment on whether that is the right behavior or not. PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Replace allocate + Encode() + free patterns by calls to Malloc + the Buffer::New() overload that takes ownership of the pointer. Avoids unnecessary heap allocations and copying around of data. DRY the accessor functions for the prime, generator, public key and private key properties; deletes about 40 lines of quadruplicated code. PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This also renames a misnamed variable `error_` to `success_`. PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: #14122 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
@bnoordhuis is this something we would want to backport to v6.x? |
Yes. |
@bnoordhuis this is going to require a manual backport. Would you be willing to help with this? We could choose to simply not land the commits that have conflicts, up for suggestion on best path forward |
ping @bnoordhuis |
Depends on #16587, the new internal APIs need to be back-ported first. |
@bnoordhuis #16587 has landed, would you be able to backport this now? |
Fixes: #13917
Also of note:
I'll clean up the commit logs some more before landing.
CI: https://ci.nodejs.org/job/node-test-pull-request/9027/