/* Reproduces bug 321960 (based on test from Daniel Stodden). At least on Ubuntu 12 and 13, causes invalid write errors in __yell or the memset call (due to some part of the main stack being marked as not addressable in memcheck). Bug seems extremely sensitive to initial conditions: Depending on the size of the env, bug is triggered or not. Also, a high nr of threads in thr[] is needed to get the problem. */ #include <pthread.h> #include <alloca.h> #include <assert.h> #include <string.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> void * nop(void *nil) { return NULL; } void __yell(void) { char buf[256]; memset(buf, 0, sizeof(buf)); } /* Without argument, executes once. Otherwise first arg indicates nr of times the process will exec itself, each time increasing the size of the environment by about 50 characters. */ int main(int argc, char **argv, char** envp) { pthread_t thr[50]; int i, err; for (i = 0; i < sizeof(thr) / sizeof(*thr); i++) { err = pthread_create(&thr[i], NULL, nop, NULL); assert(!err); } alloca(4096); __yell(); for (i = 0; i < sizeof(thr) / sizeof(*thr); i++) pthread_join(thr[i], NULL); if ( argc == 2 && atoi(argv[1]) > 0) { /* exec ourselves with some more env */ char** new_env; char more_env[100]; char n[10]; int j; sprintf(more_env, "N%d=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", atoi(argv[1])); for (j = 0; envp[j]; j++) ; new_env = malloc((j+2) * sizeof(char*)); assert (new_env != NULL); for (i = 0; i < j; i++) new_env[i] = envp[i]; new_env[i++] = more_env; new_env[i++] = NULL; assert(i == j+2); sprintf (n, "%d", atoi(argv[1]) - 1); // system ("env | wc"); execle(argv[0], argv[0], n, NULL, new_env); assert(0); } else return 0; }