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:
Yukihiro "Matz" Matsumoto
2024-10-11 08:16:24 +09:00
parent b5801cd730
commit fa68e634a7
3 changed files with 29 additions and 8 deletions
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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