Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,31 @@
set(DFSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(DFSAN_TESTSUITES)
set(DFSAN_TEST_ARCH ${DFSAN_SUPPORTED_ARCH})
if(APPLE)
darwin_filter_host_archs(DFSAN_SUPPORTED_ARCH DFSAN_TEST_ARCH)
endif()
foreach(arch ${DFSAN_TEST_ARCH})
set(DFSAN_TEST_TARGET_ARCH ${arch})
string(TOLOWER "-${arch}" DFSAN_TEST_CONFIG_SUFFIX)
get_test_cc_for_arch(${arch} DFSAN_TEST_TARGET_CC DFSAN_TEST_TARGET_CFLAGS)
string(TOUPPER ${arch} ARCH_UPPER_CASE)
set(CONFIG_NAME ${ARCH_UPPER_CASE}Config)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
list(APPEND DFSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
endforeach()
set(DFSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND DFSAN_TEST_DEPS dfsan)
endif()
add_lit_testsuite(check-dfsan "Running the DataFlowSanitizer tests"
${DFSAN_TESTSUITES}
DEPENDS ${DFSAN_TEST_DEPS})
set_target_properties(check-dfsan PROPERTIES FOLDER "Compiler-RT Misc")

View File

@@ -0,0 +1,10 @@
fun:f=uninstrumented
fun:main=uninstrumented
fun:main=discard
fun:dfsan_create_label=uninstrumented
fun:dfsan_create_label=discard
fun:dfsan_set_label=uninstrumented
fun:dfsan_set_label=discard

View File

@@ -0,0 +1,28 @@
// RUN: %clang_dfsan %s -o %t && %run %t
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
// Tests that labels are propagated through loads and stores.
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
dfsan_label new_label = dfsan_get_label(i);
assert(i_label == new_label);
dfsan_label read_label = dfsan_read_label(&i, sizeof(i));
assert(i_label == read_label);
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_add_label(j_label, &i, sizeof(i));
read_label = dfsan_read_label(&i, sizeof(i));
assert(dfsan_has_label(read_label, i_label));
assert(dfsan_has_label(read_label, j_label));
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
// RUN: %clang_dfsan %s -o %t
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout %run %t 2>&1 | FileCheck %s
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
// RUN: DFSAN_OPTIONS=dump_labels_at_exit=/dev/stdout not %run %t u 2>&1 | FileCheck %s --check-prefix=CHECK-OOL
// Tests that labels are properly dumped at program termination.
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
#include <stdio.h>
int main(int argc, char** argv) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
int k = 3;
dfsan_label k_label = dfsan_create_label("k", 0);
dfsan_set_label(k_label, &k, sizeof(k));
dfsan_label ij_label = dfsan_get_label(i + j);
dfsan_label ijk_label = dfsan_get_label(i + j + k);
fprintf(stderr, "i %d j %d k %d ij %d ijk %d\n", i_label, j_label, k_label,
ij_label, ijk_label);
// CHECK: 1 0 0 i
// CHECK: 2 0 0 j
// CHECK: 3 0 0 k
// CHECK: 4 1 2
// CHECK: 5 3 4
if (argc > 1) {
// Exhaust the labels.
unsigned long num_labels = 1 << (sizeof(dfsan_label) * 8);
for (unsigned long i = ijk_label + 1; i < num_labels - 2; ++i) {
dfsan_label l = dfsan_create_label("l", 0);
assert(l == i);
}
// Consume the last available label.
dfsan_label l = dfsan_union(5, 6);
assert(l == num_labels - 2);
// Try to allocate another label (either explicitly or by unioning two
// existing labels), but expect a crash.
if (argv[1][0] == 'c') {
l = dfsan_create_label("l", 0);
} else {
l = dfsan_union(6, 7);
}
// CHECK-OOL: FATAL: DataFlowSanitizer: out of labels
// CHECK-OOL: 1 0 0 i
// CHECK-OOL: 2 0 0 j
// CHECK-OOL: 3 0 0 k
// CHECK-OOL: 4 1 2
// CHECK-OOL: 5 3 4
// CHECK-OOL: 6 0 0
// CHECK-OOL: 65534 5 6
// CHECK-OOL: 65535 0 0 <init label>
}
return 0;
}

View File

@@ -0,0 +1,24 @@
// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && %run %t 2>&1 | FileCheck %s
// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_unimplemented=0 %run %t 2>&1 | count 0
// RUN: %clang_dfsan %s -fsanitize-blacklist=%S/Inputs/flags_abilist.txt -mllvm -dfsan-debug-nonzero-labels -o %t && DFSAN_OPTIONS=warn_nonzero_labels=1 %run %t 2>&1 | FileCheck --check-prefix=CHECK-NONZERO %s
// Tests that flags work correctly.
#include <sanitizer/dfsan_interface.h>
int f(int i) {
return i;
}
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
// CHECK: WARNING: DataFlowSanitizer: call to uninstrumented function f
// CHECK-NOT: WARNING: DataFlowSanitizer: saw nonzero label
// CHECK-NONZERO: WARNING: DataFlowSanitizer: saw nonzero label
f(i);
return 0;
}

