brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · 20e55da Raw
258 lines · cpp
1// Check that shadow of retrieved value from va_list matches the shadow of passed value.2 3// Without -fno-sanitize-memory-param-retval we can't even pass poisoned values.4// RUN: %clangxx_msan -fno-sanitize-memory-param-retval -fsanitize-memory-track-origins=0 -O3 %s -o %t5 6// FIXME: The rest is likely still broken.7// XFAIL: target={{(loongarch64|mips|powerpc64).*}}8 9#include <sanitizer/msan_interface.h>10#include <stdarg.h>11#include <stdint.h>12#include <stdio.h>13#include <string.h>14 15#ifdef DEBUG_VARARG_SHADOW_TEST16__attribute__((noinline, no_sanitize("memory"))) void17printb(const void *p, size_t n, int line, int align) {18  fprintf(stderr, "\n%p at line %d: \n", p, line);19  for (int i = 0; i < n;) {20    fprintf(stderr, "%p: ", (void *)(((uint8_t *)p) + i));21    for (int j = 0; j < align; ++i, ++j)22      fprintf(stderr, "%02x ", ((uint8_t *)p)[i]);23    fprintf(stderr, "\n");24  }25}26 27struct my_va_list {28#  ifdef __ARM_ARCH_ISA_A6429  void *stack;30  void *gr_top;31  void *vr_top;32  int gr_offs;33  int vr_offs;34#  else35  unsigned int gp_offset;36  unsigned int fp_offset;37  void *overflow_arg_area;38  void *reg_save_area;39#  endif40};41 42__attribute__((noinline, no_sanitize("memory"))) void printva(const void *p,43                                                              int line) {44  my_va_list *pp = (my_va_list *)p;45#  ifdef __ARM_ARCH_ISA_A6446  fprintf(stderr,47          "\nva %p at line %d: stack : %p\n gr_top: %p\n vr_top: %p\n gr_offs: "48          "%d\n "49          "vr_offs: %d\n",50          p, line, pp->stack, pp->gr_top, pp->vr_top, pp->gr_offs, pp->vr_offs);51 52  printb((char *)pp->gr_top + pp->gr_offs, -pp->gr_offs, __LINE__, 8);53  printb((char *)pp->vr_top + pp->vr_offs, -pp->vr_offs, __LINE__, 16);54  printb((char *)pp->stack, 256, __LINE__, 8);55#  else56  fprintf(stderr,57          "\nva %p at line %d:\n gp_offset: %u\n fp_offset: %u\n "58          "overflow_arg_area: %p\n reg_save_area: %p\n\n",59          p, line, pp->gp_offset, pp->fp_offset, pp->overflow_arg_area,60          pp->reg_save_area);61 62  printb((char *)pp->reg_save_area + pp->gp_offset,63         pp->fp_offset - pp->gp_offset, __LINE__, 8);64  printb((char *)pp->reg_save_area + pp->fp_offset, 128, __LINE__, 16);65  printb((char *)pp->overflow_arg_area, 256, __LINE__, 8);66#  endif67}68 69__attribute__((noinline, no_sanitize("memory"))) void printtls(int line) {70  uint8_t tmp[kMsanParamTlsSize];71  for (int i = 0; i < kMsanParamTlsSize; ++i)72    tmp[i] = __msan_va_arg_tls[i];73  fprintf(stderr, "\nTLS at line %d: ", line);74  for (int i = 0; i < kMsanParamTlsSize;) {75    fprintf(stderr, "\n");76    for (int j = 0; j < 16; ++i, ++j)77      fprintf(stderr, "%02x ", tmp[i]);78  }79 80  fprintf(stderr, "\n");81}82#endif // DEBUG_VARARG_SHADOW_TEST83 84const int kMsanParamTlsSize = 800;85extern "C" __thread uint8_t __msan_va_arg_tls[];86 87struct IntInt {88  int a;89  int b;90};91 92struct Int64Int64 {93  int64_t a;94  int64_t b;95};96 97struct DoubleDouble {98  double a;99  double b;100};101 102struct Double4 {103  double a[4];104};105 106struct DoubleFloat {107  double a;108  float b;109};110 111struct LongDouble2 {112  long double a[2];113};114 115struct LongDouble4 {116  long double a[4];117};118 119template <class T>120__attribute__((noinline)) void print_shadow(va_list &args, int n,121                                            const char *function) {122  for (int i = 0; i < n; i++) {123    // 1-based to make it different from clean shadow.124    fprintf(stderr, "\nArgShadow fn:%s n:%d i:%02x ", function, n, i + 1);125    T arg_int = va_arg(args, T);126    if (__msan_test_shadow(&arg_int, sizeof(arg_int)))127      fprintf(stderr, "fake[clean] %02x", i + 1);128    else129      __msan_dump_shadow(&arg_int, sizeof(arg_int));130#ifdef DEBUG_VARARG_SHADOW_TEST131    printb(&arg_int, sizeof(arg_int), __LINE__, 16);132#endif133  }134}135 136template <class T> __attribute__((noinline)) void test1(int n, ...) {137#ifdef DEBUG_VARARG_SHADOW_TEST138  printtls(__LINE__);139#endif140  va_list args;141  va_start(args, n);142#ifdef DEBUG_VARARG_SHADOW_TEST143  printva(&args, __LINE__);144#endif145  print_shadow<T>(args, n, __FUNCTION__);146  va_end(args);147}148 149template <class T> __attribute__((noinline)) void test2(T t, int n, ...) {150#ifdef DEBUG_VARARG_SHADOW_TEST151  printtls(__LINE__);152#endif153  va_list args;154  va_start(args, n);155#ifdef DEBUG_VARARG_SHADOW_TEST156  printva(&args, __LINE__);157#endif158  print_shadow<T>(args, n, __FUNCTION__);159  va_end(args);160}161 162template <class T> __attribute__((noinline)) void test() {163  // Array of values we will pass into variadic functions.164  static T args[32] = {};165 166  // Poison values making the fist byte of the item shadow match the index.167  // E.g. item 3 should be poisoned as '03 ff ff ff'.168  memset(args, 0xff, sizeof(args));169  __msan_poison(args, sizeof(args));170  for (int i = 0; i < 32; ++i) {171    char *first = (char *)(&args[i]);172    *first = char(*(int *)(first)&i);173  }174#ifdef DEBUG_VARARG_SHADOW_TEST175  __msan_print_shadow(args, sizeof(args));176#endif177 178  // Now we will check that index, printed like 'i:03' will match179  // '0x123abc[0x123abc] 03 ff ff ff'180  memset(__msan_va_arg_tls, 0xee, kMsanParamTlsSize);181  test1<T>(1, args[1]);182  // CHECK-COUNT-1: ArgShadow fn:test1 n:1 i:[[ARGI:[[:xdigit:]]{2}]] {{[^]]+}}] [[ARGI]]183 184  memset(__msan_va_arg_tls, 0xee, kMsanParamTlsSize);185  test1<T>(4, args[1], args[2], args[3], args[4]);186  // CHECK-COUNT-4: ArgShadow fn:test1 n:4 i:[[ARGI:[[:xdigit:]]{2}]] {{[^]]+}}] [[ARGI]]187 188  memset(__msan_va_arg_tls, 0xee, kMsanParamTlsSize);189  test1<T>(20, args[1], args[2], args[3], args[4], args[5], args[6], args[7],190           args[8], args[9], args[10], args[11], args[12], args[13], args[14],191           args[15], args[16], args[17], args[18], args[19], args[20]);192  // CHECK-COUNT-20: ArgShadow fn:test1 n:20 i:[[ARGI:[[:xdigit:]]{2}]] {{[^]]+}}] [[ARGI]]193 194  memset(__msan_va_arg_tls, 0xee, kMsanParamTlsSize);195  test2<T>(args[31], 1, args[1]);196  // CHECK-COUNT-1: ArgShadow fn:test2 n:1 i:[[ARGI:[[:xdigit:]]{2}]] {{[^]]+}}] [[ARGI]]197 198  memset(__msan_va_arg_tls, 0xee, kMsanParamTlsSize);199  test2<T>(args[31], 4, args[1], args[2], args[3], args[4]);200  // CHECK-COUNT-4: ArgShadow fn:test2 n:4 i:[[ARGI:[[:xdigit:]]{2}]] {{[^]]+}}] [[ARGI]]201 202  memset(__msan_va_arg_tls, 0xee, kMsanParamTlsSize);203  test2<T>(args[31], 20, args[1], args[2], args[3], args[4], args[5], args[6],204           args[7], args[8], args[9], args[10], args[11], args[12], args[13],205           args[14], args[15], args[16], args[17], args[18], args[19],206           args[20]);207  // CHECK-COUNT-20: ArgShadow fn:test2 n:20 i:[[ARGI:[[:xdigit:]]{2}]] {{[^]]+}}] [[ARGI]]208}209 210int main(int argc, char *argv[]) {211#define TEST(T...)                                                             \212  if (argc == 2 && strcmp(argv[1], #T) == 0) {                                 \213    test<T>();                                                                 \214    return 0;                                                                  \215  }216 217  TEST(char);218  // RUN: %run %t char 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"219 220  TEST(int);221  // RUN: %run %t int 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"222 223  TEST(void*);224  // RUN: %run %t "void*" 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"225 226  TEST(float);227  // RUN: %run %t float 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"228 229  TEST(double);230  // RUN: %run %t double 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"231 232  TEST(long double);233  // RUN: %run %t "long double" 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"234 235  TEST(IntInt);236  // RUN: %run %t IntInt 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"237 238  TEST(Int64Int64);239  // RUN: %run %t Int64Int64 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"240 241  TEST(DoubleDouble);242  // RUN: %run %t DoubleDouble 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"243 244  TEST(Double4);245  // RUN: %run %t Double4 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"246 247  TEST(DoubleFloat);248  // RUN: %run %t DoubleFloat 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"249 250  TEST(LongDouble2);251  // RUN: %run %t LongDouble2 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"252 253  TEST(LongDouble4);254  // RUN: %run %t LongDouble4 2>&1 | FileCheck %s --implicit-check-not="ArgShadow"255 256  return 1;257}258