Skip to content

Commit 03a08b8

Browse files
zsxOldes
authored andcommitted
ATRONIX: Fix stack expansion
Stack expansion could happen in Do_Args and Do_Next. All pointers pointing to stack values need to be re-evaluated after stack expansion (cherry picked from commit ca5e8f1) # Conflicts: # src/core/c-do.c
1 parent 4911e09 commit 03a08b8

File tree

1 file changed

+28
-37
lines changed

1 file changed

+28
-37
lines changed

src/core/c-do.c

+28-37
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@
3535
#include <stdio.h>
3636
#include "sys-state.h"
3737

38-
REBNATIVE(do); // Forward declaration for detection and special cases
39-
#define IS_DO(v) (IS_NATIVE(v) && (VAL_FUNC_CODE(v) == &N_do))
40-
4138
enum Eval_Types {
4239
ET_INVALID, // not valid to evaluate
4340
ET_WORD,
@@ -607,13 +604,13 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
607604

608605
/***********************************************************************
609606
**
610-
*/ static REBINT Do_Args(REBVAL *func, REBVAL *path, REBSER *block, REBCNT index)
607+
*/ static REBINT Do_Args(REBCNT func_offset, REBVAL *path, REBSER *block, REBCNT index)
611608
/*
612609
** Evaluate code block according to the function arg spec.
613610
** Args are pushed onto the data stack in the same order
614611
** as the function frame.
615612
**
616-
** func: function or path value
613+
** func_offset: offset of the function or path value, relative to DS_Base
617614
** path: refinements or object/function path
618615
** block: current evaluation block
619616
** index: current evaluation index
@@ -627,11 +624,15 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
627624
REBINT dsp = DSP + 1; // stack base
628625
REBINT dsf = dsp - DSF_BIAS;
629626
REBVAL *tos;
627+
REBVAL *func;
630628

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

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

636637
// Get list of words:
637638
words = VAL_FUNC_WORDS(func);
@@ -656,6 +657,8 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
656657
ds = dsp;
657658
for (; NOT_END(args); args++, ds++) {
658659

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

661664
// Process each formal argument:
@@ -841,6 +844,7 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
841844
if (IS_UNSET(value)) Trap1(RE_NO_VALUE, word);
842845
if (VAL_TYPE(value) >= REB_NATIVE && VAL_TYPE(value) <= REB_FUNCTION) goto reval; // || IS_LIT_PATH(value)
843846
DS_PUSH(value);
847+
if (IS_LIT_WORD(value)) VAL_SET(DS_TOP, REB_WORD);
844848
if (IS_FRAME(value)) Init_Obj_Value(DS_TOP, VAL_WORD_FRAME(word));
845849
index++;
846850
break;
@@ -872,7 +876,8 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
872876
Debug_Value(word, 4, 0);
873877
Dump_Values(value, 4);
874878
}
875-
index = Do_Args(value, 0, block, index+1); // uses old DSF, updates DSP
879+
index = Do_Args(dsf + 3, 0, block, index+1); // uses old DSF, updates DSP
880+
value = DSF_FUNC(dsf); //reevaluate value, because stack could be expanded in Do_Args
876881
eval_func2:
877882
// Evaluate the function:
878883
DSF = dsf; // Set new DSF
@@ -927,12 +932,15 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
927932
//Debug_Fmt("v: %r", value);
928933
// Value returned only for functions that need evaluation (but not GET_PATH):
929934
if (value && ANY_FUNC(value)) {
935+
REBCNT offset = 0;
930936
if (IS_OP(value)) Trap_Type(value); // (because prior value is wiped out above)
931937
// Can be object/func or func/refinements or object/func/refinement:
932938
dsf = Push_Func(TRUE, block, index, VAL_WORD_SYM(word), value); // Do not unset TOS1 (it is the value)
933939
value = DS_TOP;
934-
index = Do_Args(value, word+1, block, index+1);
940+
offset = value - DS_Base;
935941
ftype = VAL_TYPE(value)-REB_NATIVE;
942+
index = Do_Args(offset, word+1, block, index+1);
943+
value = &DS_Base[offset]; //restore in case the stack is expanded
936944
goto eval_func2;
937945
} else
938946
index++;
@@ -1323,9 +1331,9 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
13231331
**
13241332
***********************************************************************/
13251333
{
1334+
REBINT ftype = VAL_TYPE(func) - REB_NATIVE; // function type
13261335
REBSER *block = VAL_SERIES(args);
13271336
REBCNT index = VAL_INDEX(args);
1328-
REBCNT dsp;
13291337
REBCNT dsf;
13301338

13311339
REBSER *words;
@@ -1334,10 +1342,6 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
13341342
REBINT start;
13351343
REBVAL *val;
13361344

1337-
dsp = DSP; // in case we have to reset it later
1338-
1339-
reapply: // Go back here to start over with a new func
1340-
13411345
if (index > SERIES_TAIL(block)) index = SERIES_TAIL(block);
13421346

13431347
// Push function frame:
@@ -1353,17 +1357,6 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
13531357
if (reduce) {
13541358
// Reduce block contents to stack:
13551359
n = 0;
1356-
// Check for DO any-function
1357-
if (index < BLK_LEN(block)) {
1358-
index = Do_Next(block, index, 0);
1359-
val = DS_TOP;
1360-
if (IS_DO(func) && ANY_FUNC(val)) {
1361-
func = val; // apply this func directly (volatile reference!)
1362-
DSP = dsp; // reset the stack
1363-
goto reapply; // go back to the beginning
1364-
}
1365-
n++;
1366-
}
13671360
while (index < BLK_LEN(block)) {
13681361
index = Do_Next(block, index, 0);
13691362
if (THROWN(DS_TOP)) return;
@@ -1372,18 +1365,11 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
13721365
if (n > len) DSP = start + len;
13731366
}
13741367
else {
1375-
// Get args block and check for DO any-function
1376-
n = BLK_LEN(block) - index;
1377-
val = BLK_SKIP(block, index);
1378-
if (n > 0 && IS_DO(func) && ANY_FUNC(val)) {
1379-
func = val; // apply this func directly
1380-
index++; // skip past the func value in the args
1381-
DSP = dsp; // reset the stack
1382-
goto reapply; // go back to the beginning
1383-
}
13841368
// Copy block contents to stack:
1369+
n = VAL_BLK_LEN(args);
13851370
if (len < n) n = len;
1386-
memcpy(&DS_Base[start], val, n * sizeof(REBVAL));
1371+
if (start + n + 100 > SERIES_REST(DS_Series)) Expand_Stack(STACK_MIN);
1372+
memcpy(&DS_Base[start], BLK_SKIP(block, index), n * sizeof(REBVAL));
13871373
DSP = start + n - 1;
13881374
}
13891375

@@ -1418,7 +1404,8 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
14181404

14191405
// Evaluate the function:
14201406
DSF = dsf;
1421-
Func_Dispatch[VAL_TYPE(func) - REB_NATIVE](func);
1407+
func = DSF_FUNC(dsf); //stack could be expanded
1408+
Func_Dispatch[ftype](func);
14221409
DSP = dsf;
14231410
DSF = PRIOR_DSF(dsf);
14241411
}
@@ -1447,6 +1434,10 @@ x*/ static REBINT Do_Args_Light(REBVAL *func, REBVAL *path, REBSER *block, REBCN
14471434
func = DSF_FUNC(dsf); // for safety
14481435
words = VAL_FUNC_WORDS(func);
14491436
ds = SERIES_TAIL(words)-1; // length of stack fill below
1437+
if (DSP + ds + 100 > SERIES_REST(DS_Series)) {//unlikely
1438+
Expand_Stack(STACK_MIN);
1439+
func = DSF_FUNC(dsf); //reevaluate func
1440+
}
14501441

14511442
// Gather arguments from C stack:
14521443
for (; ds > 0; ds--) {

0 commit comments

Comments
 (0)