diff --git a/src/include.am b/src/include.am index 5948c50fa..78abea93a 100644 --- a/src/include.am +++ b/src/include.am @@ -293,7 +293,8 @@ endif !BUILD_FIPS_RAND src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_port.c \ - wolfcrypt/src/error.c + wolfcrypt/src/error.c \ + wolfcrypt/src/debug.c if !BUILD_FIPS_RAND src_libwolfssl_la_SOURCES += \ diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 7a8115a43..79e655aae 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -49,7 +49,12 @@ void file_test(const char* file, byte* hash); #endif #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) -void simple_test(func_args*); + +#ifdef HAVE_STACK_SIZE +static THREAD_RETURN simple_test(func_args*); +#else +static void simple_test(func_args*); +#endif enum { NUMARGS = 3 @@ -72,6 +77,12 @@ char* myoptarg = NULL; #endif /* NO_TESTSUITE_MAIN_DRIVER */ +#ifdef HAVE_STACK_SIZE +static void *echoclient_test_wrapper(void* args) { + echoclient_test(args); + return (void *)0; +} +#endif int testsuite_test(int argc, char** argv) { @@ -90,6 +101,9 @@ int testsuite_test(int argc, char** argv) int len = 8; int num = 6; #endif +#ifdef HAVE_STACK_SIZE + void *serverThreadStackContext = 0; +#endif #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { @@ -121,16 +135,27 @@ int testsuite_test(int argc, char** argv) #ifndef NO_CRYPT_TEST /* wc_ test */ - wolfcrypt_test(&server_args); + #ifdef HAVE_STACK_SIZE + StackSizeCheck(&server_args, wolfcrypt_test); + #else + wolfcrypt_test(&server_args); + #endif if (server_args.return_code != 0) return server_args.return_code; #endif /* Simple wolfSSL client server test */ - simple_test(&server_args); + #ifdef HAVE_STACK_SIZE + StackSizeCheck(&server_args, (THREAD_RETURN (*)(void *))simple_test); + #else + simple_test(&server_args); + #endif if (server_args.return_code != 0) return server_args.return_code; - /* Echo input wolfSSL client server test */ - start_thread(echoserver_test, &server_args, &serverThread); + #ifdef HAVE_STACK_SIZE + StackSizeCheck_launch(&server_args, echoserver_test, &serverThread, &serverThreadStackContext); + #else + start_thread(echoserver_test, &server_args, &serverThread); + #endif wait_tcp_ready(&server_args); { func_args echo_args; @@ -160,7 +185,13 @@ int testsuite_test(int argc, char** argv) echo_args.signal = server_args.signal; /* make sure OK */ + + #ifdef HAVE_STACK_SIZE + fputs("echoclient_test #1: ", stdout); + StackSizeCheck(&echo_args, echoclient_test_wrapper); + #else echoclient_test(&echo_args); + #endif if (echo_args.return_code != 0) return echo_args.return_code; #ifdef WOLFSSL_DTLS @@ -170,9 +201,19 @@ int testsuite_test(int argc, char** argv) echo_args.argc = 2; strcpy(echo_args.argv[1], "quit"); + #ifdef HAVE_STACK_SIZE + fputs("echoclient_test #2: ", stdout); + StackSizeCheck(&echo_args, echoclient_test_wrapper); + #else echoclient_test(&echo_args); + #endif if (echo_args.return_code != 0) return echo_args.return_code; - join_thread(serverThread); + #ifdef HAVE_STACK_SIZE + fputs("reaping echoserver_test: ", stdout); + StackSizeCheck_reap(serverThread, serverThreadStackContext); + #else + join_thread(serverThread); + #endif if (server_args.return_code != 0) return server_args.return_code; } @@ -223,7 +264,11 @@ int testsuite_test(int argc, char** argv) } #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) -void simple_test(func_args* args) +#ifdef HAVE_STACK_SIZE +static THREAD_RETURN simple_test(func_args* args) +#else +static void simple_test(func_args* args) +#endif { THREAD_TYPE serverThread; @@ -273,10 +318,17 @@ void simple_test(func_args* args) client_test(&cliArgs); if (cliArgs.return_code != 0) { args->return_code = cliArgs.return_code; + #ifdef HAVE_STACK_SIZE + return (void *)0; + #else return; + #endif } join_thread(serverThread); if (svrArgs.return_code != 0) args->return_code = svrArgs.return_code; +#ifdef HAVE_STACK_SIZE + return (void *)0; +#endif } #endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ diff --git a/wolfcrypt/src/debug.c b/wolfcrypt/src/debug.c new file mode 100644 index 000000000..60adae5a4 --- /dev/null +++ b/wolfcrypt/src/debug.c @@ -0,0 +1,42 @@ +/* debug.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include +#include +#include +#include + +#ifdef HAVE_STACK_SIZE_VERBOSE +WOLFSSL_API THREAD_LS_T unsigned char *StackSizeCheck_myStack = NULL; +WOLFSSL_API THREAD_LS_T size_t StackSizeCheck_stackSize = 0; +WOLFSSL_API THREAD_LS_T size_t StackSizeCheck_stackSizeHWM = 0; +WOLFSSL_API THREAD_LS_T size_t *StackSizeCheck_stackSizeHWM_ptr = 0; +WOLFSSL_API THREAD_LS_T void *StackSizeCheck_stackOffsetPointer = 0; +#endif diff --git a/wolfssl/test.h b/wolfssl/test.h index af50d3a34..8e2e93ef6 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -2002,6 +2002,16 @@ static WC_INLINE void CaCb(unsigned char* der, int sz, int type) typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); #define STACK_CHECK_VAL 0x01 +struct stack_size_debug_context { + unsigned char *myStack; + size_t stackSize; +#ifdef HAVE_STACK_SIZE_VERBOSE + size_t *stackSizeHWM_ptr; + thread_func fn; + void *args; +#endif +}; + #ifdef HAVE_STACK_SIZE_VERBOSE /* per-subtest stack high water mark tracking. @@ -2011,21 +2021,13 @@ typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); * CFLAGS='-g -DHAVE_STACK_SIZE_VERBOSE' ./configure --enable-stacksize [...] */ -static THREAD_LS_T unsigned char *StackSizeCheck_myStack = NULL; -static THREAD_LS_T size_t StackSizeCheck_stackSize = 0; -static THREAD_LS_T size_t StackSizeCheck_stackSizeHWM = 0; -static THREAD_LS_T size_t *StackSizeCheck_stackSizeHWM_ptr = 0; -static THREAD_LS_T void *StackSizeCheck_stackOffsetPointer = 0; +extern THREAD_LS_T unsigned char *StackSizeCheck_myStack; +extern THREAD_LS_T size_t StackSizeCheck_stackSize; +extern THREAD_LS_T size_t StackSizeCheck_stackSizeHWM; +extern THREAD_LS_T size_t *StackSizeCheck_stackSizeHWM_ptr; +extern THREAD_LS_T void *StackSizeCheck_stackOffsetPointer; -struct debug_stack_size_verbose_shim_args { - unsigned char *myStack; - size_t stackSize; - size_t *stackSizeHWM_ptr; - thread_func fn; - void *args; -}; - -static void *debug_stack_size_verbose_shim(struct debug_stack_size_verbose_shim_args *shim_args) { +static void *debug_stack_size_verbose_shim(struct stack_size_debug_context *shim_args) { StackSizeCheck_myStack = shim_args->myStack; StackSizeCheck_stackSize = shim_args->stackSize; StackSizeCheck_stackSizeHWM_ptr = shim_args->stackSizeHWM_ptr; @@ -2140,7 +2142,7 @@ static WC_INLINE int StackSizeCheck(func_args* args, thread_func tf) #ifdef HAVE_STACK_SIZE_VERBOSE StackSizeCheck_stackSizeHWM = 0; { - struct debug_stack_size_verbose_shim_args shim_args; + struct stack_size_debug_context shim_args; shim_args.myStack = myStack; shim_args.stackSize = stackSize; shim_args.stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; @@ -2179,6 +2181,88 @@ static WC_INLINE int StackSizeCheck(func_args* args, thread_func tf) return (int)((size_t)status); } +static WC_INLINE int StackSizeCheck_launch(func_args* args, thread_func tf, pthread_t *threadId, void **stack_context) +{ + int ret; + unsigned char* myStack = NULL; + size_t stackSize = 1024*1024; + pthread_attr_t myAttr; + +#ifdef PTHREAD_STACK_MIN + if (stackSize < PTHREAD_STACK_MIN) + stackSize = PTHREAD_STACK_MIN; +#endif + + struct stack_size_debug_context *shim_args = (struct stack_size_debug_context *)malloc(sizeof *shim_args); + if (! shim_args) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); + if (ret != 0 || myStack == NULL) + err_sys_with_errno("posix_memalign failed\n"); + + XMEMSET(myStack, STACK_CHECK_VAL, stackSize); + + ret = pthread_attr_init(&myAttr); + if (ret != 0) + err_sys("attr_init failed"); + + ret = pthread_attr_setstack(&myAttr, myStack, stackSize); + if (ret != 0) + err_sys("attr_setstackaddr failed"); + + shim_args->myStack = myStack; + shim_args->stackSize = stackSize; +#ifdef HAVE_STACK_SIZE_VERBOSE + shim_args->stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; + shim_args->fn = tf; + shim_args->args = args; + ret = pthread_create(threadId, &myAttr, (thread_func)debug_stack_size_verbose_shim, (void *)shim_args); +#else + ret = pthread_create(threadId, &myAttr, tf, args); +#endif + if (ret != 0) { + fprintf(stderr,"pthread_create failed: %s",strerror(ret)); + exit(EXIT_FAILURE); + } + + *stack_context = (void *)shim_args; + + return 0; +} + +static WC_INLINE int StackSizeCheck_reap(pthread_t threadId, void *stack_context) +{ + struct stack_size_debug_context *shim_args = (struct stack_size_debug_context *)stack_context; + size_t i; + void *status; + int ret = pthread_join(threadId, &status); + if (ret != 0) + err_sys("pthread_join failed"); + + for (i = 0; i < shim_args->stackSize; i++) { + if (shim_args->myStack[i] != STACK_CHECK_VAL) { + break; + } + } + + free(shim_args->myStack); +#ifdef HAVE_STACK_SIZE_VERBOSE + printf("stack used = %lu\n", *shim_args->stackSizeHWM_ptr > (shim_args->stackSize - i) ? *shim_args->stackSizeHWM_ptr : (shim_args->stackSize - i)); +#else + { + size_t used = shim_args->stackSize - i; + printf("stack used = %lu\n", used); + } +#endif + free(shim_args); + + return (int)((size_t)status); +} + + #endif /* HAVE_STACK_SIZE */ #ifndef STACK_SIZE_CHECKPOINT