mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -397,7 +397,8 @@ void
|
||||
mrb_mruby_binding_gem_init(mrb_state *mrb)
|
||||
{
|
||||
struct RClass *binding = mrb_define_class(mrb, "Binding", mrb->object_class);
|
||||
MRB_SET_INSTANCE_TT(binding, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(binding, MRB_TT_OBJECT);
|
||||
MRB_UNDEF_ALLOCATOR(binding);
|
||||
mrb_undef_class_method(mrb, binding, "new");
|
||||
mrb_undef_class_method(mrb, binding, "allocate");
|
||||
|
||||
|
||||
@@ -395,7 +395,8 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb)
|
||||
struct RClass *comp;
|
||||
|
||||
comp = mrb_define_class_id(mrb, MRB_SYM(Complex), mrb_class_get_id(mrb, MRB_SYM(Numeric)));
|
||||
MRB_SET_INSTANCE_TT(comp, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(comp, MRB_TT_COMPLEX);
|
||||
MRB_UNDEF_ALLOCATOR(comp);
|
||||
|
||||
mrb_undef_class_method(mrb, comp, "new");
|
||||
mrb_define_class_method(mrb, comp, "rectangular", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
|
||||
|
||||
@@ -492,7 +492,8 @@ mrb_mruby_data_gem_init(mrb_state* mrb)
|
||||
{
|
||||
struct RClass *d;
|
||||
d = mrb_define_class(mrb, "Data", mrb->object_class);
|
||||
MRB_SET_INSTANCE_TT(d, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(d, MRB_TT_STRUCT);
|
||||
MRB_UNDEF_ALLOCATOR(d);
|
||||
|
||||
mrb_undef_class_method(mrb, d, "new");
|
||||
mrb_define_class_method(mrb, d, "define", mrb_data_s_def, MRB_ARGS_ANY());
|
||||
|
||||
@@ -546,7 +546,8 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
|
||||
struct RClass *unbound_method = mrb_define_class_id(mrb, MRB_SYM(UnboundMethod), mrb->object_class);
|
||||
struct RClass *method = mrb_define_class_id(mrb, MRB_SYM(Method), mrb->object_class);
|
||||
|
||||
MRB_SET_INSTANCE_TT(unbound_method, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(unbound_method, MRB_TT_OBJECT);
|
||||
MRB_UNDEF_ALLOCATOR(unbound_method);
|
||||
mrb_undef_class_method(mrb, unbound_method, "new");
|
||||
mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
|
||||
@@ -561,7 +562,8 @@ mrb_mruby_method_gem_init(mrb_state* mrb)
|
||||
mrb_define_method(mrb, unbound_method, "owner", method_owner, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, unbound_method, "name", method_name, MRB_ARGS_NONE());
|
||||
|
||||
MRB_SET_INSTANCE_TT(method, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(method, MRB_TT_OBJECT);
|
||||
MRB_UNDEF_ALLOCATOR(method);
|
||||
mrb_undef_class_method(mrb, method, "new");
|
||||
mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, method, "eql?", method_eql, MRB_ARGS_REQ(1));
|
||||
|
||||
@@ -767,7 +767,8 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
|
||||
struct RClass *rat;
|
||||
|
||||
rat = mrb_define_class_id(mrb, MRB_SYM(Rational), mrb_class_get_id(mrb, MRB_SYM(Numeric)));
|
||||
MRB_SET_INSTANCE_TT(rat, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(rat, MRB_TT_RATIONAL);
|
||||
MRB_UNDEF_ALLOCATOR(rat);
|
||||
mrb_undef_class_method(mrb, rat, "new");
|
||||
mrb_define_class_method(mrb, rat, "_new", rational_s_new, MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, rat, "numerator", rational_numerator, MRB_ARGS_NONE());
|
||||
|
||||
@@ -697,7 +697,8 @@ mrb_mruby_struct_gem_init(mrb_state* mrb)
|
||||
{
|
||||
struct RClass *st;
|
||||
st = mrb_define_class(mrb, "Struct", mrb->object_class);
|
||||
MRB_SET_INSTANCE_TT(st, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(st, MRB_TT_STRUCT);
|
||||
MRB_UNDEF_ALLOCATOR(st);
|
||||
|
||||
mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, MRB_ARGS_ANY()); /* 15.2.18.3.1 */
|
||||
|
||||
|
||||
+3
-3
@@ -1949,10 +1949,10 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
|
||||
else if (ttype == 0) {
|
||||
ttype = MRB_TT_OBJECT;
|
||||
}
|
||||
if (MRB_UNDEF_ALLOCATOR_P(c)) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "allocator undefined for %v", cv);
|
||||
}
|
||||
if (ttype <= MRB_TT_CPTR) {
|
||||
if (ttype == MRB_TT_UNDEF) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "allocator undefined for %v", cv);
|
||||
}
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %v", cv);
|
||||
}
|
||||
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
|
||||
|
||||
@@ -476,7 +476,6 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
|
||||
}
|
||||
tt = MRB_INSTANCE_TT(cls);
|
||||
if (tt != MRB_TT_FALSE &&
|
||||
tt != MRB_TT_UNDEF &&
|
||||
ttype != MRB_TT_SCLASS &&
|
||||
ttype != MRB_TT_ICLASS &&
|
||||
ttype != MRB_TT_ENV &&
|
||||
|
||||
+4
-2
@@ -2227,7 +2227,8 @@ mrb_init_numeric(mrb_state *mrb)
|
||||
|
||||
/* Integer Class */
|
||||
mrb->integer_class = integer = mrb_define_class_id(mrb, MRB_SYM(Integer), numeric); /* 15.2.8 */
|
||||
MRB_SET_INSTANCE_TT(integer, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(integer, MRB_TT_INTEGER);
|
||||
MRB_UNDEF_ALLOCATOR(integer);
|
||||
mrb_undef_class_method_id(mrb, integer, MRB_SYM(new));
|
||||
mrb_define_method_id(mrb, integer, MRB_OPSYM(pow), int_pow, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, integer, MRB_OPSYM(cmp), num_cmp, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
|
||||
@@ -2272,7 +2273,8 @@ mrb_init_numeric(mrb_state *mrb)
|
||||
#ifndef MRB_NO_FLOAT
|
||||
/* Float Class */
|
||||
mrb->float_class = fl = mrb_define_class_id(mrb, MRB_SYM(Float), numeric); /* 15.2.9 */
|
||||
MRB_SET_INSTANCE_TT(fl, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT);
|
||||
MRB_UNDEF_ALLOCATOR(fl);
|
||||
mrb_undef_class_method(mrb, fl, "new");
|
||||
mrb_define_method_id(mrb, fl, MRB_OPSYM(pow), flo_pow, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, fl, MRB_OPSYM(div), flo_div, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
|
||||
|
||||
+2
-3
@@ -490,9 +490,8 @@ mrb_init_proc(mrb_state *mrb)
|
||||
mrb_method_t m;
|
||||
struct RClass *pc = mrb->proc_class = mrb_define_class_id(mrb, MRB_SYM(Proc), mrb->object_class); /* 15.2.17 */
|
||||
|
||||
MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
|
||||
|
||||
MRB_SET_INSTANCE_TT(pc, MRB_TT_UNDEF);
|
||||
MRB_SET_INSTANCE_TT(pc, MRB_TT_PROC);
|
||||
MRB_UNDEF_ALLOCATOR(pc);
|
||||
mrb_define_class_method_id(mrb, pc, MRB_SYM(new), mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
|
||||
mrb_define_method_id(mrb, pc, MRB_SYM(initialize_copy), mrb_proc_init_copy, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, pc, MRB_SYM(arity), proc_arity, MRB_ARGS_NONE()); /* 15.2.17.4.2 */
|
||||
|
||||
Reference in New Issue
Block a user