diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp --- a/compiler-rt/lib/dfsan/dfsan.cpp +++ b/compiler-rt/lib/dfsan/dfsan.cpp @@ -158,6 +158,12 @@ } } +static void ReportUnsupportedFast16(const char *func) { + Report("FATAL: DataFlowSanitizer: %s is unsupported in fast16labels mode\n", + func); + Die(); +} + // Resolves the union of two unequal labels. Nonequality is a precondition for // this function (the instrumentation pass inlines the equality test). extern "C" SANITIZER_INTERFACE_ATTRIBUTE @@ -253,15 +259,10 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label dfsan_create_label(const char *desc, void *userdata) { - dfsan_label last_label = - atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed); - if (flags().fast16labels && last_label > 15) { - Report( - "FATAL: DataFlowSanitizer: more than 16 labels created in " - "fast16labels mode\n"); - Die(); - } - dfsan_label label = flags().fast16labels ? 1U << last_label : last_label + 1; + if (flags().fast16labels) + ReportUnsupportedFast16("dfsan_create_label"); + dfsan_label label = + atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1; dfsan_check_label(label); __dfsan_label_info[label].l1 = __dfsan_label_info[label].l2 = 0; __dfsan_label_info[label].desc = desc; @@ -318,15 +319,8 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label) { - if (flags().fast16labels && (label & (label - 1))) { - // In fast16 mode, we don't have info for any union labels. Users should - // only call this function for base labels. - Report( - "FATAL: DataFlowSanitizer: called dfsan_get_label_info() on union " - "label %u in fast16labels mode\n", - label); - Die(); - } + if (flags().fast16labels) + ReportUnsupportedFast16("dfsan_get_label_info"); return &__dfsan_label_info[label]; } @@ -346,13 +340,8 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc) { - if (flags().fast16labels && (label & (label - 1)) && label != 0) { - // This is a union label. Peel off the lowest bit and recurse. - dfsan_label l1 = 1U << __builtin_ctz(label); - dfsan_label l2 = label & ~l1; - return dfsan_has_label_with_desc(l1, desc) || - dfsan_has_label_with_desc(l2, desc); - } + if (flags().fast16labels) + ReportUnsupportedFast16("dfsan_has_label_with_desc"); const dfsan_label_info *info = dfsan_get_label_info(label); if (info->l1 != 0) { return dfsan_has_label_with_desc(info->l1, desc) || @@ -372,24 +361,11 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_dump_labels(int fd) { + if (flags().fast16labels) + ReportUnsupportedFast16("dfsan_dump_labels"); + dfsan_label last_label = atomic_load(&__dfsan_last_label, memory_order_relaxed); - - if (flags().fast16labels) { - for (uptr i = 0; i < last_label; ++i) { - dfsan_label l = 1U << i; - char buf[16]; - internal_snprintf(buf, sizeof(buf), "%u ", l); - WriteToFile(fd, buf, internal_strlen(buf)); - if (__dfsan_label_info[l].desc) { - WriteToFile(fd, __dfsan_label_info[l].desc, - internal_strlen(__dfsan_label_info[l].desc)); - } - WriteToFile(fd, "\n", 1); - } - return; - } - for (uptr l = 1; l <= last_label; ++l) { char buf[64]; internal_snprintf(buf, sizeof(buf), "%u %u %u ", l, diff --git a/compiler-rt/test/dfsan/fast16labels.c b/compiler-rt/test/dfsan/fast16labels.c --- a/compiler-rt/test/dfsan/fast16labels.c +++ b/compiler-rt/test/dfsan/fast16labels.c @@ -1,10 +1,13 @@ // RUN: %clang_dfsan %s -o %t -// RUN: DFSAN_OPTIONS=fast16labels=1:dump_labels_at_exit=/dev/stdout %run %t \ -// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-LABELS -// RUN: DFSAN_OPTIONS=fast16labels=1 not %run %t exceed_16_labels 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-EXCEED16 -// RUN: DFSAN_OPTIONS=fast16labels=1 not %run %t union_label_info 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-UNION-LABEL-INFO +// RUN: DFSAN_OPTIONS=fast16labels=1 %run %t +// RUN: DFSAN_OPTIONS=fast16labels=1 not %run %t dfsan_create_label 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CREATE-LABEL +// RUN: DFSAN_OPTIONS=fast16labels=1 not %run %t dfsan_get_label_info 2>&1 \ +// RUN: | FileCheck %s --check-prefix=GET-LABEL-INFO +// RUN: DFSAN_OPTIONS=fast16labels=1 not %run %t dfsan_has_label_with_desc \ +// RUN: 2>&1 | FileCheck %s --check-prefix=HAS-LABEL-WITH-DESC +// RUN: DFSAN_OPTIONS=fast16labels=1:dump_labels_at_exit=/dev/stdout not %run \ +// RUN: %t 2>&1 | FileCheck %s --check-prefix=DUMP-LABELS // // Tests DFSAN_OPTIONS=fast16labels=1 // @@ -14,75 +17,36 @@ #include #include -void check_label(dfsan_label l) { - static dfsan_label combined = 0; - assert((l & combined) == 0); - combined = dfsan_union(l, combined); -} - int foo(int a, int b) { return a + b; } int main(int argc, char *argv[]) { + // Death tests for unsupported API usage. const char *command = (argc < 2) ? "" : argv[1]; - - // Make sure we can create 16 distinct labels. - for (int i = 0; i < 13; ++i) - check_label(dfsan_create_label("unused", NULL)); - dfsan_label lx = dfsan_create_label("x", NULL); - check_label(lx); - dfsan_label la = dfsan_create_label("a", NULL); - check_label(la); - dfsan_label lb = dfsan_create_label("b", NULL); - check_label(lb); - - // CHECK-EXCEED16: FATAL: DataFlowSanitizer: more than 16 labels created - if (strcmp(command, "exceed_16_labels") == 0) + // CREATE-LABEL: FATAL: DataFlowSanitizer: dfsan_create_label is unsupported + if (strcmp(command, "dfsan_create_label") == 0) dfsan_create_label("", NULL); - + // GET-LABEL-INFO: FATAL: DataFlowSanitizer: dfsan_get_label_info is unsupported + if (strcmp(command, "dfsan_get_label_info") == 0) + dfsan_get_label_info(1); + // HAS-LABEL-WITH-DESC: FATAL: DataFlowSanitizer: dfsan_has_label_with_desc is unsupported + if (strcmp(command, "dfsan_has_label_with_desc") == 0) + dfsan_has_label_with_desc(1, ""); + // DUMP-LABELS: FATAL: DataFlowSanitizer: dfsan_dump_labels is unsupported + + // Supported usage. int a = 10; int b = 20; - dfsan_set_label(la, &a, sizeof(a)); - dfsan_set_label(lb, &b, sizeof(b)); + dfsan_set_label(8, &a, sizeof(a)); + dfsan_set_label(512, &b, sizeof(b)); int c = foo(a, b); printf("A: 0x%x\n", dfsan_get_label(a)); printf("B: 0x%x\n", dfsan_get_label(b)); - dfsan_label lc = dfsan_get_label(c); - printf("C: 0x%x\n", lc); - - assert(dfsan_has_label(lc, la)); - assert(dfsan_has_label(lc, lb)); - assert(!dfsan_has_label(lc, lx)); - assert(dfsan_has_label_with_desc(lc, "a")); - assert(dfsan_has_label_with_desc(lc, "b")); - assert(!dfsan_has_label_with_desc(lc, "x")); - assert(lc == (la | lb)); - - const struct dfsan_label_info *info = dfsan_get_label_info(la); - assert(info->l1 == 0); - assert(info->l2 == 0); - assert(strcmp(info->desc, "a") == 0); - assert(info->userdata == NULL); - - // CHECK-UNION-LABEL-INFO: FATAL: DataFlowSanitizer: called dfsan_get_label_info() on union label - if (strcmp(command, "union_label_info") == 0) - dfsan_get_label_info(lc); - - // CHECK-LABELS: 1 unused - // CHECK-LABELS-NEXT: 2 unused - // CHECK-LABELS-NEXT: 4 unused - // CHECK-LABELS-NEXT: 8 unused - // CHECK-LABELS-NEXT: 16 unused - // CHECK-LABELS-NEXT: 32 unused - // CHECK-LABELS-NEXT: 64 unused - // CHECK-LABELS-NEXT: 128 unused - // CHECK-LABELS-NEXT: 256 unused - // CHECK-LABELS-NEXT: 512 unused - // CHECK-LABELS-NEXT: 1024 unused - // CHECK-LABELS-NEXT: 2048 unused - // CHECK-LABELS-NEXT: 4096 unused - // CHECK-LABELS-NEXT: 8192 x - // CHECK-LABELS-NEXT: 16384 a - // CHECK-LABELS-NEXT: 32768 b + dfsan_label l = dfsan_get_label(c); + printf("C: 0x%x\n", l); + assert(l == 520); // OR of the other two labels. + assert(dfsan_has_label(l, 8)); + assert(dfsan_has_label(l, 512)); + assert(!dfsan_has_label(l, 1)); }