From 87d1bbe94794304d92fc9a4af5cf17eab5d1534c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Apr 2020 16:44:39 +0900 Subject: Add new function `mrb_singleton_class_ptr()`; ref #4973 The difference between `mrb_singleton_class` and `mrb_singleton_class_ptr`: - `mrb_singleton_class_ptr` returns `struct RClass*`. - `mrb_singleton_class_ptr` returns `NULL` on immediate values where `mrb_singleton_class` raises exceptions. --- src/class.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index c49f0f474..b0af74e74 100644 --- a/src/class.c +++ b/src/class.c @@ -1242,33 +1242,45 @@ mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod) return mod; } -MRB_API mrb_value -mrb_singleton_class(mrb_state *mrb, mrb_value v) +/* returns mrb_class_ptr(mrb_singleton_class()) */ +/* except that it return NULL for immediate values */ +MRB_API struct RClass* +mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v) { struct RBasic *obj; switch (mrb_type(v)) { case MRB_TT_FALSE: if (mrb_nil_p(v)) - return mrb_obj_value(mrb->nil_class); - return mrb_obj_value(mrb->false_class); + return mrb->nil_class; + return mrb->false_class; case MRB_TT_TRUE: - return mrb_obj_value(mrb->true_class); + return mrb->true_class; case MRB_TT_CPTR: - return mrb_obj_value(mrb->object_class); + return mrb->object_class; case MRB_TT_SYMBOL: case MRB_TT_FIXNUM: #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #endif - mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); - return mrb_nil_value(); /* not reached */ + return NULL; default: break; } obj = mrb_basic_ptr(v); prepare_singleton_class(mrb, obj); - return mrb_obj_value(obj->c); + return obj->c; +} + +MRB_API mrb_value +mrb_singleton_class(mrb_state *mrb, mrb_value v) +{ + struct RClass *c = mrb_singleton_class_ptr(mrb, v); + + if (c == NULL) { + mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); + } + return mrb_obj_value(c); } MRB_API void -- cgit v1.2.3 From 49b2e8c3a9ef9a0ba115c000327c0bcd62911e44 Mon Sep 17 00:00:00 2001 From: dearblue Date: Wed, 29 Apr 2020 16:57:25 +0900 Subject: Makes `mrb_any_to_s()` accept an object whose class is `NULL` When using `mrb_any_to_s()` for debugging purposes, giving an object whose class is `NULL` no longer causes a SIGSEGV and no crash. This is achieved by making `mrb_class_name()` and `mrb_str_cat_cstr()` null safe. --- src/class.c | 5 ++++- src/string.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index b0af74e74..d30edd41e 100644 --- a/src/class.c +++ b/src/class.c @@ -1728,7 +1728,10 @@ mrb_class_real(struct RClass* cl) MRB_API const char* mrb_class_name(mrb_state *mrb, struct RClass* c) { - mrb_value name = class_name_str(mrb, c); + mrb_value name; + + if (c == NULL) return NULL; + name = class_name_str(mrb, c); return RSTRING_PTR(name); } diff --git a/src/string.c b/src/string.c index 458c511dc..44e3c9069 100644 --- a/src/string.c +++ b/src/string.c @@ -2759,7 +2759,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr) { - return mrb_str_cat(mrb, str, ptr, strlen(ptr)); + return mrb_str_cat(mrb, str, ptr, ptr ? strlen(ptr) : 0); } MRB_API mrb_value -- cgit v1.2.3