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