Skip to content

Commit

Permalink
Add test file for context functions
Browse files Browse the repository at this point in the history
For now, this just tests stack alignment in a context's entry point

This test shows a problem when building on i386 with `-msse2`, where the
compiler is allowed use some instructions that move data in and out of
the xmm0-7 registers, requiring them to be aligned on 16-byte
boundaries. Because the compiler will generally assume the stack is
correctly aligned on entering a function, the misalignment will
propagate through the stack until something uses an instruction that
requires 16-byte alignment, and we get a segmentation fault.

The misalignment happens because the stack is heap-allocated (and the
heap allocator provides a properly aligned pointer), but we push the
argument for the async task onto the stack as we call it, leaving the
stack 4 bytes below proper alignment.

The test is equally valid on x86_64, but the stack alignment is correct
there - nothing is pushed onto the stack prior to calling the task
function, as it's passed in a register.
  • Loading branch information
peadar committed Aug 18, 2023
1 parent 5af90f0 commit 0254de3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion unittest/libmariadb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
${CC_SOURCE_DIR}/unittest/libmariadb)
ADD_DEFINITIONS(-DLIBMARIADB)

SET(API_TESTS "conc336" "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2")
SET(API_TESTS "conc336" "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2" "context")
IF(WITH_DYNCOL)
SET(API_TESTS ${API_TESTS} "dyncol")
ENDIF()
Expand Down
44 changes: 44 additions & 0 deletions unittest/libmariadb/context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Tests for ma_context functions.
*/

#include "my_test.h"
#include "mysql.h"
#include "ma_context.h"
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>

/*
* Ensures the context system aligns the stack correctly for i386 and x86_64
*/
void async_task(__attribute__((unused)) void *v) {
#if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
/*
* The compiler assumes the stack is correctly aligned on a 16-byte
* boundary on entry to the function (actually, with a return address
* popped on top of the aligned address). Creating an object with a
* max_align_t type should also be aligned at that boundary, so we should
* be able to use movaps to move the first 128 bits into xmm0.
*/
union {
max_align_t aligned;
uint64_t data[2];
} aligned;
__asm__("movaps %0, %%xmm0" : : "m" (aligned.data) : "xmm0" );
#endif
}

static int test_stack_align() {
struct my_context ctx;
my_context_init(&ctx, 65536);
my_context_spawn(&ctx, async_task, &ctx);
my_context_destroy(&ctx);
return 0;
}

int main()
{
plan(1);
ok( test_stack_align() == 0, "stack alignment check" );
}

0 comments on commit 0254de3

Please sign in to comment.