forked from OSchip/llvm-project
[asan] the run-time part of intra-object-overflow detector (-fsanitize-address-field-padding=1). Note that all of this is still experimental; don't use unless you are brave.
llvm-svn: 220013
This commit is contained in:
parent
cf3ab58e47
commit
c9855da6d9
|
@ -173,6 +173,10 @@ extern "C" {
|
||||||
void __asan_poison_cxx_array_cookie(uptr p);
|
void __asan_poison_cxx_array_cookie(uptr p);
|
||||||
SANITIZER_INTERFACE_ATTRIBUTE
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
uptr __asan_load_cxx_array_cookie(uptr *p);
|
uptr __asan_load_cxx_array_cookie(uptr *p);
|
||||||
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
|
void __asan_poison_intra_object_redzone(uptr p, uptr size);
|
||||||
|
SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
|
void __asan_unpoison_intra_object_redzone(uptr p, uptr size);
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
#endif // ASAN_INTERFACE_INTERNAL_H
|
#endif // ASAN_INTERFACE_INTERNAL_H
|
||||||
|
|
|
@ -135,6 +135,7 @@ const int kAsanStackUseAfterScopeMagic = 0xf8;
|
||||||
const int kAsanGlobalRedzoneMagic = 0xf9;
|
const int kAsanGlobalRedzoneMagic = 0xf9;
|
||||||
const int kAsanInternalHeapMagic = 0xfe;
|
const int kAsanInternalHeapMagic = 0xfe;
|
||||||
const int kAsanArrayCookieMagic = 0xac;
|
const int kAsanArrayCookieMagic = 0xac;
|
||||||
|
const int kAsanIntraObjectRedzone = 0xbb;
|
||||||
|
|
||||||
static const uptr kCurrentStackFrameMagic = 0x41B58AB3;
|
static const uptr kCurrentStackFrameMagic = 0x41B58AB3;
|
||||||
static const uptr kRetiredStackFrameMagic = 0x45E0360E;
|
static const uptr kRetiredStackFrameMagic = 0x45E0360E;
|
||||||
|
|
|
@ -61,6 +61,27 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
|
||||||
FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
|
FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
|
||||||
|
uptr end = ptr + size;
|
||||||
|
if (common_flags()->verbosity) {
|
||||||
|
Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n",
|
||||||
|
poison ? "" : "un", ptr, end, size);
|
||||||
|
if (common_flags()->verbosity >= 2)
|
||||||
|
PRINT_CURRENT_STACK();
|
||||||
|
}
|
||||||
|
CHECK(size);
|
||||||
|
CHECK_LE(size, 4096);
|
||||||
|
CHECK(IsAligned(end, SHADOW_GRANULARITY));
|
||||||
|
if (!IsAligned(ptr, SHADOW_GRANULARITY)) {
|
||||||
|
*(u8 *)MemToShadow(ptr) =
|
||||||
|
poison ? static_cast<u8>(ptr % SHADOW_GRANULARITY) : 0;
|
||||||
|
ptr |= SHADOW_GRANULARITY - 1;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
for (; ptr < end; ptr += SHADOW_GRANULARITY)
|
||||||
|
*(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace __asan
|
} // namespace __asan
|
||||||
|
|
||||||
// ---------------------- Interface ---------------- {{{1
|
// ---------------------- Interface ---------------- {{{1
|
||||||
|
@ -375,6 +396,17 @@ int __sanitizer_verify_contiguous_container(const void *beg_p,
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
|
void __asan_poison_intra_object_redzone(uptr ptr, uptr size) {
|
||||||
|
AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||||
|
void __asan_unpoison_intra_object_redzone(uptr ptr, uptr size) {
|
||||||
|
AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, false);
|
||||||
|
}
|
||||||
|
|
||||||
// --- Implementation of LSan-specific functions --- {{{1
|
// --- Implementation of LSan-specific functions --- {{{1
|
||||||
namespace __lsan {
|
namespace __lsan {
|
||||||
bool WordIsPoisoned(uptr addr) {
|
bool WordIsPoisoned(uptr addr) {
|
||||||
|
|
|
@ -94,6 +94,8 @@ class Decorator: public __sanitizer::SanitizerCommonDecorator {
|
||||||
return Red();
|
return Red();
|
||||||
case kAsanInternalHeapMagic:
|
case kAsanInternalHeapMagic:
|
||||||
return Yellow();
|
return Yellow();
|
||||||
|
case kAsanIntraObjectRedzone:
|
||||||
|
return Yellow();
|
||||||
default:
|
default:
|
||||||
return Default();
|
return Default();
|
||||||
}
|
}
|
||||||
|
@ -168,6 +170,8 @@ static void PrintLegend(InternalScopedString *str) {
|
||||||
kAsanContiguousContainerOOBMagic);
|
kAsanContiguousContainerOOBMagic);
|
||||||
PrintShadowByte(str, " Array cookie: ",
|
PrintShadowByte(str, " Array cookie: ",
|
||||||
kAsanArrayCookieMagic);
|
kAsanArrayCookieMagic);
|
||||||
|
PrintShadowByte(str, " Intra object redzone: ",
|
||||||
|
kAsanIntraObjectRedzone);
|
||||||
PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
|
PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,6 +985,9 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||||
case kAsanGlobalRedzoneMagic:
|
case kAsanGlobalRedzoneMagic:
|
||||||
bug_descr = "global-buffer-overflow";
|
bug_descr = "global-buffer-overflow";
|
||||||
break;
|
break;
|
||||||
|
case kAsanIntraObjectRedzone:
|
||||||
|
bug_descr = "intra-object-overflow";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// RUN: %clangxx_asan -O0 -fsanitize-address-field-padding=1 %s -o %t
|
||||||
|
// RUN: not %run %t 11 2>&1 | FileCheck %s
|
||||||
|
// RUN: %run %t 10
|
||||||
|
//
|
||||||
|
// FIXME: fix 32-bits.
|
||||||
|
// REQUIRES: asan-64-bits
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
Foo() : pre1(1), pre2(2), post1(3), post2(4) {
|
||||||
|
}
|
||||||
|
virtual ~Foo() {
|
||||||
|
}
|
||||||
|
void set(int i, int val) { a[i] = val; }
|
||||||
|
// CHECK: ERROR: AddressSanitizer: intra-object-overflow
|
||||||
|
// CHECK: #0 {{.*}}Foo::set{{.*}}intra-object-overflow.cc:[[@LINE-2]]
|
||||||
|
private:
|
||||||
|
int pre1, pre2;
|
||||||
|
int a[11];
|
||||||
|
int post1, post2;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int idx = argc == 2 ? atoi(argv[1]) : 0;
|
||||||
|
Foo *foo = new Foo;
|
||||||
|
foo->set(idx, 42);
|
||||||
|
// CHECK: #1 {{.*}}main{{.*}}intra-object-overflow.cc:[[@LINE-1]]
|
||||||
|
// CHECK: is located 84 bytes inside of 128-byte region
|
||||||
|
delete foo;
|
||||||
|
}
|
Loading…
Reference in New Issue