diff --git a/configure.ac b/configure.ac index 970cc5081..72cbde789 100644 --- a/configure.ac +++ b/configure.ac @@ -217,11 +217,17 @@ AC_ARG_ENABLE([debug-trace-errcodes], [ ENABLED_DEBUG_TRACE_ERRCODES=no ] ) -if test "$ENABLED_DEBUG_TRACE_ERRCODES" = "yes" +if test "$ENABLED_DEBUG_TRACE_ERRCODES" != "no" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DEBUG_TRACE_ERROR_CODES" fi +if test "$ENABLED_DEBUG_TRACE_ERRCODES" = "backtrace" +then + AM_CFLAGS="$AM_CFLAGS -g -funwind-tables -DWOLFSSL_DEBUG_BACKTRACE_ERROR_CODES" + AM_LDFLAGS="$AM_LDFLAGS -lbacktrace" +fi + # Start without certificates enabled and enable if a certificate algorithm is # enabled ENABLED_CERTS="no" @@ -9981,7 +9987,7 @@ echo "" >> $OPTION_FILE echo "#endif /* WOLFSSL_OPTIONS_H */" >> $OPTION_FILE echo "" >> $OPTION_FILE -if test "$ENABLED_DEBUG_TRACE_ERRCODES" = "yes" +if test "$ENABLED_DEBUG_TRACE_ERRCODES" != "no" then support/gen-debug-trace-error-codes.sh || AC_MSG_ERROR([Header generation for debug-trace-errcodes failed.]) fi diff --git a/src/internal.c b/src/internal.c index 16230dbb7..219465a1d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -20653,7 +20653,11 @@ static void LogAlert(int type) typeStr = AlertTypeToString(type); if (typeStr != NULL) { char buff[60]; - XSNPRINTF(buff, sizeof(buff), "Alert type: %s", typeStr); + if (XSNPRINTF(buff, sizeof(buff), "Alert type: %s", typeStr) + >= (int)sizeof(buff)) + { + buff[sizeof(buff) - 1] = 0; + } WOLFSSL_MSG(buff); } #else diff --git a/src/pk.c b/src/pk.c index 8b8dd9773..34e272784 100644 --- a/src/pk.c +++ b/src/pk.c @@ -4691,7 +4691,9 @@ int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) mp_clear(t); #ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (rsa != NULL) { + XFREE(tmp, rsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + } #endif return ret; diff --git a/support/gen-debug-trace-error-codes.sh b/support/gen-debug-trace-error-codes.sh index 1aba489d9..01f32faa8 100755 --- a/support/gen-debug-trace-error-codes.sh +++ b/support/gen-debug-trace-error-codes.sh @@ -12,7 +12,12 @@ BEGIN { print("#undef WOLFSSL_DEBUG_TRACE_ERROR_CODES_H") >> "wolfssl/debug-untrace-error-codes.h"; } { - if (match($0, "^[[:space:]]+([A-Z][A-Z0-9_]+)[[:space:]]*=[[:space:]]*(-[0-9]+)[,[:space:]]", errcode_a)) { + if (match($0, "^[[:space:]]+([A-Z][A-Z0-9_]+)[[:space:]]*=[[:space:]]*(-[0-9]+)[,[:space:]]")) { + + # for mawkward compatibility -- gawk allows errcode_a as the 3rd arg to match(). + gsub("^[[:space:]]+", "", $0); + split($0, errcode_a, "[[:space:]=,]+"); + if ((errcode_a[1] == "MIN_CODE_E") || (errcode_a[1] == "WC_LAST_E") || (errcode_a[1] == "MAX_CODE_E")) diff --git a/tests/api.c b/tests/api.c index 04858591d..bb0877d10 100644 --- a/tests/api.c +++ b/tests/api.c @@ -78089,9 +78089,11 @@ static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer, (void)encInfo; /* not used in this test */ #ifdef DEBUG_WOLFSSL - fprintf(stderr, "%s (%d): Loading PEM %s (len %d) to DER (len %d)\n", - (ret == 0) ? "Success" : "Failure", ret, privKeyFile, (int)key_sz, - (*pDer)->length); + if (*pDer != NULL) { + fprintf(stderr, "%s (%d): Loading PEM %s (len %d) to DER (len %d)\n", + (ret == 0) ? "Success" : "Failure", ret, privKeyFile, + (int)key_sz, (*pDer)->length); + } #endif return ret; diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 0bb532237..9078c0bf6 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1663,18 +1663,6 @@ static const char* bench_result_words3[][5] = { const char *desc_extra); #endif -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ - !defined(HAVE_STACK_SIZE) -#ifdef __cplusplus - extern "C" { -#endif - WOLFSSL_API int wolfSSL_Debugging_ON(void); - WOLFSSL_API void wolfSSL_Debugging_OFF(void); -#ifdef __cplusplus - } /* extern "C" */ -#endif -#endif - #if !defined(WC_NO_RNG) && \ ((!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) \ || !defined(NO_DH) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) \ diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index f28a71ef7..9568f1c6a 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -471,26 +471,48 @@ void WOLFSSL_BUFFER(const byte* buffer, word32 length) while (buflen > 0) { int bufidx = 0; - XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "\t"); + if (XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "\t") + >= (int)sizeof(line) - bufidx) + { + goto errout; + } bufidx++; for (i = 0; i < LINE_LEN; i++) { if (i < buflen) { - XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "%02x ", buffer[i]); + if (XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "%02x ", + buffer[i]) >= (int)sizeof(line) - bufidx) + { + goto errout; + } } else { - XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, " "); + if (XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, " ") + >= (int)sizeof(line) - bufidx) + { + goto errout; + } } bufidx += 3; } - XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "| "); + if (XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "| ") + >= (int)sizeof(line) - bufidx) + { + goto errout; + } bufidx++; for (i = 0; i < LINE_LEN; i++) { if (i < buflen) { - XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, - "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.'); + if (XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, + "%c", 31 < buffer[i] && buffer[i] < 127 + ? buffer[i] + : '.') + >= (int)sizeof(line) - bufidx) + { + goto errout; + } bufidx++; } } @@ -499,6 +521,12 @@ void WOLFSSL_BUFFER(const byte* buffer, word32 length) buffer += LINE_LEN; buflen -= LINE_LEN; } + + return; + +errout: + + wolfssl_log(INFO_LOG, NULL, 0, "\t[Buffer error while rendering]"); } #undef WOLFSSL_ENTER /* undo WOLFSSL_DEBUG_CODEPOINTS wrapper */ @@ -506,7 +534,11 @@ void WOLFSSL_ENTER(const char* msg) { if (loggingEnabled) { char buffer[WOLFSSL_MAX_ERROR_SZ]; - XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg); + if (XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg) + >= (int)sizeof(buffer)) + { + buffer[sizeof(buffer) - 1] = 0; + } wolfssl_log(ENTER_LOG, NULL, 0, buffer); } } @@ -516,7 +548,11 @@ void WOLFSSL_ENTER2(const char *file, int line, const char* msg) { if (loggingEnabled) { char buffer[WOLFSSL_MAX_ERROR_SZ]; - XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg); + if (XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg) + >= (int)sizeof(buffer)) + { + buffer[sizeof(buffer) - 1] = 0; + } wolfssl_log(ENTER_LOG, file, line, buffer); } } @@ -527,8 +563,12 @@ void WOLFSSL_LEAVE(const char* msg, int ret) { if (loggingEnabled) { char buffer[WOLFSSL_MAX_ERROR_SZ]; - XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", - msg, ret); + if (XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", + msg, ret) + >= (int)sizeof(buffer)) + { + buffer[sizeof(buffer) - 1] = 0; + } wolfssl_log(LEAVE_LOG, NULL, 0, buffer); } } @@ -538,8 +578,12 @@ void WOLFSSL_LEAVE2(const char *file, int line, const char* msg, int ret) { if (loggingEnabled) { char buffer[WOLFSSL_MAX_ERROR_SZ]; - XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", - msg, ret); + if (XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", + msg, ret) + >= (int)sizeof(buffer)) + { + buffer[sizeof(buffer) - 1] = 0; + } wolfssl_log(LEAVE_LOG, file, line, buffer); } } @@ -1674,3 +1718,135 @@ void WOLFSSL_ERROR_MSG(const char* msg) } #endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES + +#include + +#if BACKTRACE_SUPPORTED != 1 + #error WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES is defined but BACKTRACE_SUPPORTED is 0. +#endif + +#if !defined(WOLFSSL_MUTEX_INITIALIZER) && defined(WOLFSSL_NO_ATOMICS) + #error WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES requires WOLFSSL_MUTEX_INITIALIZER or wolfSSL_Atomic_Ints. +#endif + +#include + +static int backtrace_callback(void *data, uintptr_t pc, const char *filename, + int lineno, const char *function) +{ + if (function == NULL) + return 0; + /* the first callback is for the call to wc_print_backtrace() -- skip it. */ + if (*(int *)data == 0) { + *(int *)data = 1; + return 0; + } +#ifdef NO_STDIO_FILESYSTEM + printf(" #%d %p in %s %s:%d\n", (*(int *)data)++, (void *)pc, + function, filename, lineno); +#else + fprintf(stderr, " #%d %p in %s %s:%d\n", (*(int *)data)++, (void *)pc, + function, filename, lineno); +#endif + return 0; +} + +static void backtrace_error(void *data, const char *msg, int errnum) { + (void)data; +#ifdef NO_STDIO_FILESYSTEM + printf("ERR TRACE: error %d while backtracing: %s", errnum, msg); +#else + fprintf(stderr, "ERR TRACE: error %d while backtracing: %s", errnum, msg); +#endif +} + +static void backtrace_creation_error(void *data, const char *msg, int errnum) { + (void)data; +#ifdef NO_STDIO_FILESYSTEM + printf("ERR TRACE: internal error %d " + "while initializing backtrace facility: %s", errnum, msg); + printf("ERR TRACE: internal error " + "while initializing backtrace facility"); +#else + fprintf(stderr, "ERR TRACE: internal error %d " + "while initializing backtrace facility: %s", errnum, msg); +#endif +} + +static int backtrace_init(struct backtrace_state **backtrace_state) { +#ifdef WOLFSSL_MUTEX_INITIALIZER + static wolfSSL_Mutex backtrace_create_state_mutex = + WOLFSSL_MUTEX_INITIALIZER(backtrace_create_state_mutex); + if (wc_LockMutex(&backtrace_create_state_mutex) != 0) + return -1; +#elif defined(WOLFSSL_ATOMIC_OPS) + static wolfSSL_Atomic_Int init_count = 0; + if (wolfSSL_Atomic_Int_FetchAdd(&init_count, 1) != 1) + return -1; +#endif + if (*backtrace_state == NULL) { + /* passing a NULL filename to backtrace_create_state() tells + * libbacktrace to use a target-specific strategy to determine the + * executable. "libbacktrace supports ELF, PE/COFF, Mach-O, and XCOFF + * executables with DWARF debugging information. In other words, it + * supports GNU/Linux, *BSD, macOS, Windows, and AIX." + */ + *backtrace_state = backtrace_create_state( + NULL, 0, backtrace_creation_error, NULL); + } +#ifdef WOLFSSL_MUTEX_INITIALIZER + wc_UnLockMutex(&backtrace_create_state_mutex); +#endif + if (*backtrace_state == NULL) + return -1; + return 0; +} + +void wc_backtrace_render(void) { + static wolfSSL_Mutex backtrace_mutex + WOLFSSL_MUTEX_INITIALIZER_CLAUSE(backtrace_mutex); + static struct backtrace_state *backtrace_state = NULL; + int depth = 0; + +#ifndef WOLFSSL_MUTEX_INITIALIZER + static wolfSSL_Atomic_Int init_count = 0; + if (init_count != 1) { + int cur_init_count = wolfSSL_Atomic_Int_FetchSub(&init_count, 1); + if (cur_init_count != 0) { + (void)wolfSSL_Atomic_Int_FetchAdd(&init_count, 1); + return; + } + if (wc_InitMutex(&backtrace_mutex) != 0) + return; + /* set init_count to 1, race-free: (-1) - (0-2) = 1 */ + (void)wolfSSL_Atomic_Int_FetchSub(&init_count, cur_init_count - 2); + } +#endif + + /* backtrace_state can't be shared between threads even when + * BACKTRACE_SUPPORTS_THREADS == 1, so we serialize the render op. this + * helpfully mutexes the initialization too. + */ + if (wc_LockMutex(&backtrace_mutex) != 0) + return; + + if (backtrace_state == NULL) { + if (backtrace_init(&backtrace_state) < 0) { + wc_UnLockMutex(&backtrace_mutex); + return; + } + } + + /* note that the optimizer can produce misleading backtraces, even with + * -funwind-tables. in contrast, the macro-generated "ERR TRACE" message + * from WC_ERR_TRACE() always accurately identifies the error code point. + */ + backtrace_full(backtrace_state, 0, backtrace_callback, backtrace_error, + (void *)&depth); + + wc_UnLockMutex(&backtrace_mutex); +} + +#endif /* WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES */ diff --git a/wolfcrypt/src/wc_kyber.c b/wolfcrypt/src/wc_kyber.c index ffa37d84c..a32d0916b 100644 --- a/wolfcrypt/src/wc_kyber.c +++ b/wolfcrypt/src/wc_kyber.c @@ -286,7 +286,9 @@ int wc_KyberKey_MakeKeyWithRandom(KyberKey* key, const unsigned char* rand, } /* Free dynamic memory allocated in function. */ - XFREE(a, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key != NULL) { + XFREE(a, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return ret; } @@ -890,7 +892,9 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, #ifndef USE_INTEL_SPEEDUP /* Dispose of dynamic memory allocated in function. */ - XFREE(cmp, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key != NULL) { + XFREE(cmp, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } #endif return ret; diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 8fb71b3c6..413868ebb 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -298,17 +298,31 @@ WOLFSSL_ABI WOLFSSL_API const char* wc_GetErrorString(int error); #undef WOLFSSL_DEBUG_TRACE_ERROR_CODES #endif #ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES + extern void wc_backtrace_render(void); #define WC_NO_ERR_TRACE(label) (CONST_NUM_ERR_ ## label) + #ifndef WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE + #ifdef WOLFSSL_DEBUG_BACKTRACE_ERROR_CODES + #define WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE wc_backtrace_render() + #else + #define WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE (void)0 + #endif + #endif #ifndef WC_ERR_TRACE #ifdef NO_STDIO_FILESYSTEM #define WC_ERR_TRACE(label) \ - ( printf("ERR TRACE: %s L %d " #label " (%d)\n", \ - __FILE__, __LINE__, label), label) + ( printf("ERR TRACE: %s L %d %s (%d)\n", \ + __FILE__, __LINE__, #label, label), \ + WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE, \ + label \ + ) #else #define WC_ERR_TRACE(label) \ ( fprintf(stderr, \ - "ERR TRACE: %s L %d " #label " (%d)\n", \ - __FILE__, __LINE__, label), label) + "ERR TRACE: %s L %d %s (%d)\n", \ + __FILE__, __LINE__, #label, label), \ + WOLFSSL_DEBUG_BACKTRACE_RENDER_CLAUSE, \ + label \ + ) #endif #endif #include