Skip to content

Pointer bug in background_thread0_work() if VARIABLE_ARRAY used alloca() implementation #59

Description

@fuhsnn

Under rare conditions, VLA declarations in jemalloc might use alloca() under the hood:

/* Declare a variable-length array. */
#if __STDC_VERSION__ < 199901L || defined(__STDC_NO_VLA__)
# ifdef _MSC_VER
# include <malloc.h>
# define alloca _alloca
# else
# ifdef JEMALLOC_HAS_ALLOCA_H
# include <alloca.h>
# else
# include <stdlib.h>
# endif
# endif
# define VARIABLE_ARRAY_UNSAFE(type, name, count) \
type *name = alloca(sizeof(type) * (count))
#else
# define VARIABLE_ARRAY_UNSAFE(type, name, count) type name[(count)]
#endif

This particular VLA in background_thread0_work(),

VARIABLE_ARRAY(bool, created_threads, const_max_background_threads);

has its address taken here:
if (check_background_thread_creation(tsd,
const_max_background_threads, &n_created,
(bool *)&created_threads)) {
continue;
}

With alloca() the variable is actually a pointer, so &created_threads wouldn't be the intended array space but instead the address of the pointer variable itself (bool **), which leads to test failing, hanging or segfault.

Only found because I was disabling VLA in my C compiler for fun, but can be reproduced on GCC/Clang by forcing alloca:

diff --git a/src/background_thread.c b/src/background_thread.c
index 2eb08dd..96ef481 100644
--- a/src/background_thread.c
+++ b/src/background_thread.c
@@ -434,7 +434,7 @@ background_thread0_work(tsd_t *tsd) {
 	 */
 	const size_t const_max_background_threads = max_background_threads;
 	assert(const_max_background_threads > 0);
-	VARIABLE_ARRAY(bool, created_threads, const_max_background_threads);
+	bool *created_threads = __builtin_alloca(sizeof(bool) * const_max_background_threads);
 	unsigned i;
 	for (i = 1; i < const_max_background_threads; i++) {
 		created_threads[i] = false;

Will file a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions