-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
crypto: better crypto error messages #14725
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
Conversation
Feature request to add openSSL error stack to the exception object thrown from crypto. New exception property only added to object if the error stack has not cleared out prior to calling ThrowCryptoError. Refs: nodejs#5444
|
Decided to open up this PR with my initial commit to get some general feedback to see if this is what was expected and if i'm on the right track. I didn't include any tests at this time since im just making sure what I have right now is correct. Once I know if this is correct or not, i'll add some tests. |
| void ThrowCryptoError(Environment* env, | ||
| unsigned long err, // NOLINT(runtime/int) | ||
| const char* default_message = nullptr) { | ||
| HandleScope scope(env->isolate()); |
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.
Below is the bulk of the change. Updated ThrowCryptoError to get the current error state and add the stack to a new property on the exception object. I figured it would be a good idea to include the errorStack regardless if the error passed in is a default_message or openSSL error.
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.
Also. Do i need to change any documentation on this? if so, where is it located?
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.
docs would be somewhere in here: https://github.com/nodejs/node/blob/master/doc/api/errors.md#class-error
There is no specific class for crypto errors, so docs will just have to go with generic Error but described as "only for crypto"
src/node_crypto.cc
Outdated
|
|
||
| ClearErrorOnReturn clear_error_on_return; | ||
| // ClearErrorOnReturn clear_error_on_return; | ||
|
|
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.
so i comment out this line for now. Maybe i'm wrong, but it feels like this was in the wrong spot. This is not the binding function and I thought the openssl's error stack needs to be balanced upon entry and exit of the VerifyFinal bound function. So i moved it there. Please let me know if im wrong and I'll uncomment this and remove the line from the bound function, but I might need a little guidance on what I need to move around to not clear out the error stack when exiting this function. Maybe we just throw the error from this function instead of the bound function?
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.
You make a compelling case, but I would have to look more closely and don't have time right now. I think there was a bug recently where sign failure was causing subsequent operations to fail because stack wasn't cleared, but that just means its important to do, not that its important to do here, so this needs careful thought.
|
|
||
| ERR_set_mark(); | ||
|
|
||
| bp = BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len); |
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.
setting the err mark. #5444 (comment). Im not sure where else we might need to do this in this file.
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 admit I don't understand why that is necessary when you have a ClearErrorOnReturn in the binding function.
|
|
||
| ClearErrorOnReturn clear_error_on_return; | ||
|
|
||
| Verify* verify; |
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.
here is adding the clear_error_on_return in the function thats bound
|
|
||
| Verify* verify; | ||
| ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); | ||
|
|
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.
Will add tests once I know if this is correct route to handle this or what I need to change
|
|
||
| exception->Set(env->context(), key, errorStack).FromJust(); | ||
| env->isolate()->ThrowException(exception); | ||
| } |
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.
new property looks like this
openSSLErrorStack:
[ 'error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib',
'error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error' ]
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.
Useful comment, please put it in the source code
|
@nodejs/crypto |
src/node_crypto.cc
Outdated
| ERR_error_string_n(err, errmsg, sizeof(errmsg)); | ||
| env->ThrowError(errmsg); | ||
| message = String::NewFromUtf8(env->isolate(), errmsg, | ||
| v8::NewStringType::kInternalized) |
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.
maybe the performance diff isn't observable, but I wonder if errors are thrown enough for it to be worth internalizing the string
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'll change this to normal and the one below in the else
src/node_crypto.cc
Outdated
|
|
||
| Local<Value> exception_v = Exception::Error(message); | ||
| CHECK(!exception_v.IsEmpty()); | ||
| // add the openSSLErrorStack property |
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 comment style is to have capitalized and punctuated sentences, pls take a look at all the comments
src/node_crypto.cc
Outdated
|
|
||
| // get the error state | ||
| // will only add to errorStack if state has not been cleared out | ||
| ERR_STATE *es; |
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.
merge this line with next, so declaration and initialization is done in one line
src/node_crypto.cc
Outdated
|
|
||
| // add content to the openssl error stack | ||
| unsigned int i = 0; | ||
| while (es->bottom != es->top |
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.
given that this while loop has an initialization before it, and increments its state at the end, should it be a for loop?
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.
Yup. Will do
src/node_crypto.cc
Outdated
| unsigned long err_buf = es->err_buffer[es->top]; // NOLINT(runtime/int) | ||
| // only add if there is valid err_buffer | ||
| if (err_buf) { | ||
| char tmpStr[128] = { 0 }; |
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'd choose 256, it is what ERR_error_string() uses. I think it doesn't need zero initialization, ERR_error_string_n() terminates.
|
|
||
| exception->Set(env->context(), key, errorStack).FromJust(); | ||
| env->isolate()->ThrowException(exception); | ||
| } |
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.
Useful comment, please put it in the source code
src/node_crypto.cc
Outdated
|
|
||
| ClearErrorOnReturn clear_error_on_return; | ||
| // ClearErrorOnReturn clear_error_on_return; | ||
|
|
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.
You make a compelling case, but I would have to look more closely and don't have time right now. I think there was a bug recently where sign failure was causing subsequent operations to fail because stack wasn't cleared, but that just means its important to do, not that its important to do here, so this needs careful thought.
| void ThrowCryptoError(Environment* env, | ||
| unsigned long err, // NOLINT(runtime/int) | ||
| const char* default_message = nullptr) { | ||
| HandleScope scope(env->isolate()); |
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.
docs would be somewhere in here: https://github.com/nodejs/node/blob/master/doc/api/errors.md#class-error
There is no specific class for crypto errors, so docs will just have to go with generic Error but described as "only for crypto"
|
Added some updates from previous review and tests |
| const credentials = tls.createSecureContext(options); | ||
| const context = credentials.context; | ||
| const notcontext = { setOptions: context.setOptions, setKey: context.setKey }; | ||
| tls.createSecureContext({ secureOptions: 1 }, notcontext); |
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.
Updated tests below to check for existence of new openSSLErrorStack property for when it should and should not be there
|
ping @sam-github, most of your comments have been addressed |
doc/api/errors.md
Outdated
| provide a text description of the error. | ||
| provide a text description of the error. For crypto only, `Error` objects will | ||
| include the OpenSSL error stack, if it's available when the error is thrown, in | ||
| a separate property. |
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.
tiny nits: use long forms (it's → it is) and I’d put the sentence in a new paragraph.
src/node_crypto.cc
Outdated
| env->ThrowError(errmsg); | ||
| message = String::NewFromUtf8(env->isolate(), errmsg, | ||
| v8::NewStringType::kNormal) | ||
| .ToLocalChecked(); |
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.
tiny style nit: 4 spaces indentation for statement continuations (applies elsewhere too)
src/node_crypto.cc
Outdated
| Local<Object> exception = exception_v.As<Object>(); | ||
| Local<String> key = String::NewFromUtf8(env->isolate(), "openSSLErrorStack", | ||
| v8::NewStringType::kInternalized) | ||
| .ToLocalChecked(); |
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 think you can feel free to add this to the list in env.h. (Also, using FIXED_ONE_BYTE_STRING should be okay here too.)
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.
@addaleax thanks for reviewing this. Just to clarify, you're saying that I could add the property to list in env.h or use FIXED_ONE_BYTE_STRING, correct?
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.
Yes – either one is fine, and I’d have a slight preference for the former :)
| // The openSSL stack should have content. | ||
| if ((err instanceof Error) && | ||
| /asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag/.test(err) && | ||
| err.openSSLErrorStack !== undefined && |
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.
Maybe be more specific here and check Array.isArray(err.openSSLErrorStack)?
| v8::NewStringType::kNormal) | ||
| .ToLocalChecked(); | ||
| .ToLocalChecked(); | ||
| } else { |
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.
added additional space to these since its a continuation of line
src/node_crypto.cc
Outdated
| Local<Object> exception = exception_v.As<Object>(); | ||
| Local<Array> errorStack = Array::New(env->isolate()); | ||
|
|
||
| ERR_STATE *es = ERR_get_state(); |
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.
This seems to allocate memory, where does that get freed?
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 thought that the openssl lib would take care of this, but maybe my assumption is incorrect?
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’m not sure myself. 😄
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.
My thinking is that we should probably just let the openssl lib free the memory. ERR_get_state will return a pointer to the err state struct that was allocated by openssl. If we try to free that memory here, wont that cause potential issues down the line if other functions need to access it/try to read the reference it has to it?
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.
You can't (shouldn't) free the memory, openssl takes care of it internally.
src/node_crypto.cc
Outdated
| if (err_buf) { | ||
| char tmpStr[256] = { }; | ||
| ERR_error_string_n(err_buf, tmpStr, sizeof(tmpStr)); | ||
| errorStack->Set(i, String::NewFromUtf8(env->isolate(), tmpStr, |
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.
Can you always use the overload of Set() that takes a context argument/returns a Maybe? The other one is deprecated.
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.
sure
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.
And its ok that I get a compiler warning warning: ignoring return value of function declared with 'warn_unused_result' attribute?
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.
You’d call .FromJust()on the result, just like .ToLocalChecked() for MaybeLocals :)
src/node_crypto.cc
Outdated
| Local<Object> exception = exception_v.As<Object>(); | ||
| Local<Array> errorStack = Array::New(env->isolate()); | ||
|
|
||
| ERR_STATE *es = ERR_get_state(); |
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.
You can't (shouldn't) free the memory, openssl takes care of it internally.
src/node_crypto.cc
Outdated
| Local<Value> exception_v = Exception::Error(message); | ||
| CHECK(!exception_v.IsEmpty()); | ||
| Local<Object> exception = exception_v.As<Object>(); | ||
| Local<Array> errorStack = Array::New(env->isolate()); |
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.
Style issue: use snake_case for locals, not camelCase.
|
So i believe i have addressed everyones review comments. The only thing left outstanding is the comment about moving |
|
There has not been any activity on this for several days now. @addaleax @bnoordhuis is there anything else that should be done on this? |
|
@gla5001 Thanks for the ping – as far as I am concerned, the code looks good, but I’m not familiar enough with OpenSSL’s APIs to give this an approval. ping @nodejs/crypto |
When ESM support was added it created a regression in the test runner that broke the ability to run individual tests. This commit re-introduces the use of `NormalizePath` which fixes the regression in the test runner Refs: nodejs#15300 PR-URL: nodejs#15329 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Update AUTHORS list using tools/update-authors.sh. Update .mailmap to handle duplicates. PR-URL: nodejs#15181 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Khaidi Chu <i@2333.moe> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
PR-URL: nodejs#15002 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
PR-URL: nodejs#15235 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
`domain.dispose()` is generally considered an anti-pattern, has been runtime-deprecated for over 4 years, and is a part of the `domain` module that can not be emulated by `async_hooks`; so remove it. Ref: https://nodejs.org/en/docs/guides/domain-postmortem/ Ref: 4a74fc9 PR-URL: nodejs#15412 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Currently the following compiler warning is generated:
1 warning generated.
../src/udp_wrap.cc:238:12: warning: comparison of integers of different
signs: 'int' and 'uint32_t' (aka 'unsigned int') [-Wsign-compare]
if (size != args[0].As<Uint32>()->Value()) {
~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
This commit changes the check to see that the Uint32 value does not
exceed the max int size instead of first casting and then comparing.
PR-URL: nodejs#15402
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
The list is defunct at this point. I believe this to be in effect a minor defect from 3eecdf9 PR-URL: nodejs#8422 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Julien Gilli <jgilli@nodejs.org> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Refs: nodejs#14985 PR-URL: nodejs#15461 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Fixes: nodejs#14577 PR-URL: nodejs#14581 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
|
All my comments addressed, so LGTM I haven't had time to review for #14725 (comment), though, and still don't, so someone else will have to sign off on that. |
|
thanks @sam-github |
|
btw, looks like it needs rebasing. |
|
yeah, i'll take care of that once I get a few more approvals. |
|
ping @nodejs/crypto |
bnoordhuis
left a comment
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.
Bikeshed: anyone have opinions on the .openSSLErrorStack property name?
Performance: creating an array and setting a property for every exception might not be cheap.
doc/api/errors.md
Outdated
| provide a text description of the error. | ||
|
|
||
| For crypto only, `Error` objects will include the OpenSSL error stack in a | ||
| separate property if it is available when the error is thrown. |
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.
Can you name the property here?
src/node_crypto.cc
Outdated
| Local<Object> exception = exception_v.As<Object>(); | ||
| Local<Array> error_stack = Array::New(env->isolate()); | ||
|
|
||
| ERR_STATE *es = ERR_get_state(); |
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.
Style: star leans left.
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.
yup. will fix
src/node_crypto.cc
Outdated
| ERR_STATE *es = ERR_get_state(); | ||
| // Build the error_stack array to be added to openSSLErrorStack property. | ||
| for (unsigned int i = 0; es->bottom != es->top | ||
| && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0; i++) { |
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.
This doesn't look correct to me. For starters, es->top and es->bottom should be restored after you're done. Second, this assumes es->bottom <= es->top but that isn't necessarily true because it's a ring buffer.
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.
ok. i think i understand. I'll fix this
src/node_crypto.cc
Outdated
| unsigned long err_buf = es->err_buffer[es->top]; // NOLINT(runtime/int) | ||
| // Only add error string if there is valid err_buffer. | ||
| if (err_buf) { | ||
| char tmpStr[256] = { }; |
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.
Style: snake_case and no init necessary.
src/node_crypto.cc
Outdated
| // 'error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib', | ||
| // 'error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error' | ||
| // ] | ||
| exception->Set(env->openssl_error_stack(), error_stack); |
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.
Can you use the Set() that takes a Local<Context>?
|
|
||
| ERR_set_mark(); | ||
|
|
||
| bp = BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len); |
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 admit I don't understand why that is necessary when you have a ClearErrorOnReturn in the binding function.
PR-URL: nodejs#15463 Fixes: nodejs#15462 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
PR-URL: nodejs#15481 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Bryan English <bryan@bryanenglish.com> Reviewed-By: James M Snell <jasnell@gmail.com>
PR-URL: nodejs#13003 Fixes: nodejs#12951 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
V8 platform tasks may schedule other tasks (both background and foreground), and may perform asynchronous operations like resolving Promises. To address that: - Run the task queue drain call inside a callback scope. This makes sure asynchronous operations inside it, like resolving promises, lead to the microtask queue and any subsequent operations not being silently forgotten. - Move the task queue drain call before `EmitBeforeExit()` and only run `EmitBeforeExit()` if there is no new event loop work. - Account for possible new foreground tasks scheduled by background tasks in `DrainBackgroundTasks()`. PR-URL: nodejs#15428 Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Matthew Loring <mattloring@google.com>
Feature request to add openSSL error stack to the exception object thrown from crypto. New exception property only added to object if the error stack has not cleared out prior to calling ThrowCryptoError. Refs: nodejs#5444
|
having some git issues. will resolve them |
|
I did something terribly wrong git wise here. i opened a new PR #15518 with all the updated changes. Please review that. I am closing this PR. |
|
FYI, for next time, you can force push a branch to replace it's contents without closing a PR. |
|
cool. thanks for the tip. |
Feature request to add openSSL error stack to the exception object
thrown from crypto. New exception property only added to object
if the error stack has not cleared out prior to calling
ThrowCryptoError.
Refs: #5444
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesAffected core subsystem(s)