From b13342e933c507c4ce0eda0a0193339a111f27a5 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 4 Sep 2019 22:04:08 +0200 Subject: [PATCH] Modernise the ERR functionality further (new functions and deprecations) ERR_func_error_string() essentially returns NULL, and since all function codes are now removed for all intents and purposes, this function has fallen out of use and cannot be modified to suit the data, since its only function is to interpret an error code. To compensate for the loss of error code, we instead provide new functions that extracts the function name strings from an error record: - ERR_get_error_func() - ERR_peek_error_func() - ERR_peek_last_error_func() Similarly, the once all encompasing functions ERR_peek_last_error_line_data(), ERR_peek_error_line_data() and ERR_get_error_line_data() lack the capability of getting the function name string, so we deprecate those and add these functions to replace them: - ERR_get_error_all() - ERR_peek_error_all() - ERR_peek_last_error_all() Finally, we adjust a few lines of code that used the now deprecated functions. Fixes #9756 Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/9756) --- crypto/err/err.c | 105 ++++++++++++++++++++++++++++++------- doc/man3/ERR_get_error.pod | 64 +++++++++++++++++++--- include/openssl/err.h | 47 ++++++++++++++--- test/errtest.c | 4 +- test/evp_test.c | 4 +- util/libcrypto.num | 17 ++++-- 6 files changed, 198 insertions(+), 43 deletions(-) diff --git a/crypto/err/err.c b/crypto/err/err.c index 25ab13509c..deaa579090 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -126,8 +126,8 @@ static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; static int int_err_library_number = ERR_LIB_USER; static unsigned long get_error_values(int inc, int top, const char **file, - int *line, const char **data, - int *flags); + int *line, const char **func, + const char **data, int *flags); static unsigned long err_string_data_hash(const ERR_STRING_DATA *a) { @@ -371,55 +371,112 @@ void ERR_clear_error(void) unsigned long ERR_get_error(void) { - return get_error_values(1, 0, NULL, NULL, NULL, NULL); + return get_error_values(1, 0, NULL, NULL, NULL, NULL, NULL); } unsigned long ERR_get_error_line(const char **file, int *line) { - return get_error_values(1, 0, file, line, NULL, NULL); + return get_error_values(1, 0, file, line, NULL, NULL, NULL); } +unsigned long ERR_get_error_func(const char **func) +{ + return get_error_values(1, 0, NULL, NULL, func, NULL, NULL); +} + +unsigned long ERR_get_error_data(const char **data, int *flags) +{ + return get_error_values(1, 0, NULL, NULL, NULL, data, flags); +} + +unsigned long ERR_get_error_all(const char **file, int *line, + const char **func, + const char **data, int *flags) +{ + return get_error_values(1, 0, file, line, func, data, flags); +} + +#if !OPENSSL_API_3 unsigned long ERR_get_error_line_data(const char **file, int *line, const char **data, int *flags) { - return get_error_values(1, 0, file, line, data, flags); + return get_error_values(1, 0, file, line, NULL, data, flags); } +#endif unsigned long ERR_peek_error(void) { - return get_error_values(0, 0, NULL, NULL, NULL, NULL); + return get_error_values(0, 0, NULL, NULL, NULL, NULL, NULL); } unsigned long ERR_peek_error_line(const char **file, int *line) { - return get_error_values(0, 0, file, line, NULL, NULL); + return get_error_values(0, 0, file, line, NULL, NULL, NULL); +} + +unsigned long ERR_peek_error_func(const char **func) +{ + return get_error_values(0, 0, NULL, NULL, func, NULL, NULL); +} + +unsigned long ERR_peek_error_data(const char **data, int *flags) +{ + return get_error_values(0, 0, NULL, NULL, NULL, data, flags); +} + +unsigned long ERR_peek_error_all(const char **file, int *line, + const char **func, + const char **data, int *flags) +{ + return get_error_values(0, 0, file, line, func, data, flags); } +#if !OPENSSL_API_3 unsigned long ERR_peek_error_line_data(const char **file, int *line, const char **data, int *flags) { - return get_error_values(0, 0, file, line, data, flags); + return get_error_values(0, 0, file, line, NULL, data, flags); } +#endif unsigned long ERR_peek_last_error(void) { - return get_error_values(0, 1, NULL, NULL, NULL, NULL); + return get_error_values(0, 1, NULL, NULL, NULL, NULL, NULL); } unsigned long ERR_peek_last_error_line(const char **file, int *line) { - return get_error_values(0, 1, file, line, NULL, NULL); + return get_error_values(0, 1, file, line, NULL, NULL, NULL); +} + +unsigned long ERR_peek_last_error_func(const char **func) +{ + return get_error_values(0, 1, NULL, NULL, func, NULL, NULL); +} + +unsigned long ERR_peek_last_error_data(const char **data, int *flags) +{ + return get_error_values(0, 1, NULL, NULL, NULL, data, flags); +} + +unsigned long ERR_peek_last_error_all(const char **file, int *line, + const char **func, + const char **data, int *flags) +{ + return get_error_values(0, 1, file, line, func, data, flags); } +#if !OPENSSL_API_3 unsigned long ERR_peek_last_error_line_data(const char **file, int *line, const char **data, int *flags) { - return get_error_values(0, 1, file, line, data, flags); + return get_error_values(0, 1, file, line, NULL, data, flags); } +#endif static unsigned long get_error_values(int inc, int top, const char **file, - int *line, const char **data, - int *flags) + int *line, const char **func, + const char **data, int *flags) { int i = 0; ERR_STATE *es; @@ -430,13 +487,15 @@ static unsigned long get_error_values(int inc, int top, const char **file, return 0; if (inc && top) { - if (file) + if (file != NULL) *file = ""; - if (line) + if (line != NULL) *line = 0; - if (data) + if (func != NULL) + *func = ""; + if (data != NULL) *data = ""; - if (flags) + if (flags != NULL) *flags = 0; return ERR_R_INTERNAL_ERROR; @@ -481,6 +540,12 @@ static unsigned long get_error_values(int inc, int top, const char **file, } } + if (func != NULL) { + *func = es->err_func[i]; + if (*func == NULL) + *func = "N/A"; + } + if (data == NULL) { if (inc) { err_clear_data(es, i, 0); @@ -558,12 +623,12 @@ const char *ERR_lib_error_string(unsigned long e) return ((p == NULL) ? NULL : p->string); } +#if !OPENSSL_API_3 const char *ERR_func_error_string(unsigned long e) { - if (!RUN_ONCE(&err_string_init, do_err_strings_init)) - return NULL; - return ERR_GET_LIB(e) == ERR_LIB_SYS ? "system library" : NULL; + return NULL; } +#endif const char *ERR_reason_error_string(unsigned long e) { diff --git a/doc/man3/ERR_get_error.pod b/doc/man3/ERR_get_error.pod index c3fab39cb9..045ef210a2 100644 --- a/doc/man3/ERR_get_error.pod +++ b/doc/man3/ERR_get_error.pod @@ -4,8 +4,11 @@ ERR_get_error, ERR_peek_error, ERR_peek_last_error, ERR_get_error_line, ERR_peek_error_line, ERR_peek_last_error_line, -ERR_get_error_line_data, ERR_peek_error_line_data, -ERR_peek_last_error_line_data - obtain error code and data +ERR_get_error_func, ERR_peek_error_func, ERR_peek_last_error_func, +ERR_get_error_data, ERR_peek_error_data, ERR_peek_last_error_data, +ERR_get_error_all, ERR_peek_error_all, ERR_peek_last_error_all, +ERR_get_error_line_data, ERR_peek_error_line_data, ERR_peek_last_error_line_data +- obtain error code and data =head1 SYNOPSIS @@ -19,6 +22,26 @@ ERR_peek_last_error_line_data - obtain error code and data unsigned long ERR_peek_error_line(const char **file, int *line); unsigned long ERR_peek_last_error_line(const char **file, int *line); + unsigned long ERR_get_error_func(const char **func); + unsigned long ERR_peek_error_func(const char **func); + unsigned long ERR_peek_last_error_func(const char **func); + + unsigned long ERR_get_error_data(const char **data, int *flags); + unsigned long ERR_peek_error_data(const char **data, int *flags); + unsigned long ERR_peek_last_error_data(const char **data, int *flags); + + unsigned long ERR_get_error_all(const char **file, int *line, + const char *func, + const char **data, int *flags); + unsigned long ERR_peek_error_all(const char **file, int *line, + const char *func, + const char **data, int *flags); + unsigned long ERR_peek_last_error_all(const char **file, int *line, + const char *func, + const char **data, int *flags); + +Deprecated since OpenSSL 3.0: + unsigned long ERR_get_error_line_data(const char **file, int *line, const char **data, int *flags); unsigned long ERR_peek_error_line_data(const char **file, int *line, @@ -44,15 +67,31 @@ L for human-readable error messages. ERR_get_error_line(), ERR_peek_error_line() and -ERR_peek_last_error_line() are the same as the above, but they +ERR_peek_last_error_line() are the same as ERR_get_error(), +ERR_peek_error() and ERR_peek_last_error(), but they additionally store the file name and line number where the error occurred in *B and *B, unless these are B. +ERR_get_error_func(), ERR_peek_error_func() and +ERR_peek_last_error_func() are the same as ERR_get_error(), +ERR_peek_error() and ERR_peek_last_error(), but they +additionally store the name of the function where the error in *B, +unless it is B. + +ERR_get_error_data(), ERR_peek_error_data() and +ERR_peek_last_error_data() are the same as ERR_get_error(), +ERR_peek_error() and ERR_peek_last_error(), but they +additionally store additional data and flags associated with the error +code in *B and *B, unless these are B. +*B contains a string if *B&B is true. + +ERR_get_error_all(), ERR_peek_error_all() and +ERR_peek_last_error_all() are combinations of all of the above. + ERR_get_error_line_data(), ERR_peek_error_line_data() and -ERR_peek_last_error_line_data() store additional data and flags -associated with the error code in *B -and *B, unless these are B. *B contains a string -if *B&B is true. +ERR_peek_last_error_line_data() are older variants of ERR_get_error_all(), +ERR_peek_error_all() and ERR_peek_last_error_all(), and should no longer +be used. An application B free the *B pointer (or any other pointers returned by these functions) with OPENSSL_free() as freeing is handled @@ -67,6 +106,17 @@ The error code, or 0 if there is no error in the queue. L, L +=head1 HISTORY + +ERR_get_error_func(), ERR_peek_error_func(), ERR_peek_last_error_func(), +ERR_get_error_data(), ERR_peek_error_data(), ERR_peek_last_error_data(), +ERR_get_error_all(), ERR_peek_error_all() and ERR_peek_last_error_all() +were added in OpenSSL 3.0. + +ERR_get_error_line_data(), ERR_peek_error_line_data() and +ERR_peek_last_error_line_data() became deprecated in OpenSSL 3.0. + + =head1 COPYRIGHT Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/err.h b/include/openssl/err.h index 0da66092b4..2b4a71a9a4 100644 --- a/include/openssl/err.h +++ b/include/openssl/err.h @@ -260,31 +260,64 @@ void ERR_vset_error(int lib, int reason, const char *fmt, va_list args); void ERR_set_error_data(char *data, int flags); unsigned long ERR_get_error(void); +/* + * TODO(3.0) consider if the following three functions should be deprecated. + * They all drop the error record from the error queue, so regardless of which + * one is used, the rest of the information is lost, making them not so useful. + * The recommendation should be to use the peek functions to extract all the + * additional data. + */ unsigned long ERR_get_error_line(const char **file, int *line); -unsigned long ERR_get_error_line_data(const char **file, int *line, - const char **data, int *flags); +unsigned long ERR_get_error_func(const char **func); +unsigned long ERR_get_error_data(const char **data, int *flags); +unsigned long ERR_get_error_all(const char **file, int *line, + const char **func, + const char **data, int *flags); +DEPRECATEDIN_3(unsigned long ERR_get_error_line_data(const char **file, + int *line, + const char **data, + int *flags)) unsigned long ERR_peek_error(void); unsigned long ERR_peek_error_line(const char **file, int *line); -unsigned long ERR_peek_error_line_data(const char **file, int *line, - const char **data, int *flags); +unsigned long ERR_peek_error_func(const char **func); +unsigned long ERR_peek_error_data(const char **data, int *flags); +unsigned long ERR_peek_error_all(const char **file, int *line, + const char **func, + const char **data, int *flags); +DEPRECATEDIN_3(unsigned long ERR_peek_error_line_data(const char **file, + int *line, + const char **data, + int *flags)) unsigned long ERR_peek_last_error(void); unsigned long ERR_peek_last_error_line(const char **file, int *line); -unsigned long ERR_peek_last_error_line_data(const char **file, int *line, - const char **data, int *flags); +unsigned long ERR_peek_last_error_func(const char **func); +unsigned long ERR_peek_last_error_data(const char **data, int *flags); +unsigned long ERR_peek_last_error_all(const char **file, int *line, + const char **func, + const char **data, int *flags); +DEPRECATEDIN_3(unsigned long ERR_peek_last_error_line_data(const char **file, + int *line, + const char **data, + int *flags)) + void ERR_clear_error(void); + char *ERR_error_string(unsigned long e, char *buf); void ERR_error_string_n(unsigned long e, char *buf, size_t len); const char *ERR_lib_error_string(unsigned long e); -const char *ERR_func_error_string(unsigned long e); +DEPRECATEDIN_3(const char *ERR_func_error_string(unsigned long e)) const char *ERR_reason_error_string(unsigned long e); + void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), void *u); # ifndef OPENSSL_NO_STDIO void ERR_print_errors_fp(FILE *fp); # endif void ERR_print_errors(BIO *bp); + void ERR_add_error_data(int num, ...); void ERR_add_error_vdata(int num, va_list args); + int ERR_load_strings(int lib, ERR_STRING_DATA *str); int ERR_load_strings_const(const ERR_STRING_DATA *str); int ERR_unload_strings(int lib, ERR_STRING_DATA *str); diff --git a/test/errtest.c b/test/errtest.c index ffe6532240..179c338c45 100644 --- a/test/errtest.c +++ b/test/errtest.c @@ -40,7 +40,7 @@ static int vdata_appends(void) CRYPTOerr(0, ERR_R_MALLOC_FAILURE); ERR_add_error_data(1, "hello "); ERR_add_error_data(1, "world"); - ERR_get_error_line_data(NULL, NULL, &data, NULL); + ERR_peek_error_data(&data, NULL); return TEST_str_eq(data, "hello world"); } @@ -63,7 +63,7 @@ static int raised_error(void) #endif ERR_raise_data(ERR_LIB_SYS, ERR_R_INTERNAL_ERROR, "calling exit()"); - if (!TEST_ulong_ne(e = ERR_get_error_line_data(&f, &l, &data, NULL), 0) + if (!TEST_ulong_ne(e = ERR_get_error_all(&f, &l, NULL, &data, NULL), 0) || !TEST_int_eq(ERR_GET_REASON(e), ERR_R_INTERNAL_ERROR) #if !defined(OPENSSL_NO_FILENAMES) && !defined(OPENSSL_NO_ERR) || !TEST_int_eq(l, line) diff --git a/test/evp_test.c b/test/evp_test.c index b1194d2bc9..0b5fd5dae3 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -2799,7 +2799,6 @@ static void clear_test(EVP_TEST *t) static int check_test_error(EVP_TEST *t) { unsigned long err; - const char *func; const char *reason; if (t->err == NULL && t->expected_err == NULL) @@ -2842,9 +2841,8 @@ static int check_test_error(EVP_TEST *t) return 0; } - func = ERR_func_error_string(err); reason = ERR_reason_error_string(err); - if (func == NULL && reason == NULL) { + if (reason == NULL) { TEST_info("%s:%d: Expected error \"%s\", no strings available." " Assuming ok.", t->s.test_file, t->s.start, t->reason); diff --git a/util/libcrypto.num b/util/libcrypto.num index 07469a1f26..cadc4a57ba 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -515,7 +515,7 @@ DH_generate_parameters 526 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_0 BN_set_negative 527 3_0_0 EXIST::FUNCTION: i2d_TS_RESP_bio 528 3_0_0 EXIST::FUNCTION:TS ASYNC_WAIT_CTX_set_wait_fd 529 3_0_0 EXIST::FUNCTION: -ERR_func_error_string 530 3_0_0 EXIST::FUNCTION: +ERR_func_error_string 530 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3 ASN1_STRING_data 531 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_1_1_0 X509_CRL_add1_ext_i2d 532 3_0_0 EXIST::FUNCTION: i2d_TS_TST_INFO 533 3_0_0 EXIST::FUNCTION:TS @@ -757,7 +757,7 @@ EVP_rc5_32_12_16_cfb64 775 3_0_0 EXIST::FUNCTION:RC5 PKCS7_dataVerify 776 3_0_0 EXIST::FUNCTION: PKCS7_SIGNER_INFO_free 777 3_0_0 EXIST::FUNCTION: PKCS7_add_attrib_smimecap 778 3_0_0 EXIST::FUNCTION: -ERR_peek_last_error_line_data 779 3_0_0 EXIST::FUNCTION: +ERR_peek_last_error_line_data 779 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3 EVP_PKEY_meth_set_sign 780 3_0_0 EXIST::FUNCTION: ASN1_i2d_bio 781 3_0_0 EXIST::FUNCTION: DSA_verify 782 3_0_0 EXIST::FUNCTION:DSA @@ -969,7 +969,7 @@ DH_get_default_method 993 3_0_0 EXIST::FUNCTION:DH PEM_proc_type 994 3_0_0 EXIST::FUNCTION: BIO_printf 995 3_0_0 EXIST::FUNCTION: a2i_IPADDRESS 996 3_0_0 EXIST::FUNCTION: -ERR_peek_error_line_data 997 3_0_0 EXIST::FUNCTION: +ERR_peek_error_line_data 997 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3 ERR_unload_strings 998 3_0_0 EXIST::FUNCTION: SEED_cfb128_encrypt 999 3_0_0 EXIST::FUNCTION:SEED ASN1_BIT_STRING_it 1000 3_0_0 EXIST::FUNCTION: @@ -1554,7 +1554,7 @@ SRP_VBASE_free 1588 3_0_0 EXIST::FUNCTION:SRP PKCS7_add0_attrib_signing_time 1589 3_0_0 EXIST::FUNCTION: X509_STORE_set_flags 1590 3_0_0 EXIST::FUNCTION: UI_get0_output_string 1591 3_0_0 EXIST::FUNCTION: -ERR_get_error_line_data 1592 3_0_0 EXIST::FUNCTION: +ERR_get_error_line_data 1592 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3 CTLOG_get0_name 1593 3_0_0 EXIST::FUNCTION:CT ASN1_TBOOLEAN_it 1594 3_0_0 EXIST::FUNCTION: RC2_set_key 1595 3_0_0 EXIST::FUNCTION:RC2 @@ -4753,3 +4753,12 @@ EVP_PKEY_CTX_get_params 4869 3_0_0 EXIST::FUNCTION: EVP_PKEY_CTX_gettable_params 4870 3_0_0 EXIST::FUNCTION: EVP_PKEY_CTX_settable_params 4871 3_0_0 EXIST::FUNCTION: EVP_CIPHER_CTX_tag_length 4872 3_0_0 EXIST::FUNCTION: +ERR_get_error_func 4873 3_0_0 EXIST::FUNCTION: +ERR_get_error_data 4874 3_0_0 EXIST::FUNCTION: +ERR_get_error_all 4875 3_0_0 EXIST::FUNCTION: +ERR_peek_error_func 4876 3_0_0 EXIST::FUNCTION: +ERR_peek_error_data 4877 3_0_0 EXIST::FUNCTION: +ERR_peek_error_all 4878 3_0_0 EXIST::FUNCTION: +ERR_peek_last_error_func 4879 3_0_0 EXIST::FUNCTION: +ERR_peek_last_error_data 4880 3_0_0 EXIST::FUNCTION: +ERR_peek_last_error_all 4881 3_0_0 EXIST::FUNCTION: -- 2.34.1