[asan] implement an experimental detector of ODR violations. Not tested yet outside of a tiny test, may need tuning.

llvm-svn: 207210
This commit is contained in:
Kostya Serebryany 2014-04-25 08:58:28 +00:00
parent 56a18f02ea
commit e91930a7e6
6 changed files with 56 additions and 0 deletions

View File

@ -64,6 +64,7 @@ struct Flags {
bool start_deactivated;
int detect_invalid_pointer_pairs;
bool detect_container_overflow;
bool detect_odr_violation;
};
extern Flags asan_flags_dont_use_directly;

View File

@ -92,6 +92,18 @@ static void RegisterGlobal(const Global *g) {
CHECK(AddrIsInMem(g->beg));
CHECK(AddrIsAlignedByGranularity(g->beg));
CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
if (flags()->detect_odr_violation) {
// Try detecting ODR (One Definition Rule) violation, i.e. the situation
// where two globals with the same name are defined in different modules.
if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
// This check may not be enough: if the first global is much larger
// the entire redzone of the second global may be within the first global.
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
if (g->beg == l->g->beg)
ReportODRViolation(g, l->g);
}
}
}
if (flags()->poison_heap)
PoisonRedZones(*g);
ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals;

View File

@ -729,6 +729,19 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
}
void ReportODRViolation(const __asan_global *g1, const __asan_global *g2) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg);
Printf("%s", d.EndWarning());
Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1->module_name);
Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2->module_name);
Report("HINT: if you don't care about these warnings you may set "
"ASAN_OPTIONS=detect_odr_violation=0\n");
ReportErrorSummary("odr-violation", g1->module_name, 0, g1->name);
}
// ----------------------- CheckForInvalidPointerPair ----------- {{{1
static NOINLINE void
ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {

View File

@ -54,6 +54,9 @@ void NORETURN
ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid,
uptr new_mid, StackTrace *stack);
void NORETURN
ReportODRViolation(const __asan_global *g1, const __asan_global *g2);
// Mac-specific errors and warnings.
void WarnMacFreeUnallocated(
uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack);

View File

@ -225,6 +225,10 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
"detect_container_overflow",
"If true, honor the container overflow annotations. "
"See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow");
ParseFlag(str, &f->detect_odr_violation,
"detect_odr_violation",
"If true, detect violation of One-Definition-Rule (ODR) ");
}
void InitializeFlags(Flags *f, const char *env) {

View File

@ -0,0 +1,23 @@
// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so
// RUN: %clangxx_asan %s %t.so -Wl,-R. -o %t
// RUN: ASAN_OPTIONS=detect_odr_violation=1 not %t 2>&1 | FileCheck %s
// RUN: ASAN_OPTIONS=detect_odr_violation=0 %t 2>&1 | FileCheck %s --check-prefix=DISABLED
// RUN: %t 2>&1 | FileCheck %s --check-prefix=DISABLED
#ifndef SZ
# define SZ 4
#endif
#if BUILD_SO
char G[SZ];
#else
#include <stdio.h>
char G[100];
int main(int argc, char **argv) {
printf("PASS: %p\n", &G);
}
#endif
// CHECK: ERROR: AddressSanitizer: odr-violation
// CHECK: size=100 G
// DISABLED: PASS