crypto: do not reach into OpenSSL internals for ThrowCryptoError
There is a perfectly serviceable ERR_get_error function which avoids having to sniff through the OpenSSL ring buffer like that. It does return the errors in the opposite order, but that's easily fixed with std::reverse. Note this behavior is slightly different in that an ERR_get_error loop will ultimately clear the error queue, but this is desirable. Leaving the error queue uncleared means errors in subsequent operations may get mixed up and cause issues. PR-URL: https://github.com/nodejs/node/pull/16701 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
bbcbcb810b
commit
7db53706c9
@ -42,11 +42,13 @@
|
|||||||
// StartComAndWoSignData.inc
|
// StartComAndWoSignData.inc
|
||||||
#include "StartComAndWoSignData.inc"
|
#include "StartComAndWoSignData.inc"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h> // INT_MAX
|
#include <limits.h> // INT_MAX
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define THROW_AND_RETURN_IF_NOT_BUFFER(val, prefix) \
|
#define THROW_AND_RETURN_IF_NOT_BUFFER(val, prefix) \
|
||||||
do { \
|
do { \
|
||||||
@ -421,44 +423,33 @@ void ThrowCryptoError(Environment* env,
|
|||||||
Local<Value> exception_v = Exception::Error(message);
|
Local<Value> exception_v = Exception::Error(message);
|
||||||
CHECK(!exception_v.IsEmpty());
|
CHECK(!exception_v.IsEmpty());
|
||||||
Local<Object> exception = exception_v.As<Object>();
|
Local<Object> exception = exception_v.As<Object>();
|
||||||
ERR_STATE* es = ERR_get_state();
|
|
||||||
|
|
||||||
if (es->bottom != es->top) {
|
std::vector<Local<String>> errors;
|
||||||
Local<Array> error_stack = Array::New(env->isolate());
|
for (;;) {
|
||||||
int top = es->top;
|
unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
|
||||||
|
if (err == 0) {
|
||||||
// Build the error_stack array to be added to opensslErrorStack property.
|
break;
|
||||||
for (unsigned int i = 0; es->bottom != es->top;) {
|
}
|
||||||
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 tmp_str[256];
|
char tmp_str[256];
|
||||||
ERR_error_string_n(err_buf, tmp_str, sizeof(tmp_str));
|
ERR_error_string_n(err, tmp_str, sizeof(tmp_str));
|
||||||
error_stack->Set(env->context(), i,
|
errors.push_back(String::NewFromUtf8(env->isolate(), tmp_str,
|
||||||
String::NewFromUtf8(env->isolate(), tmp_str,
|
|
||||||
v8::NewStringType::kNormal)
|
v8::NewStringType::kNormal)
|
||||||
.ToLocalChecked()).FromJust();
|
.ToLocalChecked());
|
||||||
// Only increment if we added to error_stack.
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since the ERR_STATE is a ring buffer, we need to use modular
|
// ERR_get_error returns errors in order of most specific to least
|
||||||
// arithmetic to loop back around in the case where bottom is after top.
|
// specific. We wish to have the reverse ordering:
|
||||||
// Using ERR_NUM_ERRORS macro defined in openssl.
|
|
||||||
es->top = (((es->top - 1) % ERR_NUM_ERRORS) + ERR_NUM_ERRORS) %
|
|
||||||
ERR_NUM_ERRORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore top.
|
|
||||||
es->top = top;
|
|
||||||
|
|
||||||
// Add the opensslErrorStack property to the exception object.
|
|
||||||
// The new property will look like the following:
|
|
||||||
// opensslErrorStack: [
|
// opensslErrorStack: [
|
||||||
// 'error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib',
|
// 'error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib',
|
||||||
// 'error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 err'
|
// 'error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 err'
|
||||||
// ]
|
// ]
|
||||||
exception->Set(env->context(), env->openssl_error_stack(), error_stack)
|
if (!errors.empty()) {
|
||||||
|
std::reverse(errors.begin(), errors.end());
|
||||||
|
Local<Array> errors_array = Array::New(env->isolate(), errors.size());
|
||||||
|
for (size_t i = 0; i < errors.size(); i++) {
|
||||||
|
errors_array->Set(env->context(), i, errors[i]).FromJust();
|
||||||
|
}
|
||||||
|
exception->Set(env->context(), env->openssl_error_stack(), errors_array)
|
||||||
.FromJust();
|
.FromJust();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user