Remove implicit conversion using to_str method; fix #3854

We have added internal convenience method `__to_str` which
does string type check.

The issue #3854 was fixed but fundamental flaw of lack of stack
depth check along with fibers still remains. Use `MRB_GC_FIXED_ARENA`
for workaround.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2018-09-19 21:51:53 +09:00
parent afca99a40b
commit ff08856fe3
13 changed files with 60 additions and 114 deletions
+9 -2
View File
@@ -504,10 +504,17 @@ check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const
return tmp;
}
#define CHECK_TYPE(mrb, val, t, c) do { \
if (mrb_type(val) != (t)) {\
mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_lit(mrb, c));\
}\
} while (0)
static mrb_value
to_str(mrb_state *mrb, mrb_value val)
{
return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
CHECK_TYPE(mrb, val, MRB_TT_STRING, "String");
return val;
}
static mrb_value
@@ -1972,7 +1979,7 @@ mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
}
/* const get with class path string */
path = mrb_string_type(mrb, path);
path = mrb_ensure_string_type(mrb, path);
ptr = RSTRING_PTR(path);
len = RSTRING_LEN(path);
off = 0;
+6 -33
View File
@@ -746,6 +746,7 @@ basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
{
return mrb_respond_to(mrb, obj, id);
}
/* 15.3.1.3.43 */
/*
* call-seq:
@@ -765,45 +766,16 @@ basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
static mrb_value
obj_respond_to(mrb_state *mrb, mrb_value self)
{
mrb_value mid;
mrb_sym id, rtm_id;
mrb_bool priv = FALSE, respond_to_p = TRUE;
mrb_get_args(mrb, "o|b", &mid, &priv);
if (mrb_symbol_p(mid)) {
id = mrb_symbol(mid);
}
else {
mrb_value tmp;
if (mrb_string_p(mid)) {
tmp = mrb_check_intern_str(mrb, mid);
}
else {
tmp = mrb_check_string_type(mrb, mid);
if (mrb_nil_p(tmp)) {
tmp = mrb_inspect(mrb, mid);
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
}
tmp = mrb_check_intern_str(mrb, tmp);
}
if (mrb_nil_p(tmp)) {
respond_to_p = FALSE;
}
else {
id = mrb_symbol(tmp);
}
}
if (respond_to_p) {
respond_to_p = basic_obj_respond_to(mrb, self, id, !priv);
}
mrb_bool priv = FALSE, respond_to_p;
mrb_get_args(mrb, "n|b", &id, &priv);
respond_to_p = basic_obj_respond_to(mrb, self, id, !priv);
if (!respond_to_p) {
rtm_id = mrb_intern_lit(mrb, "respond_to_missing?");
if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) {
mrb_value args[2], v;
args[0] = mid;
args[0] = mrb_symbol_value(id);
args[1] = mrb_bool_value(priv);
v = mrb_funcall_argv(mrb, self, rtm_id, 2, args);
return mrb_bool_value(mrb_bool(v));
@@ -873,6 +845,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
mrb_define_method(mrb, krn, "__to_int", mrb_to_int, MRB_ARGS_NONE()); /* internal */
mrb_define_method(mrb, krn, "__to_str", mrb_to_str, MRB_ARGS_NONE()); /* internal */
mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1));
+27
View File
@@ -579,6 +579,33 @@ mrb_Float(mrb_state *mrb, mrb_value val)
}
#endif
MRB_API mrb_value
mrb_to_str(mrb_state *mrb, mrb_value val)
{
if (!mrb_string_p(val)) {
mrb_value type = inspect_type(mrb, val);
mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to String", type);
}
return val;
}
MRB_API mrb_value
mrb_ensure_string_type(mrb_state *mrb, mrb_value str)
{
if (!mrb_string_p(str)) {
mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to String",
inspect_type(mrb, str));
}
return str;
}
MRB_API mrb_value
mrb_check_string_type(mrb_state *mrb, mrb_value str)
{
if (!mrb_string_p(str)) return mrb_nil_value();
return str;
}
MRB_API mrb_value
mrb_inspect(mrb_state *mrb, mrb_value obj)
{
+2 -30
View File
@@ -956,15 +956,7 @@ str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
MRB_API mrb_bool
mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
{
if (mrb_immediate_p(str2)) return FALSE;
if (!mrb_string_p(str2)) {
if (mrb_nil_p(str2)) return FALSE;
if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) {
return FALSE;
}
str2 = mrb_funcall(mrb, str2, "to_str", 0);
return mrb_equal(mrb, str2, str1);
}
if (!mrb_string_p(str2)) return FALSE;
return str_eql(mrb, str1, str2);
}
@@ -992,14 +984,8 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
MRB_API mrb_value
mrb_str_to_str(mrb_state *mrb, mrb_value str)
{
mrb_value s;
if (!mrb_string_p(str)) {
s = mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
if (mrb_nil_p(s)) {
s = mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
}
return s;
return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
}
return str;
}
@@ -1714,18 +1700,6 @@ mrb_ptr_to_str(mrb_state *mrb, void *p)
return mrb_obj_value(p_str);
}
MRB_API mrb_value
mrb_string_type(mrb_state *mrb, mrb_value str)
{
return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
}
MRB_API mrb_value
mrb_check_string_type(mrb_state *mrb, mrb_value str)
{
return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
}
/* 15.2.10.5.30 */
/*
* call-seq:
@@ -2379,7 +2353,6 @@ mrb_str_to_f(mrb_state *mrb, mrb_value self)
/*
* call-seq:
* str.to_s => str
* str.to_str => str
*
* Returns the receiver.
*/
@@ -2783,7 +2756,6 @@ mrb_init_string(mrb_state *mrb)
#endif
mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */
mrb_define_method(mrb, s, "to_s", mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */
mrb_define_method(mrb, s, "to_str", mrb_str_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "to_sym", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */
mrb_define_method(mrb, s, "upcase", mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */
mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */