Avoid crash if hv.n is greater than kh_size(h); fix #3565

The resulting behavior is different from CRuby, but modifying
hash key afterwards is undefined behavior in ISO spec.
parent 952207d2
...@@ -750,20 +750,26 @@ MRB_API mrb_value ...@@ -750,20 +750,26 @@ MRB_API mrb_value
mrb_hash_keys(mrb_state *mrb, mrb_value hash) mrb_hash_keys(mrb_state *mrb, mrb_value hash)
{ {
khash_t(ht) *h = RHASH_TBL(hash); khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k; khiter_t k, end;
mrb_value ary; mrb_value ary;
mrb_value *p; mrb_value *p;
if (!h || kh_size(h) == 0) return mrb_ary_new(mrb); if (!h || kh_size(h) == 0) return mrb_ary_new(mrb);
ary = mrb_ary_new_capa(mrb, kh_size(h)); ary = mrb_ary_new_capa(mrb, kh_size(h));
mrb_ary_set(mrb, ary, kh_size(h)-1, mrb_nil_value()); end = kh_size(h)-1;
mrb_ary_set(mrb, ary, end, mrb_nil_value());
p = mrb_ary_ptr(ary)->ptr; p = mrb_ary_ptr(ary)->ptr;
for (k = kh_begin(h); k != kh_end(h); k++) { for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) { if (kh_exist(h, k)) {
mrb_value kv = kh_key(h, k); mrb_value kv = kh_key(h, k);
mrb_hash_value hv = kh_value(h, k); mrb_hash_value hv = kh_value(h, k);
p[hv.n] = kv; if (hv.n <= end) {
p[hv.n] = kv;
}
else {
p[end] = kv;
}
} }
} }
return ary; return ary;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment