Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Code coverage and UBSan bug fixes for 4.1 (compiler-rt) #14

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/profile/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
/* Raw profile format version (start from 1). */
#define INSTR_PROF_RAW_VERSION 4
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 4
#define INSTR_PROF_INDEX_VERSION 5
/* Coverage mapping format vresion (start from 0). */
#define INSTR_PROF_COVMAP_VERSION 2

Expand Down
6 changes: 4 additions & 2 deletions lib/ubsan_minimal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ include_directories(..)
set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
append_rtti_flag(OFF UBSAN_CFLAGS)

set(UBSAN_STANDALONE_CFLAGS ${SANITIZER_COMMON_CFLAGS})
append_rtti_flag(OFF UBSAN_STANDALONE_CFLAGS)
set(UBSAN_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS})

set(UBSAN_DYNAMIC_LIBS ${SANITIZER_COMMON_LINK_LIBS})

add_compiler_rt_component(ubsan-minimal)

Expand Down Expand Up @@ -39,6 +40,7 @@ if(COMPILER_RT_HAS_UBSAN_MINIMAL)
ARCHS ${UBSAN_SUPPORTED_ARCH}
OBJECT_LIBS RTUbsan_minimal
CFLAGS ${UBSAN_CFLAGS}
LINK_FLAGS ${UBSAN_LINK_FLAGS}
LINK_LIBS ${UBSAN_DYNAMIC_LIBS}
PARENT_TARGET ubsan-minimal)

Expand Down
35 changes: 19 additions & 16 deletions lib/ubsan_minimal/ubsan_minimal_handlers.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <atomic>
#include "sanitizer_common/sanitizer_atomic.h"

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

Expand All @@ -8,37 +10,38 @@ static void message(const char *msg) {
}

static const int kMaxCallerPcs = 20;
static std::atomic<void *> caller_pcs[kMaxCallerPcs];
static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
// Number of elements in caller_pcs. A special value of kMaxCallerPcs + 1 means
// that "too many errors" has already been reported.
static std::atomic<int> caller_pcs_sz;
static __sanitizer::atomic_uint32_t caller_pcs_sz;

__attribute__((noinline))
static bool report_this_error(void *caller) {
if (caller == nullptr) return false;
__attribute__((noinline)) static bool report_this_error(void *caller_p) {
uintptr_t caller = reinterpret_cast<uintptr_t>(caller_p);
if (caller == 0) return false;
while (true) {
int sz = caller_pcs_sz.load(std::memory_order_relaxed);
if (sz > kMaxCallerPcs) return false; // early exit
unsigned sz = __sanitizer::atomic_load_relaxed(&caller_pcs_sz);
if (sz > kMaxCallerPcs) return false; // early exit
// when sz==kMaxCallerPcs print "too many errors", but only when cmpxchg
// succeeds in order to not print it multiple times.
if (sz > 0 && sz < kMaxCallerPcs) {
void *p;
for (int i = 0; i < sz; ++i) {
p = caller_pcs[i].load(std::memory_order_relaxed);
if (p == nullptr) break; // Concurrent update.
uintptr_t p;
for (unsigned i = 0; i < sz; ++i) {
p = __sanitizer::atomic_load_relaxed(&caller_pcs[i]);
if (p == 0) break; // Concurrent update.
if (p == caller) return false;
}
if (p == nullptr) continue; // FIXME: yield?
if (p == 0) continue; // FIXME: yield?
}

if (!caller_pcs_sz.compare_exchange_strong(sz, sz + 1))
continue; // Concurrent update! Try again from the start.
if (!__sanitizer::atomic_compare_exchange_strong(
&caller_pcs_sz, &sz, sz + 1, __sanitizer::memory_order_seq_cst))
continue; // Concurrent update! Try again from the start.

if (sz == kMaxCallerPcs) {
message("ubsan: too many errors\n");
return false;
}
caller_pcs[sz].store(caller, std::memory_order_relaxed);
__sanitizer::atomic_store_relaxed(&caller_pcs[sz], caller);
return true;
}
}
Expand Down
1 change: 1 addition & 0 deletions test/profile/instrprof-darwin-dead-strip.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ int main() { return 0; }
// PROF-NEXT: Hash:
// PROF-NEXT: Counters: 1
// PROF-NEXT: Function count: 1
// PROF-NEXT: Instrumentation level: Front-end
// PROF-NEXT: Functions shown: 1
// PROF-NEXT: Total functions: 1
// PROF-NEXT: Maximum function count: 1
Expand Down
16 changes: 16 additions & 0 deletions test/ubsan/TestCases/Misc/bounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@
// RUN: %run %t 0 3 0 2>&1 | FileCheck %s --check-prefix=CHECK-B-3
// RUN: %run %t 0 0 4 2>&1 | FileCheck %s --check-prefix=CHECK-C-4

int get_int(int *const p __attribute__((pass_object_size(0))), int i) {
// CHECK-A-2: bounds.cpp:[[@LINE+1]]:10: runtime error: index 2 out of bounds for type 'int *'
return p[i];
}

int get_double(double *const p __attribute__((pass_object_size(0))), int i) {
// CHECK-A-2: bounds.cpp:[[@LINE+1]]:10: runtime error: index 2 out of bounds for type 'double *'
return p[i];
}

int main(int argc, char **argv) {
int bar[2];
get_int(bar, argv[1][0] - '0');

double baz[2];
get_double(baz, argv[1][0] - '0');

int arr[2][3][4] = {};

return arr[argv[1][0] - '0'][argv[2][0] - '0'][argv[3][0] - '0'];
Expand Down