From 01da5e13920989b6c7ab97900659f570bdcb78f2 Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 13 Aug 2021 15:04:19 +0900 Subject: Check the class with `I` specifier of `mrb_get_args()` Previously, the `I` specifier only checked if the object was `MRB_TT_ISTRUCT`. So it was at risk of getting pointers to different C structs if multiple classes were to use the `MRB_TT_ISTRUCT` instance. Change this behavior and change the C argument corresponding to the `I` specifier to `(void *, struct RClass)`. This change is not compatible with the previous mruby. Please note that if the user uses the previous specifications, `SIGSEGV` may occur or the machine stack may be destroyed. resolve #5527 --- src/class.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 6cf93414a..1b2beafe0 100644 --- a/src/class.c +++ b/src/class.c @@ -896,7 +896,7 @@ void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); b: boolean [mrb_bool] n: String/Symbol [mrb_sym] d: data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil - I: inline struct [void*] + I: inline struct [void*,struct RClass] &: block [mrb_value] &! raises exception if no block given *: rest argument [const mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack |: optional Following arguments are optional @@ -1141,11 +1141,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) case 'I': { void* *p; + struct RClass *klass; mrb_value ss; p = va_arg(ap, void**); + klass = va_arg(ap, struct RClass*); if (i < argc) { ss = argv[i++]; + if (!mrb_obj_is_kind_of(mrb, ss, klass)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%v is not a %C", ss, klass); + } if (!mrb_istruct_p(ss)) { mrb_raisef(mrb, E_TYPE_ERROR, "%v is not inline struct", ss); -- cgit v1.2.3