Modernise the ERR functionality further (new functions and deprecations)
authorRichard Levitte <levitte@openssl.org>
Wed, 4 Sep 2019 20:04:08 +0000 (22:04 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 12 Sep 2019 15:59:52 +0000 (17:59 +0200)
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 <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9756)

crypto/err/err.c
doc/man3/ERR_get_error.pod
include/openssl/err.h
test/errtest.c
test/evp_test.c
util/libcrypto.num

index 25ab13509ce0114f659386dd437bd5d825d52402..deaa579090bf5cc02db7ac032454ce628961fc3b 100644 (file)
@@ -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)
 {
index c3fab39cb9579325a9f859cff96e953e06b98e93..045ef210a26ef8e7de3e099c4076703cf8e41897 100644 (file)
@@ -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<ERR_error_string(3)> 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<file> and *B<line>, unless these are B<NULL>.
 
+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<func>,
+unless it is B<NULL>.
+
+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<data> and *B<flags>, unless these are B<NULL>.
+*B<data> contains a string if *B<flags>&B<ERR_TXT_STRING> 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<data>
-and *B<flags>, unless these are B<NULL>. *B<data> contains a string
-if *B<flags>&B<ERR_TXT_STRING> 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<MUST NOT> free the *B<data> 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<ERR_error_string(3)>,
 L<ERR_GET_LIB(3)>
 
+=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.
index 0da66092b4d68b16d00a25a8b64e60c7f308addb..2b4a71a9a4595ee58e1e505e588c92f3ece069e0 100644 (file)
@@ -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);
index ffe6532240dba2d982a6ee5ebddf1db9dfc74f9e..179c338c4503f0d2ecd8f30e6c6ae81e3dd468dc 100644 (file)
@@ -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)
index b1194d2bc9aba3f4001078974416c50e3cb4ea48..0b5fd5dae3c968d089f44bb177f6f1f413304528 100644 (file)
@@ -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);
index 07469a1f26b29480a6019656419be87b37425bc5..cadc4a57baaa830aeffb0a1655ccf37bc0615a65 100644 (file)
@@ -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: