Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Make Hash#inspect safety in recursive #620

Open
wants to merge 1 commit into from

4 participants

Ryunosuke SATO Yuichiro MASUI mattn Carson McDonald
Ryunosuke SATO

Hash#inspect is unsafety.

$ ./bin/mruby -e 'h = {}; h[:h]=h; puts h'
trace:
     [1] (unknown):-1:in Kernel#puts
     [0] -e:1

I know that this issue has been discussed in #57, but I'd like mruby to be safety.

Yuichiro MASUI

@matz It's seems like good. What's the problem?

mattn

i get arena overflow on latest repo.

> h = {}; h[:h]=h; puts h
RuntimeError: arena overflow error
Carson McDonald

If it helps, it looks like a difference between the mruby and mirb tools. If you go back to the commit that this was taken from 57482ef and try mirb you get the same arena overflow error. If you try today's mruby you will get a slightly different error message than above but not the overflow error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 11, 2012
  1. Ryunosuke SATO
This page is out of date. Refresh to see the latest.
Showing with 33 additions and 5 deletions.
  1. +26 −5 src/hash.c
  2. +7 −0 test/t/hash.rb
31 src/hash.c
View
@@ -883,18 +883,27 @@ mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
*/
static mrb_value
-inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
+inspect_hash(mrb_state *mrb, mrb_value hash, mrb_value list)
{
+ int i;
mrb_value str, str2;
khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
- if (recur) return mrb_str_new(mrb, "{...}", 5);
+ /* check recursive */
+ for(i=0; i<RARRAY_LEN(list); i++) {
+ if (mrb_obj_equal(mrb, hash, RARRAY_PTR(list)[i])) {
+ return mrb_str_new(mrb, "{...}", 5);
+ }
+ }
+
+ mrb_ary_push(mrb, list, hash);
str = mrb_str_new(mrb, "{", 1);
if (h && kh_size(h) > 0) {
for (k = kh_begin(h); k != kh_end(h); k++) {
int ai;
+ mrb_value key, value;
if (!kh_exist(h,k)) continue;
@@ -902,10 +911,22 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
if (RSTRING_LEN(str) > 1) mrb_str_cat2(mrb, str, ", ");
- str2 = mrb_inspect(mrb, kh_key(h,k));
+ key = kh_key(h,k);
+ if (mrb_hash_p(key)) {
+ str2 = inspect_hash(mrb, key, list);
+ } else {
+ str2 = mrb_inspect(mrb, key);
+ }
+
mrb_str_append(mrb, str, str2);
mrb_str_buf_cat(mrb, str, "=>", 2);
- str2 = mrb_inspect(mrb, kh_value(h,k));
+
+ value = kh_value(h,k);
+ if (mrb_hash_p(value)) {
+ str2 = inspect_hash(mrb, value, list);
+ } else {
+ str2 = mrb_inspect(mrb, value);
+ }
mrb_str_append(mrb, str, str2);
mrb_gc_arena_restore(mrb, ai);
@@ -935,7 +956,7 @@ mrb_hash_inspect(mrb_state *mrb, mrb_value hash)
if (!h || kh_size(h) == 0)
return mrb_str_new(mrb, "{}", 2);
- return inspect_hash(mrb, hash, 0);
+ return inspect_hash(mrb, hash, mrb_ary_new(mrb));
}
/* 15.2.13.4.29 (x)*/
7 test/t/hash.rb
View
@@ -229,6 +229,13 @@
a.values == ['abc_value']
end
+assert('Hash#inspect', '15.2.13.4.30') do
+ a = {}
+ a[a] = a
+
+ a.inspect == '{{...}=>{...}}'
+end
+#
# Not ISO specified
assert('Hash#reject') do
Something went wrong with that request. Please try again.