Skip to content

Commit ca5e8f1

Browse files
committed
Fix stack expansion
Stack expansion could happend in Do_Args and Do_Next. All pointers pointing to stack values need to be re-evaluated after stack expansion
1 parent 472484f commit ca5e8f1

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

src/core/c-do.c

+17-7
Original file line numberDiff line numberDiff line change
@@ -605,13 +605,13 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
605605

606606
/***********************************************************************
607607
**
608-
*/ static REBINT Do_Args(REBVAL *func, REBVAL *path, REBSER *block, REBCNT index)
608+
*/ static REBINT Do_Args(REBCNT func_offset, REBVAL *path, REBSER *block, REBCNT index)
609609
/*
610610
** Evaluate code block according to the function arg spec.
611611
** Args are pushed onto the data stack in the same order
612612
** as the function frame.
613613
**
614-
** func: function or path value
614+
** func_offset: offset of the function or path value, relative to DS_Base
615615
** path: refinements or object/function path
616616
** block: current evaluation block
617617
** index: current evaluation index
@@ -625,11 +625,15 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
625625
REBINT dsp = DSP + 1; // stack base
626626
REBINT dsf = dsp - DSF_BIAS;
627627
REBVAL *tos;
628+
REBVAL *func;
628629

629-
if (IS_OP(func)) dsf--; // adjust for extra arg
630+
if ((dsp + 100) > (REBINT)SERIES_REST(DS_Series)) {
631+
Expand_Stack(STACK_MIN);
632+
}
630633

631-
if ((dsp + 100) > (REBINT)SERIES_REST(DS_Series))
632-
Trap0(RE_STACK_OVERFLOW); //Expand_Stack();
634+
func = &DS_Base[func_offset];
635+
636+
if (IS_OP(func)) dsf--; // adjust for extra arg
633637

634638
// Get list of words:
635639
words = VAL_FUNC_WORDS(func);
@@ -654,6 +658,8 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
654658
ds = dsp;
655659
for (; NOT_END(args); args++, ds++) {
656660

661+
func = &DS_Base[func_offset]; //DS_Base could be changed
662+
657663
//if (Trace_Flags) Trace_Arg(ds - dsp, args, path);
658664

659665
// Process each formal argument:
@@ -865,7 +871,8 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
865871
Debug_Value(word, 4, 0);
866872
Dump_Values(value, 4);
867873
}
868-
index = Do_Args(value, 0, block, index+1); // uses old DSF, updates DSP
874+
index = Do_Args(dsf + 3, 0, block, index+1); // uses old DSF, updates DSP
875+
value = DSF_FUNC(dsf); //reevaluate value, because stack could be expanded in Do_Args
869876
eval_func2:
870877
// Evaluate the function:
871878
DSF = dsf; // Set new DSF
@@ -924,8 +931,10 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
924931
// Can be object/func or func/refinements or object/func/refinement:
925932
dsf = Push_Func(TRUE, block, index, VAL_WORD_SYM(word), value); // Do not unset TOS1 (it is the value)
926933
value = DS_TOP;
927-
index = Do_Args(value, word+1, block, index+1);
934+
REBCNT offset = value - DS_Base;
928935
ftype = VAL_TYPE(value)-REB_NATIVE;
936+
index = Do_Args(offset, word+1, block, index+1);
937+
value = &DS_Base[offset]; //restore in case the stack is expanded
929938
goto eval_func2;
930939
} else
931940
index++;
@@ -1368,6 +1377,7 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
13681377

13691378
// Evaluate the function:
13701379
DSF = dsf;
1380+
func = DSF_FUNC(dsf); //stack could be expanded
13711381
Func_Dispatch[ftype](func);
13721382
DSP = dsf;
13731383
DSF = PRIOR_DSF(dsf);

0 commit comments

Comments
 (0)