summaryrefslogtreecommitdiffstats
path: root/crypto
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 /crypto
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)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/err/err.c10
-rw-r--r--crypto/err/err_local.h1
2 files changed, 6 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;