Skip to content

Commit

Permalink
Make Hash#inspect safety in recursive
Browse files Browse the repository at this point in the history
  • Loading branch information
tricknotes committed Dec 11, 2012
1 parent 57482ef commit 900a3a0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
31 changes: 26 additions & 5 deletions src/hash.c
Expand Up @@ -883,29 +883,50 @@ 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;

ai = mrb_gc_arena_save(mrb);

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);
Expand Down Expand Up @@ -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)*/
Expand Down
7 changes: 7 additions & 0 deletions test/t/hash.rb
Expand Up @@ -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
Expand Down

0 comments on commit 900a3a0

Please sign in to comment.