1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This test case was originally written by Nicholas Nethercote. */
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// [[This comment applies to the old piggybacking approach to
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// origin-tracking.  The newer approach handles the cases in this file
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// correctly.]]
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test demonstrates cases the piggybacking algorithm cannot handle,
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// but which are handled ok by the instrumentation based algorithm.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "../memcheck.h"
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint x = 0;
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t1(void);
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t2(void);
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t3(void);
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t4(void);
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t5(void);
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t6(void);
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(void)
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(4 == sizeof(int));
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x += t1();
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x += t2();
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x += t3();
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x += t4();
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x += t5();
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x += t6();
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x & 255;
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t1(void)
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // 8-bit undefined value.  When compared it's loaded from memory, so will
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // never work.
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   char* ptr_to_undef_char = malloc(sizeof(char));
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   char  undef_char = *ptr_to_undef_char;
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprintf(stderr, "\nUndef 1 of 8 (8 bit undef)\n");
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (undef_char == 0x12 ? 11 : 22);
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t2(void)
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Stack, 8-bit from (recently) 32-bit.  But the load only loads 8-bits
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // of the value, so it'll never work.
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int undef_stack_int;
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register char undef_stack_char = (char)undef_stack_int;
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprintf(stderr, "\nUndef 2 of 8 (8 bits of 32 undef)\n");
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (undef_stack_char == 0x12 ? 11 : 22);
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t3(void)
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // 32-bit undefined value.  This one is identified, and is here for
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // sanity-checking.
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int* ptr_to_undef_int = malloc(sizeof(int));
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int  undef_int = *ptr_to_undef_int;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprintf(stderr, "\nUndef 3 of 8 (32 bit undef)\n");
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (undef_int == 0x12345678 ? 13 : 24);
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t4(void)
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Unaligned 32-bit value.
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int* ptr_to_undef_int = malloc(sizeof(int) + 1);
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int  undef_unaligned_int = *(int*)((long)ptr_to_undef_int + 1);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprintf(stderr, "\nUndef 4 of 8 (32 bit undef, unaligned)\n");
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (undef_unaligned_int == 0x12345678 ? 14 : 25);
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t5(void)
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Modified 32-bit value.
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int* ptr_to_undef_int3 = malloc(sizeof(int));
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int  modified_undef_int = *ptr_to_undef_int3;
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprintf(stderr, "\nUndef 5 of 8 (32 bit undef, modified)\n");
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified_undef_int++;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (modified_undef_int == 0x12345678 ? 15 : 26);
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) int t6(void)
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int y = 0;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Uninitialised 32-bit value (middle of 3) is made undefined in two
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // unaligned pieces:
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   |....|....|....|   three 4-byte integers
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //    XXXX-YY           first MAKE_MEM_UNDEFINED
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //           YY-XXXX    second MAKE_MEM_UNDEFINED
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Because the YY parts don't get marked (they're not 32-bit and aligned)
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the middle byte keeps its original value, which is zero (from calloc).
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // So even though it's been marked as undefined, it doesn't have an
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // origin-tracking value and so cannot be identified.  We also check the
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // first and third ints (which are identified) for sanity-checking.
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int* ptr_to_3_undef_ints = calloc(3, sizeof(int));
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int* ptr_to_middle       = (int*)((long)ptr_to_3_undef_ints + 6);
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_MAKE_MEM_UNDEFINED(ptr_to_3_undef_ints, 6);
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_MAKE_MEM_UNDEFINED(ptr_to_middle,       6);
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "\nUndef 6 of 8 (32 bit undef, unaligned, strange, #1)\n");
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      y += (*(ptr_to_3_undef_ints + 0)  == 0x12345678 ? 16 : 27);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "\nUndef 7 of 8 (32 bit undef, unaligned, strange, #2)\n");
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      y += (*(ptr_to_3_undef_ints + 1)  == 0x12345678 ? 17 : 28);
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "\nUndef 8 of 8 (32 bit undef, unaligned, strange, #3)\n");
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      y += (*(ptr_to_3_undef_ints + 2)  == 0x12345678 ? 18 : 29);
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return y;
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
117