Prohibit Class#allocate in a different way

The method introduced by #5979 causes a fault by swapping classes.

```console
% bin/mruby -e 'Method = Proc; p Object.method(:inspect)'
zsh: segmentation fault (core dumped)  bin/mruby -e 'Method = Proc; p Object.method(:inspect)'
```

After applying this patch, a `TypeError` exception will be raised.

```console
% bin/mruby -e 'Method = Proc; p Object.method(:inspect)'
trace (most recent call last):
        [1] -e:1
-e:1:in method: allocation failure of Proc (TypeError)
```

However, if the `mrb_vtype` is the same object, the same care must still be taken as before.

```console
% bin/mruby -e 'Method = Binding; p method(:puts).eval("12345")'
trace (most recent call last):
        [1] -e:1
-e:1:in eval: wrong argument type nil (expected Proc) (TypeError)
```
This commit is contained in:
dearblue
2023-12-22 21:59:34 +09:00
parent fa75865a33
commit 8ecfacefca
11 changed files with 28 additions and 17 deletions
+5 -1
View File
@@ -57,7 +57,8 @@ mrb_class(mrb_state *mrb, mrb_value v)
19: is_prepended
18: is_origin
17: is_inherited (used by method cache)
6-16: unused
7-16: unused
6: prohibit Class#allocate
0-5: instance type
*/
#define MRB_FL_CLASS_IS_PREPENDED (1 << 19)
@@ -74,6 +75,9 @@ mrb_class(mrb_state *mrb, mrb_value v)
#define MRB_INSTANCE_TT_MASK (0x1F)
#define MRB_SET_INSTANCE_TT(c, tt) ((c)->flags = (((c)->flags & ~MRB_INSTANCE_TT_MASK) | (char)(tt)))
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)((c)->flags & MRB_INSTANCE_TT_MASK)
#define MRB_FL_UNDEF_ALLOCATE (1 << 6)
#define MRB_UNDEF_ALLOCATOR(c) (mrb_assert((c)->tt == MRB_TT_CLASS), (c)->flags |= MRB_FL_UNDEF_ALLOCATE)
#define MRB_UNDEF_ALLOCATOR_P(c) ((c)->flags & MRB_FL_UNDEF_ALLOCATE)
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);