err_save.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #define OSSL_FORCE_ERR_STATE
  10. #include <openssl/err.h>
  11. #include "err_local.h"
  12. /*
  13. * Save and restore error state.
  14. * We are using CRYPTO_zalloc(.., NULL, 0) instead of OPENSSL_malloc() in
  15. * these functions to prevent mem alloc error loop.
  16. */
  17. ERR_STATE *OSSL_ERR_STATE_new(void)
  18. {
  19. return CRYPTO_zalloc(sizeof(ERR_STATE), NULL, 0);
  20. }
  21. void OSSL_ERR_STATE_save(ERR_STATE *es)
  22. {
  23. size_t i;
  24. ERR_STATE *thread_es;
  25. if (es == NULL)
  26. return;
  27. for (i = 0; i < ERR_NUM_ERRORS; i++)
  28. err_clear(es, i, 1);
  29. thread_es = ossl_err_get_state_int();
  30. if (thread_es == NULL)
  31. return;
  32. memcpy(es, thread_es, sizeof(*es));
  33. /* Taking over the pointers, just clear the thread state. */
  34. memset(thread_es, 0, sizeof(*thread_es));
  35. }
  36. void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es)
  37. {
  38. size_t i, j, count;
  39. int top;
  40. ERR_STATE *thread_es;
  41. if (es == NULL)
  42. return;
  43. thread_es = ossl_err_get_state_int();
  44. if (thread_es == NULL) {
  45. for (i = 0; i < ERR_NUM_ERRORS; ++i)
  46. err_clear(es, i, 1);
  47. es->top = es->bottom = 0;
  48. return;
  49. }
  50. /* Determine number of errors we are going to move. */
  51. for (count = 0, top = thread_es->top;
  52. thread_es->bottom != top
  53. && thread_es->err_marks[top] == 0;
  54. ++count)
  55. top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
  56. /* Move the errors, preserving order. */
  57. for (i = 0, j = top; i < count; ++i) {
  58. j = (j + 1) % ERR_NUM_ERRORS;
  59. err_clear(es, i, 1);
  60. /* Move the error entry to the given ERR_STATE. */
  61. es->err_flags[i] = thread_es->err_flags[j];
  62. es->err_marks[i] = 0;
  63. es->err_buffer[i] = thread_es->err_buffer[j];
  64. es->err_data[i] = thread_es->err_data[j];
  65. es->err_data_size[i] = thread_es->err_data_size[j];
  66. es->err_data_flags[i] = thread_es->err_data_flags[j];
  67. es->err_file[i] = thread_es->err_file[j];
  68. es->err_line[i] = thread_es->err_line[j];
  69. es->err_func[i] = thread_es->err_func[j];
  70. thread_es->err_flags[j] = 0;
  71. thread_es->err_buffer[j] = 0;
  72. thread_es->err_data[j] = NULL;
  73. thread_es->err_data_size[j] = 0;
  74. thread_es->err_data_flags[j] = 0;
  75. thread_es->err_file[j] = NULL;
  76. thread_es->err_line[j] = 0;
  77. thread_es->err_func[j] = NULL;
  78. }
  79. if (i > 0) {
  80. thread_es->top = top;
  81. /* If we moved anything, es's stack always starts at [0]. */
  82. es->top = i - 1;
  83. es->bottom = ERR_NUM_ERRORS - 1;
  84. } else {
  85. /* Didn't move anything - empty stack */
  86. es->top = es->bottom = 0;
  87. }
  88. /* Erase extra space as a precaution. */
  89. for (; i < ERR_NUM_ERRORS; ++i)
  90. err_clear(es, i, 1);
  91. }
  92. void OSSL_ERR_STATE_restore(const ERR_STATE *es)
  93. {
  94. size_t i;
  95. ERR_STATE *thread_es;
  96. if (es == NULL || es->bottom == es->top)
  97. return;
  98. thread_es = ossl_err_get_state_int();
  99. if (thread_es == NULL)
  100. return;
  101. for (i = (size_t)es->bottom; i != (size_t)es->top;) {
  102. size_t top;
  103. i = (i + 1) % ERR_NUM_ERRORS;
  104. if ((es->err_flags[i] & ERR_FLAG_CLEAR) != 0)
  105. continue;
  106. err_get_slot(thread_es);
  107. top = thread_es->top;
  108. err_clear(thread_es, top, 0);
  109. thread_es->err_flags[top] = es->err_flags[i];
  110. thread_es->err_buffer[top] = es->err_buffer[i];
  111. err_set_debug(thread_es, top, es->err_file[i], es->err_line[i],
  112. es->err_func[i]);
  113. if (es->err_data[i] != NULL && es->err_data_size[i] != 0) {
  114. void *data;
  115. size_t data_sz = es->err_data_size[i];
  116. data = CRYPTO_malloc(data_sz, NULL, 0);
  117. if (data != NULL) {
  118. memcpy(data, es->err_data[i], data_sz);
  119. err_set_data(thread_es, top, data, data_sz,
  120. es->err_data_flags[i] | ERR_TXT_MALLOCED);
  121. }
  122. } else {
  123. err_clear_data(thread_es, top, 0);
  124. }
  125. }
  126. }