Home | History | Annotate | Download | only in tests
      1 
      2 /* This test case was originally written by Nicholas Nethercote. */
      3 
      4 // This test covers all the different sources of values, both defined and
      5 // undefined.  It only involves undefined condition errors.
      6 //
      7 // Nb: a stack frame is allocated when a signal is delivered.  But it
      8 // immediately get written with stuff, so there's no significant possibility
      9 // of undefined values originating there.  So we ignore it.  (On platforms
     10 // like AMD64 that have a redzone just beyond the stack pointer there is a
     11 // possibility, but it's so slim we ignore it.)
     12 
     13 #include <stdio.h>
     14 #include <assert.h>
     15 #include <stdlib.h>
     16 #include "tests/sys_mman.h"
     17 #include <unistd.h>
     18 #include "../memcheck.h"
     19 
     20 int x = 0;
     21 
     22 int main(void)
     23 {
     24    assert(1 == sizeof(char));
     25    assert(2 == sizeof(short));
     26    assert(4 == sizeof(int));
     27    assert(8 == sizeof(long long));
     28 
     29    //------------------------------------------------------------------------
     30    // Sources of undefined values
     31    //------------------------------------------------------------------------
     32 
     33    // Stack, 32-bit
     34    {
     35       volatile int undef_stack_int;
     36       fprintf(stderr, "\nUndef 1 of 8 (stack, 32 bit)\n");
     37       x += (undef_stack_int == 0x12345678 ? 10 : 21);
     38    }
     39 
     40    // Stack, 32-bit, recently modified.  Nb: we have to do the register
     41    // mucking about to make sure that the modification isn't fenced by a
     42    // store/load pair and thus not seen (see origin-not-quite.c).
     43    {
     44       volatile int undef_stack_int;
     45       register int modified_undef_stack_int;
     46       fprintf(stderr, "\nUndef 2 of 8 (stack, 32 bit)\n");
     47       modified_undef_stack_int = undef_stack_int;
     48       modified_undef_stack_int++;
     49       x += (modified_undef_stack_int == 0x1234 ? 11 : 22);
     50    }
     51 
     52    // Stack, 64-bit.  XXX: gets reported with two identical origins.
     53    {
     54       volatile long long undef_stack_longlong;
     55       fprintf(stderr, "\nUndef 3 of 8 (stack, 64 bit)\n");
     56       x += (undef_stack_longlong == 0x1234567812345678LL ? 11 : 22);
     57    }
     58 
     59    // Malloc block, uninitialised, 32-bit
     60    {
     61       int* ptr_to_undef_malloc_int = malloc(sizeof(int));
     62       int  undef_malloc_int = *ptr_to_undef_malloc_int;
     63       fprintf(stderr, "\nUndef 4 of 8 (mallocd, 32-bit)\n");
     64       x += (undef_malloc_int == 0x12345678 ? 12 : 23);
     65    }
     66 
     67    // Realloc block, uninitialised
     68    {
     69       int* ptr_to_undef_malloc_int2 = malloc(sizeof(int));
     70          // Allocate a big chunk to ensure that a new block is allocated.
     71       int* ptr_to_undef_realloc_int = realloc(ptr_to_undef_malloc_int2, 4096);
     72          // Have to move past the first 4 bytes, which were copied from the
     73          // malloc'd block.
     74       int  undef_realloc_int = *(ptr_to_undef_realloc_int+1);
     75       fprintf(stderr, "\nUndef 5 of 8 (realloc)\n");
     76       x += (undef_realloc_int == 0x12345678 ? 13 : 24);
     77    }
     78 
     79    // Custom-allocated block, non-zeroed
     80    {
     81       int  undef_custom_alloc_int;
     82       VALGRIND_MALLOCLIKE_BLOCK(&undef_custom_alloc_int, sizeof(int),
     83                                 /*rzB*/0, /*is_zeroed*/0);
     84       fprintf(stderr, "\nUndef 6 of 8 (MALLOCLIKE_BLOCK)\n");
     85       x += (undef_custom_alloc_int == 0x12345678 ? 14 : 25);
     86    }
     87 
     88    // Heap segment (brk), uninitialised
     89    // CURRENTLY DISABLED.  Why?
     90    // - On Darwin, sbrk() is implemented via vm_allocate() which always zeroes
     91    //   its allocated memory.  For a while we used use a separate .exp file
     92    //   for Darwin, but we add an extra printf on Darwin only so that it
     93    //   cannot be successfully matched on non-Darwin platforms.
     94    // - On Ubuntu 9.04 configured with --enable-only32bit, the brk symbol
     95    //   shows up as "???"
     96    // - Our current treatment of brk is suspect;  whole new pages allocated
     97    //   with brk should arguably be marked defined -- see the big comment
     98    //   above track_new_mem_brk() in memcheck/mc_main.c.
     99 //#if defined(VGO_darwin)
    100       fprintf(stderr, "\nUndef 7 of 8 (brk)\n");
    101 //      fprintf(stderr, "\n(no complaint; sbrk initialises memory on Darwin)\n");
    102       fprintf(stderr, "\n(currently disabled)\n");
    103 //#else
    104 //   {
    105 //      int* ptr_to_new_brk_limit = sbrk(4096);
    106 //      int  undef_brk_int = *ptr_to_new_brk_limit;
    107 //      fprintf(stderr, "\nUndef 7 of 8 (brk)\n");
    108 //      x += (undef_brk_int == 0x12345678 ? 15 : 26);
    109 //   }
    110 //#endif
    111 
    112    // User block, marked as undefined
    113    {
    114       int  undef_user_int = 0;
    115       (void) VALGRIND_MAKE_MEM_UNDEFINED(&undef_user_int, sizeof(int));
    116       fprintf(stderr, "\nUndef 8 of 8 (MAKE_MEM_UNDEFINED)\n");
    117       x += (undef_user_int == 0x12345678 ? 16 : 27);
    118    }
    119 
    120    //------------------------------------------------------------------------
    121    // Sources of defined values
    122    //------------------------------------------------------------------------
    123 
    124    // Heap block (calloc), initialised
    125    {
    126       int* ptr_to_def_calloc_int = calloc(1, sizeof(int));
    127       int  def_calloc_int = *ptr_to_def_calloc_int;
    128       fprintf(stderr, "\nDef 1 of 3\n");
    129       x += (def_calloc_int == 0x12345678 ? 17 : 28);
    130    }
    131 
    132    // Custom-allocated block, non-zeroed
    133    {
    134       int  def_custom_alloc_int = 0;
    135       fprintf(stderr, "\nDef 2 of 3\n");
    136       VALGRIND_MALLOCLIKE_BLOCK(&def_custom_alloc_int, sizeof(int),
    137                                 /*rzB*/0, /*is_zeroed*/1);
    138       x += (def_custom_alloc_int == 0x12345678 ? 18 : 29);
    139    }
    140 
    141    // mmap block, initialised
    142    {
    143       int* ptr_to_def_mmap_int =
    144                mmap(0, 4096, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    145       int def_mmap_int = *ptr_to_def_mmap_int;
    146       fprintf(stderr, "\nDef 3 of 3\n");
    147       x += (def_mmap_int == 0x12345678 ? 19 : 30);
    148    }
    149 
    150    return x;
    151 }
    152