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