# include "gc_hdrs.h"
#endif
+#ifndef GC_ATTR_NO_SANITIZE_ADDR
+# ifdef ADDRESS_SANITIZER
+# define GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize("address")))
+# else
+# define GC_ATTR_NO_SANITIZE_ADDR /* empty */
+# endif
+#endif /* !GC_ATTR_NO_SANITIZE_ADDR */
+
+#ifndef GC_ATTR_NO_SANITIZE_MEMORY
+# ifdef MEMORY_SANITIZER
+# define GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
+# else
+# define GC_ATTR_NO_SANITIZE_MEMORY /* empty */
+# endif
+#endif /* !GC_ATTR_NO_SANITIZE_MEMORY */
+
#ifndef GC_ATTR_UNUSED
# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
# define GC_ATTR_UNUSED __attribute__((__unused__))
# endif
#endif /* !GC_WORD_C */
+#if defined(__has_feature)
+ /* __has_feature() is supported. */
+# if __has_feature(address_sanitizer) && !defined(ADDRESS_SANITIZER)
+# define ADDRESS_SANITIZER
+# endif
+# if __has_feature(memory_sanitizer) && !defined(MEMORY_SANITIZER)
+# define MEMORY_SANITIZER
+# endif
+#endif
+
#if defined(SPARC)
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
/* include assembly code to do it well. */
/* ctxt is either a pointer to a ucontext_t we generated, or NULL. */
GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
volatile ptr_t arg)
+ GC_ATTR_NO_SANITIZE_ADDR
{
volatile int dummy;
void * context = 0;
*/
GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack,
mse *mark_stack_limit)
+ GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY
{
signed_word credit = HBLKSIZE; /* Remaining credit for marking work */
ptr_t current_p; /* Pointer to current candidate ptr. */
* change.
*/
GC_API void GC_CALL GC_push_all_eager(char *bottom, char *top)
+ GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY
{
word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
}
#endif /* NETBSD */
+#if defined(ADDRESS_SANITIZER) && (defined(UNIX_LIKE) \
+ || defined(NEED_FIND_LIMIT) || defined(MPROTECT_VDB))
+ /* To tell ASan to allow GC to use its own SIGBUS/SEGV handlers. */
+ const char *__asan_default_options(void)
+ {
+ return "allow_user_segv_handler=1";
+ }
+#endif
+
#ifdef OPENBSD
static struct sigaction old_segv_act;
STATIC sigjmp_buf GC_jmp_buf_openbsd;
# ifdef HAVE_SIGBUS
old_bus_handler = signal(SIGBUS, h);
# endif
+# endif
+# if defined(CPPCHECK) && defined(ADDRESS_SANITIZER)
+ GC_noop1((word)&__asan_default_options);
# endif
}
# endif /* NEED_FIND_LIMIT || UNIX_LIKE */
# elif defined(MSWINCE)
/* MPROTECT_VDB is unsupported for WinCE at present. */
/* FIXME: implement it (if possible). */
+# endif
+# if defined(CPPCHECK) && defined(ADDRESS_SANITIZER)
+ GC_noop1((word)&__asan_default_options);
# endif
}
#endif /* !DARWIN */
max_heap_sz += max_heap_sz * NFRAMES / 4;
# endif
# endif
+# endif
+# ifdef MEMORY_SANITIZER
+ max_heap_sz += max_heap_sz / 4;
# endif
max_heap_sz *= n_tests;
# if defined(USE_MMAP) || defined(MSWIN32)
A* a = static_cast<A*>(Undisguise(as[i]));
B* b = static_cast<B*>(Undisguise(bs[i]));
a->Test( i );
- delete a;
+# if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
+ // Workaround for ASan/MSan: the linker uses operator delete
+ // implementation from libclang_rt instead of gc_cpp (thus
+ // causing incompatible alloc/free).
+ GC_FREE(a);
+# else
+ delete a;
+# endif
b->Test( i );
B::Deleting( 1 );
delete b;