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