| /* 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; |
| } |