1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh (at) cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay (at) cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] 56 */ 57 /* ==================================================================== 58 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 59 * 60 * Redistribution and use in source and binary forms, with or without 61 * modification, are permitted provided that the following conditions 62 * are met: 63 * 64 * 1. Redistributions of source code must retain the above copyright 65 * notice, this list of conditions and the following disclaimer. 66 * 67 * 2. Redistributions in binary form must reproduce the above copyright 68 * notice, this list of conditions and the following disclaimer in 69 * the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3. All advertising materials mentioning features or use of this 73 * software must display the following acknowledgment: 74 * "This product includes software developed by the OpenSSL Project 75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 76 * 77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 78 * endorse or promote products derived from this software without 79 * prior written permission. For written permission, please contact 80 * openssl-core (at) openssl.org. 81 * 82 * 5. Products derived from this software may not be called "OpenSSL" 83 * nor may "OpenSSL" appear in their names without prior written 84 * permission of the OpenSSL Project. 85 * 86 * 6. Redistributions of any form whatsoever must retain the following 87 * acknowledgment: 88 * "This product includes software developed by the OpenSSL Project 89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 90 * 91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 102 * OF THE POSSIBILITY OF SUCH DAMAGE. 103 * ==================================================================== 104 * 105 * This product includes cryptographic software written by Eric Young 106 * (eay (at) cryptsoft.com). This product includes software written by Tim 107 * Hudson (tjh (at) cryptsoft.com). */ 108 109 #include <openssl/err.h> 110 111 #include <assert.h> 112 #include <errno.h> 113 #include <inttypes.h> 114 #include <string.h> 115 116 #if defined(OPENSSL_WINDOWS) 117 OPENSSL_MSVC_PRAGMA(warning(push, 3)) 118 #include <windows.h> 119 OPENSSL_MSVC_PRAGMA(warning(pop)) 120 #endif 121 122 #include <openssl/mem.h> 123 #include <openssl/thread.h> 124 125 #include "../internal.h" 126 #include "./internal.h" 127 128 129 struct err_error_st { 130 // file contains the filename where the error occurred. 131 const char *file; 132 // data contains a NUL-terminated string with optional data. It must be freed 133 // with |OPENSSL_free|. 134 char *data; 135 // packed contains the error library and reason, as packed by ERR_PACK. 136 uint32_t packed; 137 // line contains the line number where the error occurred. 138 uint16_t line; 139 // mark indicates a reversion point in the queue. See |ERR_pop_to_mark|. 140 unsigned mark : 1; 141 }; 142 143 // ERR_STATE contains the per-thread, error queue. 144 typedef struct err_state_st { 145 // errors contains the ERR_NUM_ERRORS most recent errors, organised as a ring 146 // buffer. 147 struct err_error_st errors[ERR_NUM_ERRORS]; 148 // top contains the index one past the most recent error. If |top| equals 149 // |bottom| then the queue is empty. 150 unsigned top; 151 // bottom contains the index of the last error in the queue. 152 unsigned bottom; 153 154 // to_free, if not NULL, contains a pointer owned by this structure that was 155 // previously a |data| pointer of one of the elements of |errors|. 156 void *to_free; 157 } ERR_STATE; 158 159 extern const uint32_t kOpenSSLReasonValues[]; 160 extern const size_t kOpenSSLReasonValuesLen; 161 extern const char kOpenSSLReasonStringData[]; 162 163 // err_clear clears the given queued error. 164 static void err_clear(struct err_error_st *error) { 165 OPENSSL_free(error->data); 166 OPENSSL_memset(error, 0, sizeof(struct err_error_st)); 167 } 168 169 static void err_copy(struct err_error_st *dst, const struct err_error_st *src) { 170 err_clear(dst); 171 dst->file = src->file; 172 if (src->data != NULL) { 173 dst->data = OPENSSL_strdup(src->data); 174 } 175 dst->packed = src->packed; 176 dst->line = src->line; 177 } 178 179 // global_next_library contains the next custom library value to return. 180 static int global_next_library = ERR_NUM_LIBS; 181 182 // global_next_library_mutex protects |global_next_library| from concurrent 183 // updates. 184 static struct CRYPTO_STATIC_MUTEX global_next_library_mutex = 185 CRYPTO_STATIC_MUTEX_INIT; 186 187 static void err_state_free(void *statep) { 188 ERR_STATE *state = statep; 189 190 if (state == NULL) { 191 return; 192 } 193 194 for (unsigned i = 0; i < ERR_NUM_ERRORS; i++) { 195 err_clear(&state->errors[i]); 196 } 197 OPENSSL_free(state->to_free); 198 OPENSSL_free(state); 199 } 200 201 // err_get_state gets the ERR_STATE object for the current thread. 202 static ERR_STATE *err_get_state(void) { 203 ERR_STATE *state = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_ERR); 204 if (state == NULL) { 205 state = OPENSSL_malloc(sizeof(ERR_STATE)); 206 if (state == NULL) { 207 return NULL; 208 } 209 OPENSSL_memset(state, 0, sizeof(ERR_STATE)); 210 if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_ERR, state, 211 err_state_free)) { 212 return NULL; 213 } 214 } 215 216 return state; 217 } 218 219 static uint32_t get_error_values(int inc, int top, const char **file, int *line, 220 const char **data, int *flags) { 221 unsigned i = 0; 222 ERR_STATE *state; 223 struct err_error_st *error; 224 uint32_t ret; 225 226 state = err_get_state(); 227 if (state == NULL || state->bottom == state->top) { 228 return 0; 229 } 230 231 if (top) { 232 assert(!inc); 233 // last error 234 i = state->top; 235 } else { 236 i = (state->bottom + 1) % ERR_NUM_ERRORS; 237 } 238 239 error = &state->errors[i]; 240 ret = error->packed; 241 242 if (file != NULL && line != NULL) { 243 if (error->file == NULL) { 244 *file = "NA"; 245 *line = 0; 246 } else { 247 *file = error->file; 248 *line = error->line; 249 } 250 } 251 252 if (data != NULL) { 253 if (error->data == NULL) { 254 *data = ""; 255 if (flags != NULL) { 256 *flags = 0; 257 } 258 } else { 259 *data = error->data; 260 if (flags != NULL) { 261 *flags = ERR_FLAG_STRING; 262 } 263 // If this error is being removed, take ownership of data from 264 // the error. The semantics are such that the caller doesn't 265 // take ownership either. Instead the error system takes 266 // ownership and retains it until the next call that affects the 267 // error queue. 268 if (inc) { 269 if (error->data != NULL) { 270 OPENSSL_free(state->to_free); 271 state->to_free = error->data; 272 } 273 error->data = NULL; 274 } 275 } 276 } 277 278 if (inc) { 279 assert(!top); 280 err_clear(error); 281 state->bottom = i; 282 } 283 284 return ret; 285 } 286 287 uint32_t ERR_get_error(void) { 288 return get_error_values(1 /* inc */, 0 /* bottom */, NULL, NULL, NULL, NULL); 289 } 290 291 uint32_t ERR_get_error_line(const char **file, int *line) { 292 return get_error_values(1 /* inc */, 0 /* bottom */, file, line, NULL, NULL); 293 } 294 295 uint32_t ERR_get_error_line_data(const char **file, int *line, 296 const char **data, int *flags) { 297 return get_error_values(1 /* inc */, 0 /* bottom */, file, line, data, flags); 298 } 299 300 uint32_t ERR_peek_error(void) { 301 return get_error_values(0 /* peek */, 0 /* bottom */, NULL, NULL, NULL, NULL); 302 } 303 304 uint32_t ERR_peek_error_line(const char **file, int *line) { 305 return get_error_values(0 /* peek */, 0 /* bottom */, file, line, NULL, NULL); 306 } 307 308 uint32_t ERR_peek_error_line_data(const char **file, int *line, 309 const char **data, int *flags) { 310 return get_error_values(0 /* peek */, 0 /* bottom */, file, line, data, 311 flags); 312 } 313 314 uint32_t ERR_peek_last_error(void) { 315 return get_error_values(0 /* peek */, 1 /* top */, NULL, NULL, NULL, NULL); 316 } 317 318 uint32_t ERR_peek_last_error_line(const char **file, int *line) { 319 return get_error_values(0 /* peek */, 1 /* top */, file, line, NULL, NULL); 320 } 321 322 uint32_t ERR_peek_last_error_line_data(const char **file, int *line, 323 const char **data, int *flags) { 324 return get_error_values(0 /* peek */, 1 /* top */, file, line, data, flags); 325 } 326 327 void ERR_clear_error(void) { 328 ERR_STATE *const state = err_get_state(); 329 unsigned i; 330 331 if (state == NULL) { 332 return; 333 } 334 335 for (i = 0; i < ERR_NUM_ERRORS; i++) { 336 err_clear(&state->errors[i]); 337 } 338 OPENSSL_free(state->to_free); 339 state->to_free = NULL; 340 341 state->top = state->bottom = 0; 342 } 343 344 void ERR_remove_thread_state(const CRYPTO_THREADID *tid) { 345 if (tid != NULL) { 346 assert(0); 347 return; 348 } 349 350 ERR_clear_error(); 351 } 352 353 int ERR_get_next_error_library(void) { 354 int ret; 355 356 CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex); 357 ret = global_next_library++; 358 CRYPTO_STATIC_MUTEX_unlock_write(&global_next_library_mutex); 359 360 return ret; 361 } 362 363 void ERR_remove_state(unsigned long pid) { 364 ERR_clear_error(); 365 } 366 367 void ERR_clear_system_error(void) { 368 errno = 0; 369 } 370 371 char *ERR_error_string(uint32_t packed_error, char *ret) { 372 static char buf[ERR_ERROR_STRING_BUF_LEN]; 373 374 if (ret == NULL) { 375 // TODO(fork): remove this. 376 ret = buf; 377 } 378 379 #if !defined(NDEBUG) 380 // This is aimed to help catch callers who don't provide 381 // |ERR_ERROR_STRING_BUF_LEN| bytes of space. 382 OPENSSL_memset(ret, 0, ERR_ERROR_STRING_BUF_LEN); 383 #endif 384 385 ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN); 386 387 return ret; 388 } 389 390 void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) { 391 char lib_buf[64], reason_buf[64]; 392 const char *lib_str, *reason_str; 393 unsigned lib, reason; 394 395 if (len == 0) { 396 return; 397 } 398 399 lib = ERR_GET_LIB(packed_error); 400 reason = ERR_GET_REASON(packed_error); 401 402 lib_str = ERR_lib_error_string(packed_error); 403 reason_str = ERR_reason_error_string(packed_error); 404 405 if (lib_str == NULL) { 406 BIO_snprintf(lib_buf, sizeof(lib_buf), "lib(%u)", lib); 407 lib_str = lib_buf; 408 } 409 410 if (reason_str == NULL) { 411 BIO_snprintf(reason_buf, sizeof(reason_buf), "reason(%u)", reason); 412 reason_str = reason_buf; 413 } 414 415 BIO_snprintf(buf, len, "error:%08" PRIx32 ":%s:OPENSSL_internal:%s", 416 packed_error, lib_str, reason_str); 417 418 if (strlen(buf) == len - 1) { 419 // output may be truncated; make sure we always have 5 colon-separated 420 // fields, i.e. 4 colons. 421 static const unsigned num_colons = 4; 422 unsigned i; 423 char *s = buf; 424 425 if (len <= num_colons) { 426 // In this situation it's not possible to ensure that the correct number 427 // of colons are included in the output. 428 return; 429 } 430 431 for (i = 0; i < num_colons; i++) { 432 char *colon = strchr(s, ':'); 433 char *last_pos = &buf[len - 1] - num_colons + i; 434 435 if (colon == NULL || colon > last_pos) { 436 // set colon |i| at last possible position (buf[len-1] is the 437 // terminating 0). If we're setting this colon, then all whole of the 438 // rest of the string must be colons in order to have the correct 439 // number. 440 OPENSSL_memset(last_pos, ':', num_colons - i); 441 break; 442 } 443 444 s = colon + 1; 445 } 446 } 447 } 448 449 // err_string_cmp is a compare function for searching error values with 450 // |bsearch| in |err_string_lookup|. 451 static int err_string_cmp(const void *a, const void *b) { 452 const uint32_t a_key = *((const uint32_t*) a) >> 15; 453 const uint32_t b_key = *((const uint32_t*) b) >> 15; 454 455 if (a_key < b_key) { 456 return -1; 457 } else if (a_key > b_key) { 458 return 1; 459 } else { 460 return 0; 461 } 462 } 463 464 // err_string_lookup looks up the string associated with |lib| and |key| in 465 // |values| and |string_data|. It returns the string or NULL if not found. 466 static const char *err_string_lookup(uint32_t lib, uint32_t key, 467 const uint32_t *values, 468 size_t num_values, 469 const char *string_data) { 470 // |values| points to data in err_data.h, which is generated by 471 // err_data_generate.go. It's an array of uint32_t values. Each value has the 472 // following structure: 473 // | lib | key | offset | 474 // |6 bits| 11 bits | 15 bits | 475 // 476 // The |lib| value is a library identifier: one of the |ERR_LIB_*| values. 477 // The |key| is a reason code, depending on the context. 478 // The |offset| is the number of bytes from the start of |string_data| where 479 // the (NUL terminated) string for this value can be found. 480 // 481 // Values are sorted based on treating the |lib| and |key| part as an 482 // unsigned integer. 483 if (lib >= (1 << 6) || key >= (1 << 11)) { 484 return NULL; 485 } 486 uint32_t search_key = lib << 26 | key << 15; 487 const uint32_t *result = bsearch(&search_key, values, num_values, 488 sizeof(uint32_t), err_string_cmp); 489 if (result == NULL) { 490 return NULL; 491 } 492 493 return &string_data[(*result) & 0x7fff]; 494 } 495 496 static const char *const kLibraryNames[ERR_NUM_LIBS] = { 497 "invalid library (0)", 498 "unknown library", // ERR_LIB_NONE 499 "system library", // ERR_LIB_SYS 500 "bignum routines", // ERR_LIB_BN 501 "RSA routines", // ERR_LIB_RSA 502 "Diffie-Hellman routines", // ERR_LIB_DH 503 "public key routines", // ERR_LIB_EVP 504 "memory buffer routines", // ERR_LIB_BUF 505 "object identifier routines", // ERR_LIB_OBJ 506 "PEM routines", // ERR_LIB_PEM 507 "DSA routines", // ERR_LIB_DSA 508 "X.509 certificate routines", // ERR_LIB_X509 509 "ASN.1 encoding routines", // ERR_LIB_ASN1 510 "configuration file routines", // ERR_LIB_CONF 511 "common libcrypto routines", // ERR_LIB_CRYPTO 512 "elliptic curve routines", // ERR_LIB_EC 513 "SSL routines", // ERR_LIB_SSL 514 "BIO routines", // ERR_LIB_BIO 515 "PKCS7 routines", // ERR_LIB_PKCS7 516 "PKCS8 routines", // ERR_LIB_PKCS8 517 "X509 V3 routines", // ERR_LIB_X509V3 518 "random number generator", // ERR_LIB_RAND 519 "ENGINE routines", // ERR_LIB_ENGINE 520 "OCSP routines", // ERR_LIB_OCSP 521 "UI routines", // ERR_LIB_UI 522 "COMP routines", // ERR_LIB_COMP 523 "ECDSA routines", // ERR_LIB_ECDSA 524 "ECDH routines", // ERR_LIB_ECDH 525 "HMAC routines", // ERR_LIB_HMAC 526 "Digest functions", // ERR_LIB_DIGEST 527 "Cipher functions", // ERR_LIB_CIPHER 528 "HKDF functions", // ERR_LIB_HKDF 529 "User defined functions", // ERR_LIB_USER 530 }; 531 532 const char *ERR_lib_error_string(uint32_t packed_error) { 533 const uint32_t lib = ERR_GET_LIB(packed_error); 534 535 if (lib >= ERR_NUM_LIBS) { 536 return NULL; 537 } 538 return kLibraryNames[lib]; 539 } 540 541 const char *ERR_func_error_string(uint32_t packed_error) { 542 return "OPENSSL_internal"; 543 } 544 545 const char *ERR_reason_error_string(uint32_t packed_error) { 546 const uint32_t lib = ERR_GET_LIB(packed_error); 547 const uint32_t reason = ERR_GET_REASON(packed_error); 548 549 if (lib == ERR_LIB_SYS) { 550 if (reason < 127) { 551 return strerror(reason); 552 } 553 return NULL; 554 } 555 556 if (reason < ERR_NUM_LIBS) { 557 return kLibraryNames[reason]; 558 } 559 560 if (reason < 100) { 561 switch (reason) { 562 case ERR_R_MALLOC_FAILURE: 563 return "malloc failure"; 564 case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED: 565 return "function should not have been called"; 566 case ERR_R_PASSED_NULL_PARAMETER: 567 return "passed a null parameter"; 568 case ERR_R_INTERNAL_ERROR: 569 return "internal error"; 570 case ERR_R_OVERFLOW: 571 return "overflow"; 572 default: 573 return NULL; 574 } 575 } 576 577 return err_string_lookup(lib, reason, kOpenSSLReasonValues, 578 kOpenSSLReasonValuesLen, kOpenSSLReasonStringData); 579 } 580 581 void ERR_print_errors_cb(ERR_print_errors_callback_t callback, void *ctx) { 582 char buf[ERR_ERROR_STRING_BUF_LEN]; 583 char buf2[1024]; 584 const char *file, *data; 585 int line, flags; 586 uint32_t packed_error; 587 588 // thread_hash is the least-significant bits of the |ERR_STATE| pointer value 589 // for this thread. 590 const unsigned long thread_hash = (uintptr_t) err_get_state(); 591 592 for (;;) { 593 packed_error = ERR_get_error_line_data(&file, &line, &data, &flags); 594 if (packed_error == 0) { 595 break; 596 } 597 598 ERR_error_string_n(packed_error, buf, sizeof(buf)); 599 BIO_snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", thread_hash, buf, 600 file, line, (flags & ERR_FLAG_STRING) ? data : ""); 601 if (callback(buf2, strlen(buf2), ctx) <= 0) { 602 break; 603 } 604 } 605 } 606 607 static int print_errors_to_file(const char* msg, size_t msg_len, void* ctx) { 608 assert(msg[msg_len] == '\0'); 609 FILE* fp = ctx; 610 int res = fputs(msg, fp); 611 return res < 0 ? 0 : 1; 612 } 613 614 void ERR_print_errors_fp(FILE *file) { 615 ERR_print_errors_cb(print_errors_to_file, file); 616 } 617 618 // err_set_error_data sets the data on the most recent error. 619 static void err_set_error_data(char *data) { 620 ERR_STATE *const state = err_get_state(); 621 struct err_error_st *error; 622 623 if (state == NULL || state->top == state->bottom) { 624 OPENSSL_free(data); 625 return; 626 } 627 628 error = &state->errors[state->top]; 629 630 OPENSSL_free(error->data); 631 error->data = data; 632 } 633 634 void ERR_put_error(int library, int unused, int reason, const char *file, 635 unsigned line) { 636 ERR_STATE *const state = err_get_state(); 637 struct err_error_st *error; 638 639 if (state == NULL) { 640 return; 641 } 642 643 if (library == ERR_LIB_SYS && reason == 0) { 644 #if defined(OPENSSL_WINDOWS) 645 reason = GetLastError(); 646 #else 647 reason = errno; 648 #endif 649 } 650 651 state->top = (state->top + 1) % ERR_NUM_ERRORS; 652 if (state->top == state->bottom) { 653 state->bottom = (state->bottom + 1) % ERR_NUM_ERRORS; 654 } 655 656 error = &state->errors[state->top]; 657 err_clear(error); 658 error->file = file; 659 error->line = line; 660 error->packed = ERR_PACK(library, reason); 661 } 662 663 // ERR_add_error_data_vdata takes a variable number of const char* pointers, 664 // concatenates them and sets the result as the data on the most recent 665 // error. 666 static void err_add_error_vdata(unsigned num, va_list args) { 667 size_t alloced, new_len, len = 0, substr_len; 668 char *buf; 669 const char *substr; 670 unsigned i; 671 672 alloced = 80; 673 buf = OPENSSL_malloc(alloced + 1); 674 if (buf == NULL) { 675 return; 676 } 677 678 for (i = 0; i < num; i++) { 679 substr = va_arg(args, const char *); 680 if (substr == NULL) { 681 continue; 682 } 683 684 substr_len = strlen(substr); 685 new_len = len + substr_len; 686 if (new_len > alloced) { 687 char *new_buf; 688 689 if (alloced + 20 + 1 < alloced) { 690 // overflow. 691 OPENSSL_free(buf); 692 return; 693 } 694 695 alloced = new_len + 20; 696 new_buf = OPENSSL_realloc(buf, alloced + 1); 697 if (new_buf == NULL) { 698 OPENSSL_free(buf); 699 return; 700 } 701 buf = new_buf; 702 } 703 704 OPENSSL_memcpy(buf + len, substr, substr_len); 705 len = new_len; 706 } 707 708 buf[len] = 0; 709 err_set_error_data(buf); 710 } 711 712 void ERR_add_error_data(unsigned count, ...) { 713 va_list args; 714 va_start(args, count); 715 err_add_error_vdata(count, args); 716 va_end(args); 717 } 718 719 void ERR_add_error_dataf(const char *format, ...) { 720 va_list ap; 721 char *buf; 722 static const unsigned buf_len = 256; 723 724 // A fixed-size buffer is used because va_copy (which would be needed in 725 // order to call vsnprintf twice and measure the buffer) wasn't defined until 726 // C99. 727 buf = OPENSSL_malloc(buf_len + 1); 728 if (buf == NULL) { 729 return; 730 } 731 732 va_start(ap, format); 733 BIO_vsnprintf(buf, buf_len, format, ap); 734 buf[buf_len] = 0; 735 va_end(ap); 736 737 err_set_error_data(buf); 738 } 739 740 int ERR_set_mark(void) { 741 ERR_STATE *const state = err_get_state(); 742 743 if (state == NULL || state->bottom == state->top) { 744 return 0; 745 } 746 state->errors[state->top].mark = 1; 747 return 1; 748 } 749 750 int ERR_pop_to_mark(void) { 751 ERR_STATE *const state = err_get_state(); 752 753 if (state == NULL) { 754 return 0; 755 } 756 757 while (state->bottom != state->top) { 758 struct err_error_st *error = &state->errors[state->top]; 759 760 if (error->mark) { 761 error->mark = 0; 762 return 1; 763 } 764 765 err_clear(error); 766 if (state->top == 0) { 767 state->top = ERR_NUM_ERRORS - 1; 768 } else { 769 state->top--; 770 } 771 } 772 773 return 0; 774 } 775 776 void ERR_load_crypto_strings(void) {} 777 778 void ERR_free_strings(void) {} 779 780 void ERR_load_BIO_strings(void) {} 781 782 void ERR_load_ERR_strings(void) {} 783 784 void ERR_load_RAND_strings(void) {} 785 786 struct err_save_state_st { 787 struct err_error_st *errors; 788 size_t num_errors; 789 }; 790 791 void ERR_SAVE_STATE_free(ERR_SAVE_STATE *state) { 792 if (state == NULL) { 793 return; 794 } 795 for (size_t i = 0; i < state->num_errors; i++) { 796 err_clear(&state->errors[i]); 797 } 798 OPENSSL_free(state->errors); 799 OPENSSL_free(state); 800 } 801 802 ERR_SAVE_STATE *ERR_save_state(void) { 803 ERR_STATE *const state = err_get_state(); 804 if (state == NULL || state->top == state->bottom) { 805 return NULL; 806 } 807 808 ERR_SAVE_STATE *ret = OPENSSL_malloc(sizeof(ERR_SAVE_STATE)); 809 if (ret == NULL) { 810 return NULL; 811 } 812 813 // Errors are stored in the range (bottom, top]. 814 size_t num_errors = state->top >= state->bottom 815 ? state->top - state->bottom 816 : ERR_NUM_ERRORS + state->top - state->bottom; 817 assert(num_errors < ERR_NUM_ERRORS); 818 ret->errors = OPENSSL_malloc(num_errors * sizeof(struct err_error_st)); 819 if (ret->errors == NULL) { 820 OPENSSL_free(ret); 821 return NULL; 822 } 823 OPENSSL_memset(ret->errors, 0, num_errors * sizeof(struct err_error_st)); 824 ret->num_errors = num_errors; 825 826 for (size_t i = 0; i < num_errors; i++) { 827 size_t j = (state->bottom + i + 1) % ERR_NUM_ERRORS; 828 err_copy(&ret->errors[i], &state->errors[j]); 829 } 830 return ret; 831 } 832 833 void ERR_restore_state(const ERR_SAVE_STATE *state) { 834 if (state == NULL || state->num_errors == 0) { 835 ERR_clear_error(); 836 return; 837 } 838 839 ERR_STATE *const dst = err_get_state(); 840 if (dst == NULL) { 841 return; 842 } 843 844 for (size_t i = 0; i < state->num_errors; i++) { 845 err_copy(&dst->errors[i], &state->errors[i]); 846 } 847 dst->top = state->num_errors - 1; 848 dst->bottom = ERR_NUM_ERRORS - 1; 849 } 850