Skip to content

Commit cd7312a

Browse files
committed
fix: use a scratch buffer in simp3btoken
Issue #251 crashes because "fill" overtakes "s" and produces malformed tokens, leading to an infinite loop. Avoid this possibility by writing the output tokens into a scratch buffer, and copy the result back at the end. Additionally, re-allocate the buffers if fill is "close to" the end of the scratch buffer. Here "close to" is a guess at how much space might be required per iteration.
1 parent aca9b69 commit cd7312a

File tree

2 files changed

+87
-3
lines changed

2 files changed

+87
-3
lines changed

check/fixes.frm

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,63 @@ assert stdout =~ exact_pattern(<<'EOF')
22202220
S1(spectator)(5)
22212221
EOF
22222222
*--#] Issue231 :
2223+
*--#[ Issue251_1
2224+
#-
2225+
Symbol x,a0,...,a3;
2226+
Local F = <a0*x^0>+...+<a3*x^3>;
2227+
Bracket x;
2228+
.sort
2229+
2230+
Local G =
2231+
+ 1 / F[1]
2232+
+ x * (-F[x]) / F[1]^2
2233+
+ x^2 * (F[x]^2 - F[1]*F[x^2]) / F[1]^3
2234+
+ x^3 * (-F[x]^3 + 2*F[1]*F[x]*F[x^2] - F[1]^2*F[x^3]) / F[1]^4
2235+
;
2236+
Print +s G;
2237+
.end
2238+
assert succeeded?
2239+
assert result("G") =~ expr("
2240+
+ a0^-1
2241+
- x*a0^-2*a1
2242+
+ x^2*a0^-3*a1^2
2243+
- x^2*a0^-2*a2
2244+
- x^3*a0^-4*a1^3
2245+
+ 2*x^3*a0^-3*a1*a2
2246+
- x^3*a0^-2*a3
2247+
")
2248+
*--#] Issue251_1
2249+
*--#[ Issue251_2
2250+
#-
2251+
Symbol x,a0,...,a3;
2252+
Local F = <a0*x^0>+...+<a3*x^3>;
2253+
Bracket x;
2254+
.sort
2255+
2256+
Local G =
2257+
+ 1 / F[1]
2258+
+ x * (-F[x]) / F[1]^2
2259+
+ x^2 * (F[x]^2 - F[1]*F[x^2]) / F[1]^3
2260+
+ x^3 * (-F[x]^3 + 2*F[1]*F[x]*F[x^2] - F[1]^2*F[x^3]
2261+
#do i = 1,100
2262+
+ F[1]^1
2263+
#enddo
2264+
) / F[1]^4
2265+
;
2266+
Print +s G;
2267+
.end
2268+
assert succeeded?
2269+
assert result("G") =~ expr("
2270+
+ a0^-1
2271+
- x*a0^-2*a1
2272+
+ x^2*a0^-3*a1^2
2273+
- x^2*a0^-2*a2
2274+
- x^3*a0^-4*a1^3
2275+
+ 100*x^3*a0^-3
2276+
+ 2*x^3*a0^-3*a1*a2
2277+
- x^3*a0^-2*a3
2278+
")
2279+
*--#] Issue251_2
22232280
*--#[ Issue253 :
22242281
* Memory error for local $-variable in TFORM
22252282
#$x = 0;

sources/token.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -614,18 +614,19 @@ IllPos: MesPrint("&Illegal character at this position: %s",in);
614614
if ( error == 0 && ( numexp = simp3atoken(AC.tokens,leftright) ) < 0 )
615615
error = 1;
616616
if ( numexp > 0 ) {
617+
// Make some space at the beginning of AC.tokens, filled with TEMPTY.
617618
SBYTE *tt;
618619
out = AC.tokens;
619620
while ( *out != TENDOFIT ) out++;
620-
while ( out+numexp*9+20 > outtop ) {
621+
while ( out+numexp*9 > outtop ) {
621622
LONG oldsize = (LONG)(out - AC.tokens);
622623
SBYTE **ppp = &(AC.tokens); /* to avoid a compiler warning */
623624
SBYTE **pppp = &(AC.toptokens);
624625
DoubleBuffer((void **)ppp,(void **)pppp,sizeof(SBYTE),"out tokens");
625626
out = AC.tokens + oldsize;
626627
outtop = AC.toptokens - MAXNUMSIZE;
627628
}
628-
tt = out + numexp*9+20;
629+
tt = out + numexp*9;
629630
while ( out >= AC.tokens ) { *tt-- = *out--; }
630631
while ( tt >= AC.tokens ) { *tt-- = TEMPTY; }
631632
if ( error == 0 && simp3btoken(AC.tokens,leftright) ) error = 1;
@@ -1441,15 +1442,33 @@ int simp3btoken(SBYTE *s, int mode)
14411442
SBYTE *t, c, *fill, *ff, *ss;
14421443
LONG num;
14431444
WORD *prot;
1445+
1446+
// Work in a temporary buffer, to avoid clashes between input and output
1447+
SBYTE *tmptokens = (SBYTE*)Malloc1((AC.toptokens-AC.tokens)*sizeof(SBYTE), "simp3btoken scratch");
1448+
SBYTE* tmptoptokens = tmptokens + (AC.toptokens-AC.tokens);
1449+
fill = tmptokens;
1450+
14441451
if ( mode == RHSIDE ) {
14451452
prot = AC.ProtoType;
14461453
numprot = prot[1] - SUBEXPSIZE;
14471454
prot += SUBEXPSIZE;
14481455
}
14491456
else { prot = 0; numprot = 0; }
1450-
fill = s;
14511457
while ( *s == TEMPTY ) s++;
14521458
while ( *s != TENDOFIT ) {
1459+
// If we are near the end of the output buffer, we'd better reallocate
1460+
// both tmptokens and AC.tokens (which must fit the final result).
1461+
// Experimentally, fill can move by at most 5 per loop iteration, but
1462+
// this buffer of 20 of might not be enough for all cases!
1463+
while ( tmptoptokens - fill < 20 ) {
1464+
LONG tmppos;
1465+
tmppos = s - AC.tokens;
1466+
DoubleBuffer((void**)&(AC.tokens), (void**)&(AC.toptokens), sizeof(SBYTE), "simp3btoken double");
1467+
s = AC.tokens + tmppos;
1468+
tmppos = fill - tmptokens;
1469+
DoubleBuffer((void**)&tmptokens, (void**)&tmptoptokens, sizeof(SBYTE), "simp3btoken scratch double");
1470+
fill = tmptokens + tmppos;
1471+
}
14531472
if ( *s == TEMPTY ) { s++; continue; }
14541473
denom = 1;
14551474
if ( *s == TDIVIDE ) { denom = -1; *fill++ = *s++; }
@@ -1807,9 +1826,17 @@ nodot: MesPrint("&Illegal second element in dotproduct");
18071826
}
18081827
}
18091828
*fill = TENDOFIT;
1829+
// Now copy the modified tokens back to the original buffer
1830+
fill = tmptokens;
1831+
s = AC.tokens;
1832+
do {
1833+
*s++ = *fill;
1834+
} while ( *fill++ != TENDOFIT );
1835+
M_free(tmptokens, "simp3btoken scratch");
18101836
return(error);
18111837
doublepower:;
18121838
MesPrint("&Dubious notation with power of power");
1839+
M_free(tmptokens, "simp3btoken scratch");
18131840
return(-1);
18141841
}
18151842

0 commit comments

Comments
 (0)