View File

@@ -0,0 +1,26 @@
// RUN: %clang_dfsan %s -o %t && %run %t
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
// Tests that labels are propagated through function calls.
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
int f(int x) {
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
return x + j;
}
int main(void) {
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
dfsan_label ij_label = dfsan_get_label(f(i));
assert(dfsan_has_label(ij_label, i_label));
assert(dfsan_has_label_with_desc(ij_label, "j"));
return 0;
}

View File

@@ -0,0 +1,75 @@
// RUN: %clang_dfsan -DLIB -c %s -o %t.lib.o && \
// RUN: %clang_dfsan -c %s -o %t.o && \
// RUN: %clang_dfsan %t.lib.o %t.o -o %t.bin && \
// RUN: %run %t.bin
// RUN: %clang_dfsan -mllvm -dfsan-args-abi -DLIB -c %s -o %t.lib.o && \
// RUN: %clang_dfsan -mllvm -dfsan-args-abi -c %s -o %t.o && \
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %t.o %t.lib.o -o %t.bin && \
// RUN: %run %t.bin
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
#ifdef LIB
// Compiling this file with and without LIB defined allows this file to be
// built as two separate translation units. This ensures that the code
// can not be optimized in a way that removes behavior we wish to test. For
// example, computing a value should cause labels to be allocated only if
// the computation is actually done. Putting the computation here prevents
// the compiler from optimizing away the computation (and labeling) that
// tests wish to verify.
int add_in_separate_translation_unit(int a, int b) {
return a + b;
}
int multiply_in_separate_translation_unit(int a, int b) {
return a * b;
}
#else
int add_in_separate_translation_unit(int i, int j);
int multiply_in_separate_translation_unit(int i, int j);
int main(void) {
size_t label_count;
// No labels allocated yet.
label_count = dfsan_get_label_count();
assert(0 == label_count);
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
// One label allocated for i.
label_count = dfsan_get_label_count();
assert(1u == label_count);
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
// Check that a new label was allocated for j.
label_count = dfsan_get_label_count();
assert(2u == label_count);
// Create a value that combines i and j.
int i_plus_j = add_in_separate_translation_unit(i, j);
// Check that a label was created for the union of i and j.
label_count = dfsan_get_label_count();
assert(3u == label_count);
// Combine i and j in a different way. Check that the existing label is
// reused, and a new label is not created.
int j_times_i = multiply_in_separate_translation_unit(j, i);
label_count = dfsan_get_label_count();
assert(3u == label_count);
assert(dfsan_get_label(i_plus_j) == dfsan_get_label(j_times_i));
return 0;
}
#endif // #ifdef LIB

View File

@@ -0,0 +1,26 @@
# -*- Python -*-
import os
# Setup config name.
config.name = 'DataFlowSanitizer' + config.name_suffix
# Setup source root.
config.test_source_root = os.path.dirname(__file__)
# Setup default compiler flags used with -fsanitize=dataflow option.
clang_dfsan_cflags = ["-fsanitize=dataflow", config.target_cflags]
clang_dfsan_cxxflags = config.cxx_mode_flags + clang_dfsan_cflags
def build_invocation(compile_flags):
return " " + " ".join([config.clang] + compile_flags) + " "
config.substitutions.append( ("%clang_dfsan ", build_invocation(clang_dfsan_cflags)) )
config.substitutions.append( ("%clangxx_dfsan ", build_invocation(clang_dfsan_cxxflags)) )
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']
# DataFlowSanitizer tests are currently supported on Linux only.
if config.host_os not in ['Linux']:
config.unsupported = True

View File

@@ -0,0 +1,12 @@
@LIT_SITE_CFG_IN_HEADER@
# Tool-specific config options.
config.name_suffix = "@DFSAN_TEST_CONFIG_SUFFIX@"
config.target_cflags = "@DFSAN_TEST_TARGET_CFLAGS@"
config.target_arch = "@DFSAN_TEST_TARGET_ARCH@"
# Load common config for all compiler-rt lit tests.
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
# Load tool-specific config that would do the real work.
lit_config.load_config(config, "@DFSAN_LIT_TESTS_DIR@/lit.cfg")

View File

