Home | History | Annotate | Download | only in tests
      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 
     17 void *
     18 nop(void *nil)
     19 {
     20     return NULL;
     21 }
     22 
     23 void
     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. */
     34 int 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, NULL, new_env);
     70        assert(0);
     71     } else
     72        return 0;
     73 }
     74