summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c2
-rw-r--r--src/class.c4
-rw-r--r--src/gc.c2
-rw-r--r--src/kernel.c4
-rw-r--r--src/vm.c18
5 files changed, 19 insertions, 11 deletions
diff --git a/src/array.c b/src/array.c
index 86fb50e5c..8b6b9fa1e 100644
--- a/src/array.c
+++ b/src/array.c
@@ -169,7 +169,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
{
mrb_int capa = a->aux.capa;
- if (len > ARY_MAX_SIZE) {
+ if (len > ARY_MAX_SIZE || len < 0) {
size_error:
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
diff --git a/src/class.c b/src/class.c
index 0eea9b4dc..99ad14d81 100644
--- a/src/class.c
+++ b/src/class.c
@@ -902,7 +902,9 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (argc > i) {
*pl = argc-i;
if (*pl > 0) {
- *var = ARGV + arg_i;
+ mrb_value args = mrb_ary_new_from_values(mrb, *pl, ARGV+arg_i);
+ RARRAY(args)->c = NULL;
+ *var = (mrb_value*)RARRAY_PTR(args);
}
i = argc;
arg_i += *pl;
diff --git a/src/gc.c b/src/gc.c
index da2fe3800..134b818ee 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -579,6 +579,8 @@ mark_context(mrb_state *mrb, struct mrb_context *c)
int i;
mrb_callinfo *ci;
+ if (c->status == MRB_FIBER_TERMINATED) return;
+
/* mark VM stack */
mark_context_stack(mrb, c);
diff --git a/src/kernel.c b/src/kernel.c
index 20f52922d..f1d7700de 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -318,6 +318,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
}
p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
p->c = mrb_singleton_class_clone(mrb, self);
+ mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c);
clone = mrb_obj_value(p);
init_copy(mrb, clone, self);
@@ -410,11 +411,8 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
{
mrb_value *argv;
mrb_int argc;
- mrb_value args;
mrb_get_args(mrb, "*", &argv, &argc);
- args = mrb_ary_new_from_values(mrb, argc, argv);
- argv = (mrb_value*)RARRAY_PTR(args);
return mrb_obj_extend(mrb, argc, argv, self);
}
diff --git a/src/vm.c b/src/vm.c
index c34737789..4fca2b2ac 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1684,6 +1684,8 @@ RETRY_TRY_BLOCK:
else {
struct REnv *e = uvenv(mrb, lv-1);
if (!e) goto L_NOSUPER;
+ if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+1)
+ goto L_NOSUPER;
stack = e->stack + 1;
}
if (r == 0) {
@@ -1894,9 +1896,13 @@ RETRY_TRY_BLOCK:
}
/* call ensure only when we skip this callinfo */
if (ci[0].ridx == ci[-1].ridx) {
+ mrb_value *org_stbase = mrb->c->stbase;
while (mrb->c->eidx > ci->epos) {
ecall(mrb, --mrb->c->eidx);
ci = mrb->c->ci;
+ if (org_stbase != mrb->c->stbase) {
+ stk = mrb->c->stack;
+ }
}
}
}
@@ -1985,21 +1991,21 @@ RETRY_TRY_BLOCK:
if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) {
goto L_BREAK_ERROR;
}
+ if (proc->env->cxt.c != mrb->c) {
+ goto L_BREAK_ERROR;
+ }
+ while (mrb->c->eidx > mrb->c->ci->epos) {
+ ecall(mrb, --mrb->c->eidx);
+ }
/* break from fiber block */
if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) {
struct mrb_context *c = mrb->c;
- while (mrb->c->eidx > 0) {
- ecall(mrb, --mrb->c->eidx);
- }
mrb->c = c->prev;
c->prev = NULL;
ci = mrb->c->ci;
}
if (ci->acc < 0) {
- while (mrb->c->eidx > mrb->c->ci->epos) {
- ecall(mrb, --mrb->c->eidx);
- }
ARENA_RESTORE(mrb, ai);
mrb->c->vmexec = FALSE;
mrb->exc = (struct RObject*)break_new(mrb, proc, v);