@@ -0,0 +1,47 @@
// RUN: %clang_dfsan %s -o %t && %run %t
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t
// Tests that labels are propagated through computation and that union labels
// are properly created.
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
int main(void) {
assert(dfsan_union(0, 0) == 0);
int i = 1;
dfsan_label i_label = dfsan_create_label("i", 0);
dfsan_set_label(i_label, &i, sizeof(i));
int j = 2;
dfsan_label j_label = dfsan_create_label("j", 0);
dfsan_set_label(j_label, &j, sizeof(j));
int k = 3;
dfsan_label k_label = dfsan_create_label("k", 0);
dfsan_set_label(k_label, &k, sizeof(k));
int k2 = 4;
dfsan_set_label(k_label, &k2, sizeof(k2));
dfsan_label ij_label = dfsan_get_label(i + j);
assert(dfsan_has_label(ij_label, i_label));
assert(dfsan_has_label(ij_label, j_label));
assert(!dfsan_has_label(ij_label, k_label));
// Test uniquing.
assert(dfsan_union(i_label, j_label) == ij_label);
assert(dfsan_union(j_label, i_label) == ij_label);
dfsan_label ijk_label = dfsan_get_label(i + j + k);
assert(dfsan_has_label(ijk_label, i_label));
assert(dfsan_has_label(ijk_label, j_label));
assert(dfsan_has_label(ijk_label, k_label));
assert(dfsan_get_label(k + k2) == k_label);
struct { int i, j; } s = { i, j };
assert(dfsan_read_label(&s, sizeof(s)) == ij_label);
return 0;
}

View File

@@ -0,0 +1,24 @@
// RUN: %clang_dfsan %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %run %t foo
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %run %t foo
#include <stdio.h>
int do_nothing(const char *format, ...) {
return 0;
}
int main(int argc, char **argv) {
int (*fp)(const char *, ...);
if (argc > 1)
fp = do_nothing;
else
fp = printf;
// CHECK: FATAL: DataFlowSanitizer: unsupported indirect call to vararg function printf
fp("hello %s\n", "world");
}

View File

@@ -0,0 +1,111 @@
// RUN: %clang_dfsan %s -o %t && %run %t | FileCheck %s
// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t | FileCheck %s
// Tests that the custom implementation of write() does writes with or without
// a callback set using dfsan_set_write_callback().
// REQUIRES: stable-runtime
#include <sanitizer/dfsan_interface.h>
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// Check write callback arguments by having the callback store them in
// the following variables:
static int last_callback_arg_fd;
static const void *last_callback_arg_buf;
static size_t last_callback_arg_count;
// Allow tests to check the number of callbacks made by incrementing
// this count. When callbacks are verified, the count is reset.
static int count_unverified_callbacks = 0;
// This callbact will be installed using dfsan_set_write_callback()
// in tests below.
static void write_callback(int fd, const void *buf, size_t count) {
// Do not do anything in this function that might call write().
count_unverified_callbacks++;
last_callback_arg_fd = fd;
last_callback_arg_buf = buf;
last_callback_arg_count = count;
}
static void write_string_to_stdout(char *string) {
char *cur = string;
int bytes_left = strlen(string);
while (bytes_left > 0) {
int res = write(fileno(stdout), cur, bytes_left);
assert (res >= 0);
cur += res;
bytes_left -= res;
}
}
static void test_can_write_without_callback() {
dfsan_set_write_callback(NULL);
count_unverified_callbacks = 0;
char aString[] = "Test that writes work without callback.\n";
// CHECK: Test that writes work without callback.
write_string_to_stdout(aString);
assert(count_unverified_callbacks == 0);
}
static void test_can_write_with_callback() {
dfsan_set_write_callback(write_callback);
count_unverified_callbacks = 0;
char stringWithCallback[] = "Test that writes work with callback.\n";
// CHECK: Test that writes work with callback.
write_string_to_stdout(stringWithCallback);
// Data was written, so at least one call to write() was made.
// Because a write may not process all the bytes it is passed, there
// may have been several calls to write().
assert(count_unverified_callbacks > 0);
count_unverified_callbacks = 0;
dfsan_set_write_callback(NULL);
char stringWithoutCallback[] = "Writes work after the callback is removed.\n";
// CHECK: Writes work after the callback is removed.
write_string_to_stdout(stringWithoutCallback);
assert(count_unverified_callbacks == 0);
}
static void test_failing_write_runs_callback() {
// Open /dev/null in read-only mode. Calling write() on fd will fail.
int fd = open("/dev/null", O_RDONLY);
assert(fd != -1);
// Install a callback.
dfsan_set_write_callback(write_callback);
// Write to the read-only file handle. The write will fail, but the callback
// should still be invoked.
char aString[] = "This text will fail to be written.\n";
int len = strlen(aString);
int write_result = write(fd, aString, len);
assert(write_result == -1);
assert(count_unverified_callbacks == 1);
count_unverified_callbacks = 0;
assert(fd == last_callback_arg_fd);
assert(aString == last_callback_arg_buf);
assert(len == last_callback_arg_count);
close(fd);
}
int main(int argc, char* argv[]) {
test_can_write_without_callback();
test_can_write_with_callback();
test_failing_write_runs_callback();
}