void __asan_poison_cxx_array_cookie(uptr p);
SANITIZER_INTERFACE_ATTRIBUTE
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"
#endif // ASAN_INTERFACE_INTERNAL_H
const int kAsanGlobalRedzoneMagic = 0xf9;
const int kAsanInternalHeapMagic = 0xfe;
const int kAsanArrayCookieMagic = 0xac;
+const int kAsanIntraObjectRedzone = 0xbb;
static const uptr kCurrentStackFrameMagic = 0x41B58AB3;
static const uptr kRetiredStackFrameMagic = 0x45E0360E;
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
// ---------------------- Interface ---------------- {{{1
return 0;
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
namespace __lsan {
bool WordIsPoisoned(uptr addr) {
return Red();
case kAsanInternalHeapMagic:
return Yellow();
+ case kAsanIntraObjectRedzone:
+ return Yellow();
default:
return Default();
}
kAsanContiguousContainerOOBMagic);
PrintShadowByte(str, " Array cookie: ",
kAsanArrayCookieMagic);
+ PrintShadowByte(str, " Intra object redzone: ",
+ kAsanIntraObjectRedzone);
PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
}
case kAsanGlobalRedzoneMagic:
bug_descr = "global-buffer-overflow";
break;
+ case kAsanIntraObjectRedzone:
+ bug_descr = "intra-object-overflow";
+ break;
}
}
--- /dev/null
+// 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;
+}