mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
variable.c (mrb_exc_const_get): E_XXX_ERROR should not call const_missing
As #6359 pointed out, calling const_missing hook from E_XXX_ERROR (that calls mrb_exc_get_id()) can be an attack vector. Since E_XXX_ERROR is supposed to be a defined error class, we think that the situation where it is undefined and the const_missing hook is called should be detected as an error; fix #6359
This commit is contained in:
@@ -182,6 +182,7 @@ mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
|
||||
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_bool mrb_ident_p(const char *s, mrb_int len);
|
||||
mrb_value mrb_exc_const_get(mrb_state *mrb, mrb_sym sym);
|
||||
|
||||
/* GC functions */
|
||||
void mrb_gc_mark_gv(mrb_state*);
|
||||
|
||||
+4
-2
@@ -659,7 +659,7 @@ mrb_class_get_id(mrb_state *mrb, mrb_sym name)
|
||||
MRB_API struct RClass*
|
||||
mrb_exc_get_id(mrb_state *mrb, mrb_sym name)
|
||||
{
|
||||
mrb_value c = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), name);
|
||||
mrb_value c = mrb_exc_const_get(mrb, name);
|
||||
|
||||
if (!mrb_class_p(c)) {
|
||||
mrb_raise(mrb, E_EXCEPTION, "exception corrupted");
|
||||
@@ -670,7 +670,9 @@ mrb_exc_get_id(mrb_state *mrb, mrb_sym name)
|
||||
if (e == E_EXCEPTION)
|
||||
return exc;
|
||||
}
|
||||
return E_EXCEPTION;
|
||||
mrb_raise(mrb, E_EXCEPTION, "non-exception raised");
|
||||
/* not reached */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MRB_API struct RClass*
|
||||
|
||||
+24
-6
@@ -764,7 +764,7 @@ mod_const_check(mrb_state *mrb, mrb_value mod)
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip)
|
||||
const_get_nohook(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip)
|
||||
{
|
||||
struct RClass *c = base;
|
||||
mrb_value v;
|
||||
@@ -785,12 +785,30 @@ L_RETRY:
|
||||
retry = TRUE;
|
||||
goto L_RETRY;
|
||||
}
|
||||
mrb_value mod = mrb_obj_value(base);
|
||||
if (mrb_func_basic_p(mrb, mod, MRB_SYM(const_missing), mrb_mod_const_missing)) {
|
||||
return mrb_const_missing(mrb, mod, sym);
|
||||
return mrb_undef_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip)
|
||||
{
|
||||
mrb_value v = const_get_nohook(mrb, base, sym, skip);
|
||||
|
||||
/* call const_missing hook */
|
||||
if (mrb_undef_p(v)) {
|
||||
mrb_value mod = mrb_obj_value(base);
|
||||
if (mrb_func_basic_p(mrb, mod, MRB_SYM(const_missing), mrb_mod_const_missing)) {
|
||||
return mrb_const_missing(mrb, mod, sym);
|
||||
}
|
||||
mrb_value name = mrb_symbol_value(sym);
|
||||
return mrb_funcall_argv(mrb, mod, MRB_SYM(const_missing), 1, &name);
|
||||
}
|
||||
mrb_value name = mrb_symbol_value(sym);
|
||||
return mrb_funcall_argv(mrb, mod, MRB_SYM(const_missing), 1, &name);
|
||||
return v;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_exc_const_get(mrb_state *mrb, mrb_sym sym)
|
||||
{
|
||||
return const_get_nohook(mrb, mrb->object_class, sym, FALSE);
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
|
||||
Reference in New Issue
Block a user