1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

merge revision(s) d6c5a30cfdf658280338dbb8c8b17fab3190b928,a2d4e1cda68a49980a4f9f353f400efbde7e7884: [Backport #18392]

ObjectSpace::WeakMap#inspect: check if living object [Bug #18392]

	---
	 gc.c                      | 29 +++++++++++++++++++++++------
	 test/ruby/test_weakmap.rb |  9 +++++++++
	 2 files changed, 32 insertions(+), 6 deletions(-)

	Fixed the check order in wmap_live_p [Bug #18392]

	Check if the object is a pointer to heap before check the flag in
	that object.
	---
	 gc.c | 35 ++++++++++++++++++++++-------------
	 1 file changed, 22 insertions(+), 13 deletions(-)
This commit is contained in:
nagachika 2022-03-12 16:28:26 +09:00
parent 09b27ec6a9
commit f2d996dcff
3 changed files with 55 additions and 20 deletions

64
gc.c
View file

@ -1202,6 +1202,14 @@ tick(void)
#define MEASURE_LINE(expr) expr
#endif /* USE_TICK_T */
static inline void *
asan_unpoison_object_temporary(VALUE obj)
{
void *ptr = asan_poisoned_object_p(obj);
asan_unpoison_object(obj, false);
return ptr;
}
#define FL_CHECK2(name, x, pred) \
((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? \
(rb_bug(name": SPECIAL_CONST (%p)", (void *)(x)), 0) : (pred))
@ -3853,16 +3861,6 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
ATOMIC_SET(finalizing, 0);
}
PUREFUNC(static inline int is_id_value(rb_objspace_t *objspace, VALUE ptr));
static inline int
is_id_value(rb_objspace_t *objspace, VALUE ptr)
{
if (!is_pointer_to_heap(objspace, (void *)ptr)) return FALSE;
if (BUILTIN_TYPE(ptr) > T_FIXNUM) return FALSE;
if (BUILTIN_TYPE(ptr) == T_ICLASS) return FALSE;
return TRUE;
}
static inline int
heap_is_swept_object(rb_objspace_t *objspace, rb_heap_t *heap, VALUE ptr)
{
@ -11178,9 +11176,20 @@ wmap_allocate(VALUE klass)
static int
wmap_live_p(rb_objspace_t *objspace, VALUE obj)
{
if (!FL_ABLE(obj)) return TRUE;
if (!is_id_value(objspace, obj)) return FALSE;
if (!is_live_object(objspace, obj)) return FALSE;
if (SPECIAL_CONST_P(obj)) return TRUE;
if (is_pointer_to_heap(objspace, (void *)obj)) {
void *poisoned = asan_unpoison_object_temporary(obj);
enum ruby_value_type t = BUILTIN_TYPE(obj);
int ret = (!(t == T_NONE || t >= T_FIXNUM || t == T_ICLASS) &&
is_live_object(objspace, obj));
if (poisoned) {
asan_poison_object(obj);
}
return ret;
}
return TRUE;
}
@ -11246,10 +11255,26 @@ struct wmap_iter_arg {
VALUE value;
};
static VALUE
wmap_inspect_append(rb_objspace_t *objspace, VALUE str, VALUE obj)
{
if (SPECIAL_CONST_P(obj)) {
return rb_str_append(str, rb_inspect(obj));
}
else if (wmap_live_p(objspace, obj)) {
return rb_str_append(str, rb_any_to_s(obj));
}
else {
return rb_str_catf(str, "#<collected:%p>", (void*)obj);
}
}
static int
wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
{
VALUE str = (VALUE)arg;
struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
rb_objspace_t *objspace = argp->objspace;
VALUE str = argp->value;
VALUE k = (VALUE)key, v = (VALUE)val;
if (RSTRING_PTR(str)[0] == '#') {
@ -11259,11 +11284,9 @@ wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
rb_str_cat2(str, ": ");
RSTRING_PTR(str)[0] = '#';
}
k = SPECIAL_CONST_P(k) ? rb_inspect(k) : rb_any_to_s(k);
rb_str_append(str, k);
wmap_inspect_append(objspace, str, k);
rb_str_cat2(str, " => ");
v = SPECIAL_CONST_P(v) ? rb_inspect(v) : rb_any_to_s(v);
rb_str_append(str, v);
wmap_inspect_append(objspace, str, v);
return ST_CONTINUE;
}
@ -11274,11 +11297,14 @@ wmap_inspect(VALUE self)
VALUE str;
VALUE c = rb_class_name(CLASS_OF(self));
struct weakmap *w;
struct wmap_iter_arg args;
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self);
if (w->wmap2obj) {
st_foreach(w->wmap2obj, wmap_inspect_i, str);
args.objspace = &rb_objspace;
args.value = str;
st_foreach(w->wmap2obj, wmap_inspect_i, (st_data_t)&args);
}
RSTRING_PTR(str)[0] = '#';
rb_str_cat2(str, ">");

View file

@ -73,6 +73,15 @@ class TestWeakMap < Test::Unit::TestCase
@wm.inspect)
end
def test_inspect_garbage
1000.times do |i|
@wm[i] = Object.new
@wm.inspect
end
assert_match(/\A\#<#{@wm.class.name}:[^:]++:(?:\s\d+\s=>\s\#<(?:Object|collected):[^:<>]*+>(?:,|>\z))+/,
@wm.inspect)
end
def test_each
m = __callee__[/test_(.*)/, 1]
x1 = Object.new

View file

@ -12,7 +12,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 4
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 185
#define RUBY_PATCHLEVEL 186
#define RUBY_RELEASE_YEAR 2022
#define RUBY_RELEASE_MONTH 3