Skip to content

Commit 50fee30

Browse files
author
Ulrich Hecht
committed
basic: CALL: fix yet another stack frame bug (with test)
We cannot modify the stack indices while evaluating arguments because that would break references to local variables of the caller. That means, however, that we also cannot push evaluated parameters on the stack because they may be overwritten by functions called while evaluating subsequent parameters. We avoid this by storing parameters in temporary lists. XXX: Probably not good for performance...
1 parent f3040a7 commit 50fee30

3 files changed

Lines changed: 30 additions & 2 deletions

File tree

tests/eb/fntest3.bas

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
10 ' make sure CALL parameters that contain function evaluations
2+
20 ' do not overwrite previously evaluated parameters
3+
90 DIM cols(11,20)
4+
100 GOTO 900
5+
270 PROC setfield(of,v)
6+
272 cols((@of+1) MOD 40,@of/40)=@v
7+
276 RETURN
8+
280 PROC getfield(of)
9+
282 RETURN cols((@of+1) MOD 40,@of/40)
10+
900 FOR x=0 TO 11:FOR y=0 TO 20
11+
910 cols(x,y)=x*1000+y
12+
920 NEXT:NEXT
13+
1000 FOR x=0 TO 9:FOR yy=640 TO 40 STEP -40
14+
1010 CALL setfield(yy+x,FN getfield(yy+x-40))
15+
1020 IF FN getfield(yy+x-40)<>FN getfield(yy+x) THEN STOP
16+
1030 NEXT:NEXT
17+
1040 PRINT "we're fine"

tests/eb/fntest3.run

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
we're fine

ttbasic/basic.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5983,22 +5983,25 @@ void BASIC_FP icall() {
59835983
}
59845984
if (*cip == I_OPEN) {
59855985
++cip;
5986+
QList<BString> strargs;
5987+
QList<num_t> numargs;
5988+
59865989
if (*cip != I_CLOSE) for(;;) {
59875990
if (is_strexp()) {
59885991
BString b = istrexp();
59895992
if (err)
59905993
return;
59915994
if (new_astk_str_i >= SIZE_ASTK)
59925995
goto overflow;
5993-
astk_str[new_astk_str_i++] = b;
5996+
strargs.push_back(b);
59945997
++str_args;
59955998
} else {
59965999
n = iexp();
59976000
if (err)
59986001
return;
59996002
if (new_astk_num_i >= SIZE_ASTK)
60006003
goto overflow;
6001-
astk_num[new_astk_num_i++] = n;
6004+
numargs.push_back(n);
60026005
++num_args;
60036006
}
60046007
if (*cip != I_COMMA)
@@ -6008,6 +6011,13 @@ void BASIC_FP icall() {
60086011

60096012
if (checkClose())
60106013
return;
6014+
6015+
for (int i = 0; i < strargs.size(); ++i) {
6016+
astk_str[new_astk_str_i++] = strargs[i];
6017+
}
6018+
for (int i = 0; i < numargs.size(); ++i) {
6019+
astk_num[new_astk_num_i++] = numargs[i];
6020+
}
60116021
}
60126022
astk_num_i = new_astk_num_i;
60136023
astk_str_i = new_astk_str_i;

0 commit comments

Comments
 (0)