diff options
author | Matt Caswell <matt@openssl.org> | 2020-11-06 12:53:01 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2020-11-19 14:57:18 +0000 |
commit | c34063d7a1e8e3e0f760fd998366165862730bae (patch) | |
tree | 7a5f3601860366688e694bd2582bd6c7c0223a53 /test/errtest.c | |
parent | 4e08ea6f111d7bdcef0659baca700a78aa867913 (diff) |
Add a test for setting, popping and clearing error marks
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/13335)
Diffstat (limited to 'test/errtest.c')
-rw-r--r-- | test/errtest.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/test/errtest.c b/test/errtest.c index 443bd0a57d..247bc546a0 100644 --- a/test/errtest.c +++ b/test/errtest.c @@ -148,6 +148,124 @@ static int raised_error(void) return 1; } +static int test_marks(void) +{ + unsigned long mallocfail, shouldnot; + + /* Set an initial error */ + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + mallocfail = ERR_peek_last_error(); + if (!TEST_ulong_gt(mallocfail, 0)) + return 0; + + /* Setting and clearing a mark should not affect the error */ + if (!TEST_true(ERR_set_mark()) + || !TEST_true(ERR_pop_to_mark()) + || !TEST_ulong_eq(mallocfail, ERR_peek_last_error()) + || !TEST_true(ERR_set_mark()) + || !TEST_true(ERR_clear_last_mark()) + || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) + return 0; + + /* Test popping errors */ + if (!TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + if (!TEST_ulong_ne(mallocfail, ERR_peek_last_error()) + || !TEST_true(ERR_pop_to_mark()) + || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) + return 0; + + /* Nested marks should also work */ + if (!TEST_true(ERR_set_mark()) + || !TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + if (!TEST_ulong_ne(mallocfail, ERR_peek_last_error()) + || !TEST_true(ERR_pop_to_mark()) + || !TEST_true(ERR_pop_to_mark()) + || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) + return 0; + + if (!TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + shouldnot = ERR_peek_last_error(); + if (!TEST_ulong_ne(mallocfail, shouldnot) + || !TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + if (!TEST_ulong_ne(shouldnot, ERR_peek_last_error()) + || !TEST_true(ERR_pop_to_mark()) + || !TEST_ulong_eq(shouldnot, ERR_peek_last_error()) + || !TEST_true(ERR_pop_to_mark()) + || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) + return 0; + + /* Setting and clearing a mark should not affect the errors on the stack */ + if (!TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + if (!TEST_true(ERR_clear_last_mark()) + || !TEST_ulong_eq(shouldnot, ERR_peek_last_error())) + return 0; + + /* + * Popping where no mark has been set should pop everything - but return + * a failure result + */ + if (!TEST_false(ERR_pop_to_mark()) + || !TEST_ulong_eq(0, ERR_peek_last_error())) + return 0; + + /* Clearing where there is no mark should fail */ + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (!TEST_false(ERR_clear_last_mark()) + /* "get" the last error to remove it */ + || !TEST_ulong_eq(mallocfail, ERR_get_error()) + || !TEST_ulong_eq(0, ERR_peek_last_error())) + return 0; + + /* + * Setting a mark where there are no errors in the stack should fail. + * NOTE: This is somewhat surprising behaviour but is historically how this + * function behaves. In practice we typically set marks without first + * checking whether there is anything on the stack - but we also don't + * tend to check the success of this function. It turns out to work anyway + * because although setting a mark with no errors fails, a subsequent call + * to ERR_pop_to_mark() or ERR_clear_last_mark() will do the right thing + * anyway (even though they will report a failure result). + */ + if (!TEST_false(ERR_set_mark())) + return 0; + + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (!TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + + /* Should be able to "pop" past 2 errors */ + if (!TEST_true(ERR_pop_to_mark()) + || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) + return 0; + + if (!TEST_true(ERR_set_mark())) + return 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + + /* Should be able to "clear" past 2 errors */ + if (!TEST_true(ERR_clear_last_mark()) + || !TEST_ulong_eq(shouldnot, ERR_peek_last_error())) + return 0; + + /* Clear remaining errors from last test */ + ERR_clear_error(); + + return 1; +} + int setup_tests(void) { ADD_TEST(preserves_system_error); @@ -156,5 +274,6 @@ int setup_tests(void) #ifndef OPENSSL_NO_DEPRECATED_3_0 ADD_TEST(test_print_error_format); #endif + ADD_TEST(test_marks); return 1; } |