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
20int x = 0;
21
22int 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