Early conversion of mesg to a string object in mrb_sys_fail()

`mrb_class_get_id()` may call the `#const_missing` method.
Therefore, if the `mesg` string originates from a string object, it may reference an invalid address.

And since `errno` might also change during the call to `#const_missing`, save this as well beforehand.

Also, while `mrb_class_defined_id()` does not currently call the `#const_defined?` method, it is unclear whether this will remain the case in the future.
This commit is contained in:
dearblue
2026-04-13 21:41:34 +09:00
parent d65f7a9c5a
commit 6c06b4cd9d
+5 -3
View File
@@ -592,18 +592,20 @@ mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg)
MRB_API mrb_noreturn void
mrb_sys_fail(mrb_state *mrb, const char *mesg)
{
mrb_int no = (mrb_int)errno;
mrb_value mesg_str = mesg ? mrb_str_new_cstr(mrb, mesg) : mrb_nil_value();
if (mrb_class_defined_id(mrb, MRB_SYM(SystemCallError))) {
struct RClass *sce = mrb_class_get_id(mrb, MRB_SYM(SystemCallError));
mrb_int no = (mrb_int)errno;
if (mesg != NULL) {
mrb_funcall_id(mrb, mrb_obj_value(sce), MRB_SYM(_sys_fail), 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg));
mrb_funcall_id(mrb, mrb_obj_value(sce), MRB_SYM(_sys_fail), 2, mrb_fixnum_value(no), mesg_str);
}
else {
mrb_funcall_id(mrb, mrb_obj_value(sce), MRB_SYM(_sys_fail), 1, mrb_fixnum_value(no));
}
}
mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mesg ? mesg_str : mrb_str_new_lit(mrb, "")));
}
/*