summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-11-06 11:43:44 +0000
committerMatt Caswell <matt@openssl.org>2020-11-19 14:56:58 +0000
commit4e08ea6f111d7bdcef0659baca700a78aa867913 (patch)
tree3175437f9561940d5191f96a4c71285f0f5909a5
parent5b1d94c11c680c2b9527c3da55593468bcf65efd (diff)
Allow multiple nested marks
Previously we only ever allowed one mark to be set against an error in the statck. If we attempted to nest them, then we would end up clearing all the errors in the stack when we popped to the mark. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/13335)
-rw-r--r--crypto/err/err.c10
-rw-r--r--crypto/err/err_local.h1
-rw-r--r--include/openssl/err.h.in1
3 files changed, 7 insertions, 5 deletions
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 2c8240f0ba..a66ea63adf 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -838,7 +838,7 @@ int ERR_set_mark(void)
if (es->bottom == es->top)
return 0;
- es->err_flags[es->top] |= ERR_FLAG_MARK;
+ es->err_marks[es->top]++;
return 1;
}
@@ -851,14 +851,14 @@ int ERR_pop_to_mark(void)
return 0;
while (es->bottom != es->top
- && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
+ && es->err_marks[es->top] == 0) {
err_clear(es, es->top, 0);
es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
}
if (es->bottom == es->top)
return 0;
- es->err_flags[es->top] &= ~ERR_FLAG_MARK;
+ es->err_marks[es->top]--;
return 1;
}
@@ -873,13 +873,13 @@ int ERR_clear_last_mark(void)
top = es->top;
while (es->bottom != top
- && (es->err_flags[top] & ERR_FLAG_MARK) == 0) {
+ && es->err_marks[top] == 0) {
top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
}
if (es->bottom == top)
return 0;
- es->err_flags[top] &= ~ERR_FLAG_MARK;
+ es->err_marks[top]--;
return 1;
}
diff --git a/crypto/err/err_local.h b/crypto/err/err_local.h
index 2f9caf2e0e..cad67cc476 100644
--- a/crypto/err/err_local.h
+++ b/crypto/err/err_local.h
@@ -64,6 +64,7 @@ static ossl_inline void err_set_data(ERR_STATE *es, size_t i,
static ossl_inline void err_clear(ERR_STATE *es, size_t i, int deall)
{
err_clear_data(es, i, (deall));
+ es->err_marks[i] = 0;
es->err_flags[i] = 0;
es->err_buffer[i] = 0;
es->err_file[i] = NULL;
diff --git a/include/openssl/err.h.in b/include/openssl/err.h.in
index 35db02fad6..1f2fde8317 100644
--- a/include/openssl/err.h.in
+++ b/include/openssl/err.h.in
@@ -56,6 +56,7 @@ extern "C" {
# define ERR_NUM_ERRORS 16
struct err_state_st {
int err_flags[ERR_NUM_ERRORS];
+ int err_marks[ERR_NUM_ERRORS];
unsigned long err_buffer[ERR_NUM_ERRORS];
char *err_data[ERR_NUM_ERRORS];
size_t err_data_size[ERR_NUM_ERRORS];