1 1.1 christos /* 2 1.1 christos * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <string.h> 11 1.1 christos #include <openssl/opensslconf.h> 12 1.1 christos #include <openssl/err.h> 13 1.1 christos #include <openssl/macros.h> 14 1.1 christos 15 1.1 christos #include "testutil.h" 16 1.1 christos 17 1.1 christos #if defined(OPENSSL_SYS_WINDOWS) 18 1.1.1.2 christos #include <windows.h> 19 1.1 christos #else 20 1.1.1.2 christos #include <errno.h> 21 1.1 christos #endif 22 1.1 christos 23 1.1 christos #ifndef OPENSSL_NO_DEPRECATED_3_0 24 1.1.1.2 christos #define IS_HEX(ch) ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) 25 1.1 christos 26 1.1 christos static int test_print_error_format(void) 27 1.1 christos { 28 1.1 christos /* Variables used to construct an error line */ 29 1.1 christos char *lib; 30 1.1 christos const char *func = OPENSSL_FUNC; 31 1.1 christos char *reason; 32 1.1.1.2 christos #ifdef OPENSSL_NO_ERR 33 1.1 christos char reasonbuf[255]; 34 1.1.1.2 christos #endif 35 1.1.1.2 christos #ifndef OPENSSL_NO_FILENAMES 36 1.1 christos const char *file = OPENSSL_FILE; 37 1.1 christos const int line = OPENSSL_LINE; 38 1.1.1.2 christos #else 39 1.1 christos const char *file = ""; 40 1.1 christos const int line = 0; 41 1.1.1.2 christos #endif 42 1.1 christos /* The format for OpenSSL error lines */ 43 1.1 christos const char *expected_format = ":error:%08lX:%s:%s:%s:%s:%d"; 44 1.1 christos /*- 45 1.1 christos * ^^ ^^ ^^ ^^ ^^ 46 1.1 christos * "library" name --------------------------++ || || || || 47 1.1 christos * function name ------------------------------++ || || || 48 1.1 christos * reason string (system error string) -----------++ || || 49 1.1 christos * file name ----------------------------------------++ || 50 1.1 christos * line number -----------------------------------------++ 51 1.1 christos */ 52 1.1 christos char expected[512]; 53 1.1 christos 54 1.1 christos char *out = NULL, *p = NULL; 55 1.1 christos int ret = 0, len; 56 1.1 christos BIO *bio = NULL; 57 1.1 christos const int syserr = EPERM; 58 1.1 christos unsigned long errorcode; 59 1.1 christos unsigned long reasoncode; 60 1.1 christos 61 1.1 christos /* 62 1.1 christos * We set a mark here so we can clear the system error that we generate 63 1.1 christos * with ERR_PUT_error(). That is, after all, just a simulation to verify 64 1.1 christos * ERR_print_errors() output, not a real error. 65 1.1 christos */ 66 1.1 christos ERR_set_mark(); 67 1.1 christos 68 1.1 christos ERR_PUT_error(ERR_LIB_SYS, 0, syserr, file, line); 69 1.1 christos errorcode = ERR_peek_error(); 70 1.1 christos reasoncode = ERR_GET_REASON(errorcode); 71 1.1 christos 72 1.1 christos if (!TEST_int_eq(reasoncode, syserr)) { 73 1.1 christos ERR_pop_to_mark(); 74 1.1 christos goto err; 75 1.1 christos } 76 1.1 christos 77 1.1.1.2 christos #if !defined(OPENSSL_NO_ERR) 78 1.1.1.2 christos #if defined(OPENSSL_NO_AUTOERRINIT) 79 1.1 christos lib = "lib(2)"; 80 1.1.1.2 christos #else 81 1.1 christos lib = "system library"; 82 1.1.1.2 christos #endif 83 1.1 christos reason = strerror(syserr); 84 1.1.1.2 christos #else 85 1.1 christos lib = "lib(2)"; 86 1.1 christos BIO_snprintf(reasonbuf, sizeof(reasonbuf), "reason(%lu)", reasoncode); 87 1.1 christos reason = reasonbuf; 88 1.1.1.2 christos #endif 89 1.1 christos 90 1.1 christos BIO_snprintf(expected, sizeof(expected), expected_format, 91 1.1.1.2 christos errorcode, lib, func, reason, file, line); 92 1.1 christos 93 1.1 christos if (!TEST_ptr(bio = BIO_new(BIO_s_mem()))) 94 1.1 christos goto err; 95 1.1 christos 96 1.1 christos ERR_print_errors(bio); 97 1.1 christos 98 1.1 christos if (!TEST_int_gt(len = BIO_get_mem_data(bio, &out), 0)) 99 1.1 christos goto err; 100 1.1 christos /* Skip over the variable thread id at the start of the string */ 101 1.1 christos for (p = out; *p != ':' && *p != 0; ++p) { 102 1.1 christos if (!TEST_true(IS_HEX(*p))) 103 1.1 christos goto err; 104 1.1 christos } 105 1.1 christos if (!TEST_true(*p != 0) 106 1.1 christos || !TEST_strn_eq(expected, p, strlen(expected))) 107 1.1 christos goto err; 108 1.1 christos 109 1.1 christos ret = 1; 110 1.1 christos err: 111 1.1 christos BIO_free(bio); 112 1.1 christos return ret; 113 1.1 christos } 114 1.1 christos #endif 115 1.1 christos 116 1.1 christos /* Test that querying the error queue preserves the OS error. */ 117 1.1 christos static int preserves_system_error(void) 118 1.1 christos { 119 1.1 christos #if defined(OPENSSL_SYS_WINDOWS) 120 1.1 christos SetLastError(ERROR_INVALID_FUNCTION); 121 1.1 christos ERR_get_error(); 122 1.1 christos return TEST_int_eq(GetLastError(), ERROR_INVALID_FUNCTION); 123 1.1 christos #else 124 1.1 christos errno = EINVAL; 125 1.1 christos ERR_get_error(); 126 1.1 christos return TEST_int_eq(errno, EINVAL); 127 1.1 christos #endif 128 1.1 christos } 129 1.1 christos 130 1.1 christos /* Test that calls to ERR_add_error_[v]data append */ 131 1.1 christos static int vdata_appends(void) 132 1.1 christos { 133 1.1 christos const char *data; 134 1.1 christos 135 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 136 1.1 christos ERR_add_error_data(1, "hello "); 137 1.1 christos ERR_add_error_data(1, "world"); 138 1.1 christos ERR_peek_error_data(&data, NULL); 139 1.1 christos return TEST_str_eq(data, "hello world"); 140 1.1 christos } 141 1.1 christos 142 1.1 christos static int raised_error(void) 143 1.1 christos { 144 1.1.1.2 christos int l, start_line = -1, end_line = -1; 145 1.1.1.2 christos const char *f, *data, *file = NULL; 146 1.1 christos unsigned long e; 147 1.1 christos 148 1.1 christos file = __FILE__; 149 1.1.1.2 christos 150 1.1.1.2 christos start_line = __LINE__ + 1; 151 1.1 christos ERR_raise_data(ERR_LIB_NONE, ERR_R_INTERNAL_ERROR, 152 1.1.1.2 christos "calling exit()"); 153 1.1.1.2 christos end_line = __LINE__ - 1; 154 1.1 christos if (!TEST_ulong_ne(e = ERR_get_error_all(&f, &l, NULL, &data, NULL), 0) 155 1.1.1.2 christos || !TEST_int_eq(ERR_GET_REASON(e), ERR_R_INTERNAL_ERROR) 156 1.1.1.2 christos || (l > 0 && !(TEST_int_eq(l, start_line) || TEST_int_eq(l, end_line))) 157 1.1.1.2 christos || (strlen(f) != 0 && !TEST_str_eq(f, file)) 158 1.1.1.2 christos || !TEST_str_eq(data, "calling exit()")) 159 1.1 christos return 0; 160 1.1 christos return 1; 161 1.1 christos } 162 1.1 christos 163 1.1 christos static int test_marks(void) 164 1.1 christos { 165 1.1 christos unsigned long mallocfail, shouldnot; 166 1.1 christos 167 1.1 christos /* Set an initial error */ 168 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 169 1.1 christos mallocfail = ERR_peek_last_error(); 170 1.1 christos if (!TEST_ulong_gt(mallocfail, 0)) 171 1.1 christos return 0; 172 1.1 christos 173 1.1 christos /* Setting and clearing a mark should not affect the error */ 174 1.1 christos if (!TEST_true(ERR_set_mark()) 175 1.1.1.2 christos || !TEST_true(ERR_pop_to_mark()) 176 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_peek_last_error()) 177 1.1.1.2 christos || !TEST_true(ERR_set_mark()) 178 1.1.1.2 christos || !TEST_true(ERR_clear_last_mark()) 179 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) 180 1.1 christos return 0; 181 1.1 christos 182 1.1 christos /* Test popping errors */ 183 1.1 christos if (!TEST_true(ERR_set_mark())) 184 1.1 christos return 0; 185 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); 186 1.1 christos if (!TEST_ulong_ne(mallocfail, ERR_peek_last_error()) 187 1.1.1.2 christos || !TEST_true(ERR_pop_to_mark()) 188 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) 189 1.1 christos return 0; 190 1.1 christos 191 1.1 christos /* Nested marks should also work */ 192 1.1 christos if (!TEST_true(ERR_set_mark()) 193 1.1.1.2 christos || !TEST_true(ERR_set_mark())) 194 1.1 christos return 0; 195 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); 196 1.1 christos if (!TEST_ulong_ne(mallocfail, ERR_peek_last_error()) 197 1.1.1.2 christos || !TEST_true(ERR_pop_to_mark()) 198 1.1.1.2 christos || !TEST_true(ERR_pop_to_mark()) 199 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) 200 1.1 christos return 0; 201 1.1 christos 202 1.1 christos if (!TEST_true(ERR_set_mark())) 203 1.1 christos return 0; 204 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 205 1.1 christos shouldnot = ERR_peek_last_error(); 206 1.1 christos if (!TEST_ulong_ne(mallocfail, shouldnot) 207 1.1.1.2 christos || !TEST_true(ERR_set_mark())) 208 1.1 christos return 0; 209 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); 210 1.1 christos if (!TEST_ulong_ne(shouldnot, ERR_peek_last_error()) 211 1.1.1.2 christos || !TEST_true(ERR_pop_to_mark()) 212 1.1.1.2 christos || !TEST_ulong_eq(shouldnot, ERR_peek_last_error()) 213 1.1.1.2 christos || !TEST_true(ERR_pop_to_mark()) 214 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) 215 1.1 christos return 0; 216 1.1 christos 217 1.1 christos /* Setting and clearing a mark should not affect the errors on the stack */ 218 1.1 christos if (!TEST_true(ERR_set_mark())) 219 1.1 christos return 0; 220 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 221 1.1 christos if (!TEST_true(ERR_clear_last_mark()) 222 1.1.1.2 christos || !TEST_ulong_eq(shouldnot, ERR_peek_last_error())) 223 1.1 christos return 0; 224 1.1 christos 225 1.1 christos /* 226 1.1 christos * Popping where no mark has been set should pop everything - but return 227 1.1 christos * a failure result 228 1.1 christos */ 229 1.1 christos if (!TEST_false(ERR_pop_to_mark()) 230 1.1.1.2 christos || !TEST_ulong_eq(0, ERR_peek_last_error())) 231 1.1 christos return 0; 232 1.1 christos 233 1.1 christos /* Clearing where there is no mark should fail */ 234 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 235 1.1 christos if (!TEST_false(ERR_clear_last_mark()) 236 1.1.1.2 christos /* "get" the last error to remove it */ 237 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_get_error()) 238 1.1.1.2 christos || !TEST_ulong_eq(0, ERR_peek_last_error())) 239 1.1 christos return 0; 240 1.1 christos 241 1.1 christos /* 242 1.1 christos * Setting a mark where there are no errors in the stack should fail. 243 1.1 christos * NOTE: This is somewhat surprising behaviour but is historically how this 244 1.1 christos * function behaves. In practice we typically set marks without first 245 1.1 christos * checking whether there is anything on the stack - but we also don't 246 1.1 christos * tend to check the success of this function. It turns out to work anyway 247 1.1 christos * because although setting a mark with no errors fails, a subsequent call 248 1.1 christos * to ERR_pop_to_mark() or ERR_clear_last_mark() will do the right thing 249 1.1 christos * anyway (even though they will report a failure result). 250 1.1 christos */ 251 1.1 christos if (!TEST_false(ERR_set_mark())) 252 1.1 christos return 0; 253 1.1 christos 254 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 255 1.1 christos if (!TEST_true(ERR_set_mark())) 256 1.1 christos return 0; 257 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); 258 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 259 1.1 christos 260 1.1 christos /* Should be able to "pop" past 2 errors */ 261 1.1 christos if (!TEST_true(ERR_pop_to_mark()) 262 1.1.1.2 christos || !TEST_ulong_eq(mallocfail, ERR_peek_last_error())) 263 1.1 christos return 0; 264 1.1 christos 265 1.1 christos if (!TEST_true(ERR_set_mark())) 266 1.1 christos return 0; 267 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); 268 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 269 1.1 christos 270 1.1 christos /* Should be able to "clear" past 2 errors */ 271 1.1 christos if (!TEST_true(ERR_clear_last_mark()) 272 1.1.1.2 christos || !TEST_ulong_eq(shouldnot, ERR_peek_last_error())) 273 1.1 christos return 0; 274 1.1 christos 275 1.1 christos /* Clear remaining errors from last test */ 276 1.1 christos ERR_clear_error(); 277 1.1 christos 278 1.1 christos return 1; 279 1.1 christos } 280 1.1 christos 281 1.1 christos static int test_clear_error(void) 282 1.1 christos { 283 1.1 christos int flags = -1; 284 1.1 christos const char *data = NULL; 285 1.1 christos int res = 0; 286 1.1 christos 287 1.1 christos /* Raise an error with data and clear it */ 288 1.1 christos ERR_raise_data(0, 0, "hello %s", "world"); 289 1.1 christos ERR_peek_error_data(&data, &flags); 290 1.1 christos if (!TEST_str_eq(data, "hello world") 291 1.1.1.2 christos || !TEST_int_eq(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 292 1.1 christos goto err; 293 1.1 christos ERR_clear_error(); 294 1.1 christos 295 1.1 christos /* Raise a new error without data */ 296 1.1 christos ERR_raise(0, 0); 297 1.1 christos ERR_peek_error_data(&data, &flags); 298 1.1 christos if (!TEST_str_eq(data, "") 299 1.1.1.2 christos || !TEST_int_eq(flags, ERR_TXT_MALLOCED)) 300 1.1 christos goto err; 301 1.1 christos ERR_clear_error(); 302 1.1 christos 303 1.1 christos /* Raise a new error with data */ 304 1.1 christos ERR_raise_data(0, 0, "goodbye %s world", "cruel"); 305 1.1 christos ERR_peek_error_data(&data, &flags); 306 1.1 christos if (!TEST_str_eq(data, "goodbye cruel world") 307 1.1.1.2 christos || !TEST_int_eq(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 308 1.1 christos goto err; 309 1.1 christos ERR_clear_error(); 310 1.1 christos 311 1.1 christos /* 312 1.1 christos * Raise a new error without data to check that the malloced storage 313 1.1 christos * is freed properly 314 1.1 christos */ 315 1.1 christos ERR_raise(0, 0); 316 1.1 christos ERR_peek_error_data(&data, &flags); 317 1.1 christos if (!TEST_str_eq(data, "") 318 1.1.1.2 christos || !TEST_int_eq(flags, ERR_TXT_MALLOCED)) 319 1.1 christos goto err; 320 1.1 christos ERR_clear_error(); 321 1.1 christos 322 1.1 christos res = 1; 323 1.1.1.2 christos err: 324 1.1.1.2 christos ERR_clear_error(); 325 1.1 christos return res; 326 1.1 christos } 327 1.1 christos 328 1.1 christos /* 329 1.1 christos * Test saving and restoring error state. 330 1.1 christos * Test 0: Save using OSSL_ERR_STATE_save() 331 1.1 christos * Test 1: Save using OSSL_ERR_STATE_save_to_mark() 332 1.1 christos */ 333 1.1 christos static int test_save_restore(int idx) 334 1.1 christos { 335 1.1 christos ERR_STATE *es; 336 1.1 christos int res = 0, i, flags = -1; 337 1.1 christos unsigned long mallocfail, interr; 338 1.1 christos static const char testdata[] = "test data"; 339 1.1 christos const char *data = NULL; 340 1.1 christos 341 1.1 christos if (!TEST_ptr(es = OSSL_ERR_STATE_new())) 342 1.1 christos goto err; 343 1.1 christos 344 1.1 christos ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 345 1.1 christos mallocfail = ERR_peek_last_error(); 346 1.1 christos if (!TEST_ulong_gt(mallocfail, 0)) 347 1.1 christos goto err; 348 1.1 christos 349 1.1 christos if (idx == 1 && !TEST_int_eq(ERR_set_mark(), 1)) 350 1.1 christos goto err; 351 1.1 christos 352 1.1 christos ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR, testdata); 353 1.1 christos interr = ERR_peek_last_error(); 354 1.1 christos if (!TEST_ulong_ne(mallocfail, ERR_peek_last_error())) 355 1.1 christos goto err; 356 1.1 christos 357 1.1 christos if (idx == 0) { 358 1.1 christos OSSL_ERR_STATE_save(es); 359 1.1 christos 360 1.1 christos if (!TEST_ulong_eq(ERR_peek_last_error(), 0)) 361 1.1 christos goto err; 362 1.1 christos } else { 363 1.1 christos OSSL_ERR_STATE_save_to_mark(es); 364 1.1 christos 365 1.1 christos if (!TEST_ulong_ne(ERR_peek_last_error(), 0)) 366 1.1 christos goto err; 367 1.1 christos } 368 1.1 christos 369 1.1 christos for (i = 0; i < 2; i++) { 370 1.1 christos OSSL_ERR_STATE_restore(es); 371 1.1 christos 372 1.1 christos if (!TEST_ulong_eq(ERR_peek_last_error(), interr)) 373 1.1 christos goto err; 374 1.1 christos ERR_peek_last_error_data(&data, &flags); 375 1.1 christos if (!TEST_str_eq(data, testdata) 376 1.1.1.2 christos || !TEST_int_eq(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 377 1.1 christos goto err; 378 1.1 christos 379 1.1 christos /* restore again to duplicate the entries */ 380 1.1 christos OSSL_ERR_STATE_restore(es); 381 1.1 christos 382 1.1 christos /* verify them all */ 383 1.1 christos if (idx == 0 || i == 0) { 384 1.1 christos if (!TEST_ulong_eq(ERR_get_error_all(NULL, NULL, NULL, 385 1.1.1.2 christos &data, &flags), 386 1.1.1.2 christos mallocfail) 387 1.1 christos || !TEST_int_ne(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 388 1.1 christos goto err; 389 1.1 christos } 390 1.1 christos 391 1.1 christos if (!TEST_ulong_eq(ERR_get_error_all(NULL, NULL, NULL, 392 1.1.1.2 christos &data, &flags), 393 1.1.1.2 christos interr) 394 1.1 christos || !TEST_str_eq(data, testdata) 395 1.1 christos || !TEST_int_eq(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 396 1.1 christos goto err; 397 1.1 christos 398 1.1 christos if (idx == 0) { 399 1.1 christos if (!TEST_ulong_eq(ERR_get_error_all(NULL, NULL, NULL, 400 1.1.1.2 christos &data, &flags), 401 1.1.1.2 christos mallocfail) 402 1.1 christos || !TEST_int_ne(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 403 1.1 christos goto err; 404 1.1 christos } 405 1.1 christos 406 1.1 christos if (!TEST_ulong_eq(ERR_get_error_all(NULL, NULL, NULL, 407 1.1.1.2 christos &data, &flags), 408 1.1.1.2 christos interr) 409 1.1 christos || !TEST_str_eq(data, testdata) 410 1.1 christos || !TEST_int_eq(flags, ERR_TXT_STRING | ERR_TXT_MALLOCED)) 411 1.1 christos goto err; 412 1.1 christos 413 1.1 christos if (!TEST_ulong_eq(ERR_get_error(), 0)) 414 1.1 christos goto err; 415 1.1 christos } 416 1.1 christos 417 1.1 christos res = 1; 418 1.1.1.2 christos err: 419 1.1 christos OSSL_ERR_STATE_free(es); 420 1.1 christos return res; 421 1.1 christos } 422 1.1 christos 423 1.1 christos int setup_tests(void) 424 1.1 christos { 425 1.1 christos ADD_TEST(preserves_system_error); 426 1.1 christos ADD_TEST(vdata_appends); 427 1.1 christos ADD_TEST(raised_error); 428 1.1 christos #ifndef OPENSSL_NO_DEPRECATED_3_0 429 1.1 christos ADD_TEST(test_print_error_format); 430 1.1 christos #endif 431 1.1 christos ADD_TEST(test_marks); 432 1.1 christos ADD_ALL_TESTS(test_save_restore, 2); 433 1.1 christos ADD_TEST(test_clear_error); 434 1.1 christos return 1; 435 1.1 christos } 436