Make asan_poison_object poison the whole slot

This change poisons the whole slot of the object rather than just the flags.
This allows ASAN to find any reads/writes into the slot after it has been
freed.
This commit is contained in:
Peter Zhu 2024-12-11 12:18:00 -05:00
parent ccded855b6
commit c37bdfa531
Notes: git 2024-12-19 14:14:55 +00:00
2 changed files with 24 additions and 18 deletions

21
gc.c
View File

@ -4309,6 +4309,27 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
#undef C
void
asan_poison_object(VALUE obj)
{
MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
asan_poison_memory_region(ptr, rb_gc_obj_slot_size(obj));
}
void
asan_unpoison_object(VALUE obj, bool newobj_p)
{
MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
asan_unpoison_memory_region(ptr, rb_gc_obj_slot_size(obj), newobj_p);
}
void *
asan_poisoned_object_p(VALUE obj)
{
MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
return __asan_region_is_poisoned(ptr, rb_gc_obj_slot_size(obj));
}
#define asan_unpoisoning_object(obj) \
for (void *poisoned = asan_unpoison_object_temporary(obj), \
*unpoisoning = &poisoned; /* flag to loop just once */ \

View File

@ -124,12 +124,7 @@ asan_poison_memory_region(const volatile void *ptr, size_t size)
*
* @param[in] obj target object.
*/
static inline void
asan_poison_object(VALUE obj)
{
MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
asan_poison_memory_region(ptr, SIZEOF_VALUE);
}
void asan_poison_object(VALUE obj);
#ifdef RUBY_ASAN_ENABLED
#define asan_poison_object_if(ptr, obj) do { \
@ -146,12 +141,7 @@ asan_poison_object(VALUE obj)
* @retval 0 the given object is fully addressable.
* @retval otherwise pointer to first such byte who is poisoned.
*/
static inline void *
asan_poisoned_object_p(VALUE obj)
{
MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
}
void *asan_poisoned_object_p(VALUE obj);
/**
* This function asserts that a (formally poisoned) memory region from ptr to
@ -186,12 +176,7 @@ asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p
* @param[in] obj target object.
* @param[in] malloc_p if the memory region is like a malloc's return value or not.
*/
static inline void
asan_unpoison_object(VALUE obj, bool newobj_p)
{
MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
}
void asan_unpoison_object(VALUE obj, bool newobj_p);
static inline void *
asan_unpoison_object_temporary(VALUE obj)