1/* Reproduces bug 321960 (based on test from Daniel Stodden).
2   At least on Ubuntu 12 and 13, causes invalid write errors
3   in __yell or the memset call (due to some part of the main
4   stack being marked as not addressable in memcheck).
5   Bug seems extremely sensitive to initial conditions:
6   Depending on the size of the env, bug is triggered or not.
7   Also, a high nr of threads in thr[] is needed to get
8   the problem. */
9#include <pthread.h>
10#include <alloca.h>
11#include <assert.h>
12#include <string.h>
13#include <stdio.h>
14#include <unistd.h>
15#include <stdlib.h>
16
17void *
18nop(void *nil)
19{
20    return NULL;
21}
22
23void
24__yell(void)
25{
26    char buf[256];
27    memset(buf, 0, sizeof(buf));
28}
29
30/* Without argument, executes once.
31   Otherwise first arg indicates nr of times the process will exec
32   itself, each time increasing the size of the environment
33   by about 50 characters. */
34int main(int argc, char **argv, char** envp)
35{
36    pthread_t thr[50];
37    int i, err;
38
39    for (i = 0; i < sizeof(thr) / sizeof(*thr); i++) {
40        err = pthread_create(&thr[i], NULL, nop, NULL);
41        assert(!err);
42    }
43
44    alloca(4096);
45    __yell();
46
47    for (i = 0; i < sizeof(thr) / sizeof(*thr); i++)
48        pthread_join(thr[i], NULL);
49
50    if ( argc == 2 && atoi(argv[1]) > 0) {
51       /* exec ourselves with some more env */
52       char** new_env;
53       char more_env[100];
54       char n[10];
55       int j;
56
57       sprintf(more_env, "N%d=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",  atoi(argv[1]));
58       for (j = 0; envp[j]; j++)
59          ;
60       new_env = malloc((j+2) * sizeof(char*));
61       assert (new_env != NULL);
62       for (i = 0; i < j; i++)
63          new_env[i] = envp[i];
64       new_env[i++] = more_env;
65       new_env[i++] = NULL;
66       assert(i == j+2);
67       sprintf (n, "%d",  atoi(argv[1]) - 1);
68       // system ("env | wc");
69       execle(argv[0], argv[0], n, (char *) NULL, new_env);
70       assert(0);
71    } else
72       return 0;
73}
74