summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-01 22:52:35 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-01 22:52:35 +0000
commit1286674bb9855d69f3448fb76c2721c5ac38b84c (patch)
tree7843fbcb9e096070fd6417f6bf997e439fb99d7e
parent990df873029a632c06dee9de9768bda8400fe922 (diff)
unpoison / poison objects while walking the heap
This fixes some ASAN errors git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67405 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--internal.h10
-rw-r--r--iseq.c14
2 files changed, 24 insertions, 0 deletions
diff --git a/internal.h b/internal.h
index 50a20a2bf6..f2c9c238eb 100644
--- a/internal.h
+++ b/internal.h
@@ -105,6 +105,7 @@ extern "C" {
# define __asan_poison_memory_region(x, y)
# define __asan_unpoison_memory_region(x, y)
# define __asan_region_is_poisoned(x, y) 0
+# define poisoned_object_p(x) 0
#endif
#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
@@ -132,6 +133,15 @@ poison_object(VALUE obj)
poison_memory_region(ptr, SIZEOF_VALUE);
}
+#if __has_feature(address_sanitizer)
+static inline void *
+poisoned_object_p(VALUE obj)
+{
+ struct RVALUE *ptr = (void *)obj;
+ return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
+}
+#endif
+
static inline void
unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
{
diff --git a/iseq.c b/iseq.c
index 864e92645c..afe03777fc 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1011,10 +1011,17 @@ remove_coverage_i(void *vstart, void *vend, size_t stride, void *data)
{
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
+ void *ptr = poisoned_object_p(v);
+ unpoison_object(v, false);
+
if (rb_obj_is_iseq(v)) {
rb_iseq_t *iseq = (rb_iseq_t *)v;
ISEQ_COVERAGE_SET(iseq, Qnil);
}
+
+ if (ptr) {
+ poison_object(v);
+ }
}
return 0;
}
@@ -3156,9 +3163,16 @@ trace_set_i(void *vstart, void *vend, size_t stride, void *data)
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
+ void *ptr = poisoned_object_p(v);
+ unpoison_object(v, false);
+
if (rb_obj_is_iseq(v)) {
rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events);
}
+
+ if (ptr) {
+ poison_object(v);
+ }
}
return 0;
}