Calling obj_info during sweep is unsafe

`obj_info` will look at references of objects in some cases (for example
it will try to access path information on ISeq objects).  But during the
sweep phase, if the referenced object is collected before `obj_info` is
called, then it could be a bad ref and a segv will occur.

For example:

A -> B

Sweep phase:

1. obj_info(B)
2. Sweep and free B
3. obj_info(A); A tries to read B
4. SEGV

This commit simply removes the call to `obj_info` during the sweep
phase.
This commit is contained in:
Aaron Patterson 2019-05-08 15:19:59 -07:00
parent a95ca6d5e9
commit c53f87943e
No known key found for this signature in database
GPG key ID: 953170BCB4FFAFC6

13
gc.c
View file

@ -1064,6 +1064,7 @@ tick(void)
#define RVALUE_AGE_SHIFT 5 /* FL_PROMOTED0 bit */ #define RVALUE_AGE_SHIFT 5 /* FL_PROMOTED0 bit */
static int rgengc_remembered(rb_objspace_t *objspace, VALUE obj); static int rgengc_remembered(rb_objspace_t *objspace, VALUE obj);
static int rgengc_remembered_sweep(rb_objspace_t *objspace, VALUE obj);
static int rgengc_remember(rb_objspace_t *objspace, VALUE obj); static int rgengc_remember(rb_objspace_t *objspace, VALUE obj);
static void rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap); static void rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap);
static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap); static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap);
@ -3822,7 +3823,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
#if USE_RGENGC && RGENGC_CHECK_MODE #if USE_RGENGC && RGENGC_CHECK_MODE
if (!is_full_marking(objspace)) { if (!is_full_marking(objspace)) {
if (RVALUE_OLD_P((VALUE)p)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p); if (RVALUE_OLD_P((VALUE)p)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p);
if (rgengc_remembered(objspace, (VALUE)p)) rb_bug("page_sweep: %p - remembered.", (void *)p); if (rgengc_remembered_sweep(objspace, (VALUE)p)) rb_bug("page_sweep: %p - remembered.", (void *)p);
} }
#endif #endif
if (obj_free(objspace, (VALUE)p)) { if (obj_free(objspace, (VALUE)p)) {
@ -6294,14 +6295,20 @@ rgengc_remember(rb_objspace_t *objspace, VALUE obj)
} }
static int static int
rgengc_remembered(rb_objspace_t *objspace, VALUE obj) rgengc_remembered_sweep(rb_objspace_t *objspace, VALUE obj)
{ {
int result = rgengc_remembersetbits_get(objspace, obj); int result = rgengc_remembersetbits_get(objspace, obj);
check_rvalue_consistency(obj); check_rvalue_consistency(obj);
gc_report(6, objspace, "rgengc_remembered: %s\n", obj_info(obj));
return result; return result;
} }
static int
rgengc_remembered(rb_objspace_t *objspace, VALUE obj)
{
gc_report(6, objspace, "rgengc_remembered: %s\n", obj_info(obj));
return rgengc_remembered_sweep(objspace, obj);
}
#ifndef PROFILE_REMEMBERSET_MARK #ifndef PROFILE_REMEMBERSET_MARK
#define PROFILE_REMEMBERSET_MARK 0 #define PROFILE_REMEMBERSET_MARK 0
#endif #endif