]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - crypto/err/err_save.c
QUIC TLS: Rethink error handling
[thirdparty/openssl.git] / crypto / err / err_save.c
index a471b22682ad92c2995240d8684ac2363b80c463..3ca059adc336b0dbf9cf61f80ab95bd086b8b629 100644 (file)
@@ -43,6 +43,71 @@ void OSSL_ERR_STATE_save(ERR_STATE *es)
     memset(thread_es, 0, sizeof(*thread_es));
 }
 
+void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es)
+{
+    size_t i, j, count;
+    int top;
+    ERR_STATE *thread_es;
+
+    if (es == NULL)
+        return;
+
+    thread_es = ossl_err_get_state_int();
+    if (thread_es == NULL) {
+        for (i = 0; i < ERR_NUM_ERRORS; ++i)
+            err_clear(es, i, 1);
+
+        es->top = es->bottom = 0;
+        return;
+    }
+
+    /* Determine number of errors we are going to move. */
+    for (count = 0, top = thread_es->top;
+         thread_es->bottom != top
+         && thread_es->err_marks[top] == 0;
+         ++count)
+        top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
+
+    /* Move the errors, preserving order. */
+    for (i = 0, j = top; i < count; ++i) {
+        j = (j + 1) % ERR_NUM_ERRORS;
+
+        err_clear(es, i, 1);
+
+        /* Move the error entry to the given ERR_STATE. */
+        es->err_flags[i]        = thread_es->err_flags[j];
+        es->err_marks[i]        = 0;
+        es->err_buffer[i]       = thread_es->err_buffer[j];
+        es->err_data[i]         = thread_es->err_data[j];
+        es->err_data_size[i]    = thread_es->err_data_size[j];
+        es->err_data_flags[i]   = thread_es->err_data_flags[j];
+        es->err_file[i]         = thread_es->err_file[j];
+        es->err_line[i]         = thread_es->err_line[j];
+        es->err_func[i]         = thread_es->err_func[j];
+
+        thread_es->err_flags[j]     = 0;
+        thread_es->err_buffer[j]    = 0;
+        thread_es->err_data[j]      = NULL;
+        thread_es->err_data_size[j] = 0;
+        thread_es->err_file[j]      = NULL;
+        thread_es->err_line[j]      = 0;
+        thread_es->err_func[j]      = NULL;
+    }
+
+    if (i > 0) {
+        /* If we moved anything, es's stack always starts at [0]. */
+        es->top     = i - 1;
+        es->bottom  = ERR_NUM_ERRORS - 1;
+    } else {
+        /* Didn't move anything - empty stack */
+        es->top = es->bottom = 0;
+    }
+
+    /* Erase extra space as a precaution. */
+    for (; i < ERR_NUM_ERRORS; ++i)
+        err_clear(es, i, 1);
+}
+
 void OSSL_ERR_STATE_restore(const ERR_STATE *es)
 {
     size_t i;