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
+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