Hello!
I need to compile stunnel using VC for Windows x64 platform. I know that I can use MinGW/gcc and it will work, but VC used to build all other libraries and I want to simplify assembly process.
I am try build stunnel by VC for Windows x64 platform and it builds fine but after start, stunnel crashed in VC runtime after calling setjmp function in client.c :
/* try to process the request */
err=setjmp(c->err);
I did some researches of the reason of a problem and found the following comment in prototypes.h:
jmp_buf err; /* exception handler needs to be 16-byte aligned on Itanium */
The memory for CLI struct allocated by str_alloc_detached function (jmp_buf uded in definition CLI struct), but jmp_buf for AMD64/x64 must be 16-byte aligned to save state of SSE registers. Function calloc used for memory allocation in str_alloc_detached function and sometimes it return pointers not aligned to 16-byte boundary what causes a problem.
I create dummy patch to workaround the problem but am think the best solution in that case is to use malloc instead calloc function (as described in some articles it’s always 16-byte aligned on AMD64 VC builds).
Can you suggest some solutions to this problem?
prototypes.h
@@ -404,6 +404,10 @@ typedef struct {
uint64_t sock_bytes, ssl_bytes; /* bytes written to socket and SSL */
s_poll_set *fds; /* file descriptors */
uintptr_t redirect; /* redirect to another destination after failed auth */
+ /* New member added by Zuz to work around setjmp alignment issues */
+#if defined(_MSC_VER) && defined(_WIN64)
+ void *cli_struct_free_ptr; /* Ptr to unaligned address for this struct */
+#endif
} CLI;
client.c
@@ -76,8 +76,14 @@ NOEXPORT void reset(SOCKET, char *);
CLI *alloc_client_session(SERVICE_OPTIONS *opt, SOCKET rfd, SOCKET wfd) {
static unsigned long long seq=0;
CLI *c;
-
+#if defined(_MSC_VER) && defined(_WIN64)
+ #define CLI_STRUCT_ALIGNMENT 15
+ void *cli_ptr_unaligned = str_alloc_detached(sizeof(CLI) + CLI_STRUCT_ALIGNMENT);
+ c = (CLI *)(((uintptr_t)cli_ptr_unaligned+CLI_STRUCT_ALIGNMENT) & ~ (uintptr_t)0x0F);
+ c->cli_struct_free_ptr = cli_ptr_unaligned;
+#else
c=str_alloc_detached(sizeof(CLI));
+#endif
c->opt=opt;
c->local_rfd.fd=rfd;
c->local_wfd.fd=wfd;
@@ -117,7 +123,13 @@ void client_main(CLI *c) {
* -> spawn a local program instead of stdio */
for(;;) {
SERVICE_OPTIONS *opt=c->opt;
+#if defined(_MSC_VER) && defined(_WIN64)
+ void *cli_ptr_unaligned = c->cli_struct_free_ptr;
+#endif
memset(c, 0, sizeof(CLI)); /* connect_local needs clean c */
+#if defined(_MSC_VER) && defined(_WIN64)
+ c->cli_struct_free_ptr = cli_ptr_unaligned;
+#endif
c->opt=opt;
if(!setjmp(c->err))
c->local_rfd.fd=c->local_wfd.fd=connect_local(c);
@@ -136,7 +148,11 @@ void client_main(CLI *c) {
}
} else
client_run(c);
- str_free(c);
+#if defined(_MSC_VER) && defined(_WIN64)
+ str_free(c->cli_struct_free_ptr);
+#else
+ str_free(c);
+#endif
}
#ifdef __GNUC__
--
Yuris W. Auzins