diff options
| -rw-r--r-- | src/array.c | 3 | ||||
| -rw-r--r-- | src/hash.c | 2 | ||||
| -rw-r--r-- | src/vm.c | 7 | ||||
| -rw-r--r-- | test/t/array.rb | 19 |
4 files changed, 29 insertions, 2 deletions
diff --git a/src/array.c b/src/array.c index 0f52c38ef..ccd22674e 100644 --- a/src/array.c +++ b/src/array.c @@ -764,6 +764,9 @@ mrb_ary_first(mrb_state *mrb, mrb_value self) if (mrb_get_args(mrb, "|i", &size) == 0) { return (a->len > 0)? a->ptr[0]: mrb_nil_value(); } + if (size < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); + } if (size > a->len) size = a->len; if (a->flags & MRB_ARY_SHARED) { diff --git a/src/hash.c b/src/hash.c index dacef4713..04e8c60be 100644 --- a/src/hash.c +++ b/src/hash.c @@ -568,7 +568,9 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) if (!kh_exist(h,k)) continue; delKey = kh_key(h,k); + mrb_gc_protect(mrb, delKey); delVal = mrb_hash_delete_key(mrb, hash, delKey); + mrb_gc_protect(mrb, delVal); return mrb_assoc_new(mrb, delKey, delVal); } @@ -718,7 +718,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb->stack += a; if (MRB_PROC_CFUNC_P(m)) { - ci->nregs = n + 1; + if (n == CALL_MAXARGS) { + ci->nregs = 3; + } + else { + ci->nregs = n + 2; + } mrb->stack[0] = m->body.func(mrb, recv); mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; diff --git a/test/t/array.rb b/test/t/array.rb index 7029cd3c6..cb99cea6a 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -118,7 +118,24 @@ assert('Array#first', '15.2.12.5.13') do a = [] b = [1,2,3] - a.first == nil and b.first == 1 + e2 = nil + e3 = nil + begin + # this will cause an exception due to the wrong argument + [1,2,3].first(-1) + rescue => e1 + e2 = e1 + end + begin + # this will cause an exception due to the wrong argument + [1,2,3].first(1,2) + rescue => e1 + e3 = e1 + end + + a.first == nil and b.first == 1 and b.first(0) == [] and + b.first(1) == [1] and b.first(4) == [1,2,3] and + e2.class == ArgumentError and e3.class == ArgumentError end assert('Array#index', '15.2.12.5.14') do |
