diff options
| author | dearblue <[email protected]> | 2021-08-13 15:04:19 +0900 |
|---|---|---|
| committer | dearblue <[email protected]> | 2021-08-13 15:04:19 +0900 |
| commit | 01da5e13920989b6c7ab97900659f570bdcb78f2 (patch) | |
| tree | 5e0b9eea1c7ab20c8e018b54dce9f6f4af6ff36e | |
| parent | 9e74aad43c8a7652c3cc0ffdc282c66ea866999b (diff) | |
| download | mruby-01da5e13920989b6c7ab97900659f570bdcb78f2.tar.gz mruby-01da5e13920989b6c7ab97900659f570bdcb78f2.zip | |
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
| -rw-r--r-- | include/mruby.h | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-inline-struct/test/inline.c | 3 | ||||
| -rw-r--r-- | src/class.c | 7 |
3 files changed, 9 insertions, 3 deletions
diff --git a/include/mruby.h b/include/mruby.h index 77f862356..4d2b65254 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -901,7 +901,7 @@ MRB_API struct RClass* mrb_define_module_under_id(mrb_state *mrb, struct RClass * | `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 arguments | const {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; `*!` avoid copy of the stack. | * | <code>\|</code> | optional | | After this spec following specs would be optional. | diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c index 6764b1af4..16d16fa4d 100644 --- a/mrbgems/mruby-inline-struct/test/inline.c +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -57,7 +57,8 @@ static mrb_value istruct_test_test_receive_direct(mrb_state *mrb, mrb_value self) { char *ptr; - mrb_get_args(mrb, "I", &ptr); + struct RClass *klass = mrb_class_get(mrb, "InlineStructTest"); + mrb_get_args(mrb, "I", &ptr, klass); return mrb_bool_value(ptr[0] == 's'); } 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); |
