@@ -212,6 +212,113 @@ static int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
212
212
}
213
213
214
214
215
+ // namespace node::crypto::error
216
+ namespace error {
217
+ void Decorate (Environment* env, Local<Object> obj,
218
+ unsigned long err) { // NOLINT(runtime/int)
219
+ if (err == 0 ) return ; // No decoration possible.
220
+
221
+ const char * ls = ERR_lib_error_string (err);
222
+ const char * fs = ERR_func_error_string (err);
223
+ const char * rs = ERR_reason_error_string (err);
224
+
225
+ Isolate* isolate = env->isolate ();
226
+ Local<Context> context = isolate->GetCurrentContext ();
227
+
228
+ if (ls != nullptr ) {
229
+ if (obj->Set (context, env->library_string (),
230
+ OneByteString (isolate, ls)).IsNothing ()) {
231
+ return ;
232
+ }
233
+ }
234
+ if (fs != nullptr ) {
235
+ if (obj->Set (context, env->function_string (),
236
+ OneByteString (isolate, fs)).IsNothing ()) {
237
+ return ;
238
+ }
239
+ }
240
+ if (rs != nullptr ) {
241
+ if (obj->Set (context, env->reason_string (),
242
+ OneByteString (isolate, rs)).IsNothing ()) {
243
+ return ;
244
+ }
245
+
246
+ // SSL has no API to recover the error name from the number, so we
247
+ // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
248
+ // which ends up being close to the original error macro name.
249
+ std::string reason (rs);
250
+
251
+ for (auto & c : reason) {
252
+ if (c == ' ' )
253
+ c = ' _' ;
254
+ else
255
+ c = ToUpper (c);
256
+ }
257
+
258
+ #define OSSL_ERROR_CODES_MAP (V ) \
259
+ V (SYS) \
260
+ V (BN) \
261
+ V (RSA) \
262
+ V (DH) \
263
+ V (EVP) \
264
+ V (BUF) \
265
+ V (OBJ) \
266
+ V (PEM) \
267
+ V (DSA) \
268
+ V (X509) \
269
+ V (ASN1) \
270
+ V (CONF) \
271
+ V (CRYPTO) \
272
+ V (EC) \
273
+ V (SSL) \
274
+ V (BIO) \
275
+ V (PKCS7) \
276
+ V (X509V3) \
277
+ V (PKCS12) \
278
+ V (RAND) \
279
+ V (DSO) \
280
+ V (ENGINE) \
281
+ V (OCSP) \
282
+ V (UI) \
283
+ V (COMP) \
284
+ V (ECDSA) \
285
+ V (ECDH) \
286
+ V (OSSL_STORE) \
287
+ V (FIPS) \
288
+ V (CMS) \
289
+ V (TS) \
290
+ V (HMAC) \
291
+ V (CT) \
292
+ V (ASYNC) \
293
+ V (KDF) \
294
+ V (SM2) \
295
+ V (USER) \
296
+
297
+ #define V (name ) case ERR_LIB_##name: lib = #name " _" ; break ;
298
+ const char * lib = " " ;
299
+ const char * prefix = " OSSL_" ;
300
+ switch (ERR_GET_LIB (err)) { OSSL_ERROR_CODES_MAP (V) }
301
+ #undef V
302
+ #undef OSSL_ERROR_CODES_MAP
303
+ // Don't generate codes like "ERR_OSSL_SSL_".
304
+ if (lib && strcmp (lib, " SSL_" ) == 0 )
305
+ prefix = " " ;
306
+
307
+ // All OpenSSL reason strings fit in a single 80-column macro definition,
308
+ // all prefix lengths are <= 10, and ERR_OSSL_ is 9, so 128 is more than
309
+ // sufficient.
310
+ char code[128 ];
311
+ snprintf (code, sizeof (code), " ERR_%s%s%s" , prefix, lib, reason.c_str ());
312
+
313
+ if (obj->Set (env->isolate ()->GetCurrentContext (),
314
+ env->code_string (),
315
+ OneByteString (env->isolate (), code)).IsNothing ())
316
+ return ;
317
+ }
318
+ }
319
+ } // namespace error
320
+
321
+
215
322
struct CryptoErrorVector : public std ::vector<std::string> {
216
323
inline void Capture () {
217
324
clear ();
@@ -258,6 +365,8 @@ struct CryptoErrorVector : public std::vector<std::string> {
258
365
259
366
void ThrowCryptoError (Environment* env,
260
367
unsigned long err, // NOLINT(runtime/int)
368
+ // Default, only used if there is no SSL `err` which can
369
+ // be used to create a long-style message string.
261
370
const char * message = nullptr ) {
262
371
char message_buffer[128 ] = {0 };
263
372
if (err != 0 || message == nullptr ) {
@@ -270,7 +379,11 @@ void ThrowCryptoError(Environment* env,
270
379
.ToLocalChecked ();
271
380
CryptoErrorVector errors;
272
381
errors.Capture ();
273
- auto exception = errors.ToException (env, exception_string);
382
+ Local<Value> exception = errors.ToException (env, exception_string);
383
+ Local<Object> obj;
384
+ if (!exception ->ToObject (env->context ()).ToLocal (&obj))
385
+ return ;
386
+ error::Decorate (env, obj, err);
274
387
env->isolate ()->ThrowException (exception );
275
388
}
276
389
0 commit comments