Skip to content

Commit 33c127c

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 7ed2880 commit 33c127c

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
@@ -613,18 +613,19 @@ IllPos: MesPrint("&Illegal character at this position: %s",in);
613613
if ( error == 0 && ( numexp = simp3atoken(AC.tokens,leftright) ) < 0 )
614614
error = 1;
615615
if ( numexp > 0 ) {
616+
// Make some space at the beginning of AC.tokens, filled with TEMPTY.
616617
SBYTE *tt;
617618
out = AC.tokens;
618619
while ( *out != TENDOFIT ) out++;
619-
while ( out+numexp*9+20 > outtop ) {
620+
while ( out+numexp*9 > outtop ) {
620621
LONG oldsize = (LONG)(out - AC.tokens);
621622
SBYTE **ppp = &(AC.tokens); /* to avoid a compiler warning */
622623
SBYTE **pppp = &(AC.toptokens);
623624
DoubleBuffer((void **)ppp,(void **)pppp,sizeof(SBYTE),"out tokens");
624625
out = AC.tokens + oldsize;
625626
outtop = AC.toptokens - MAXNUMSIZE;
626627
}
627-
tt = out + numexp*9+20;
628+
tt = out + numexp*9;
628629
while ( out >= AC.tokens ) { *tt-- = *out--; }
629630
while ( tt >= AC.tokens ) { *tt-- = TEMPTY; }
630631
if ( error == 0 && simp3btoken(AC.tokens,leftright) ) error = 1;
@@ -1440,15 +1441,33 @@ int simp3btoken(SBYTE *s, int mode)
14401441
SBYTE *t, c, *fill, *ff, *ss;
14411442
LONG num;
14421443
WORD *prot;
1444+
1445+
// Work in a temporary buffer, to avoid clashes between input and output
1446+
SBYTE *tmptokens = (SBYTE*)Malloc1((AC.toptokens-AC.tokens)*sizeof(SBYTE), "simp3btoken scratch");
1447+
SBYTE* tmptoptokens = tmptokens + (AC.toptokens-AC.tokens);
1448+
fill = tmptokens;
1449+
14431450
if ( mode == RHSIDE ) {
14441451
prot = AC.ProtoType;
14451452
numprot = prot[1] - SUBEXPSIZE;
14461453
prot += SUBEXPSIZE;
14471454
}
14481455
else { prot = 0; numprot = 0; }
1449-
fill = s;
14501456
while ( *s == TEMPTY ) s++;
14511457
while ( *s != TENDOFIT ) {
1458+
// If we are near the end of the output buffer, we'd better reallocate
1459+
// both tmptokens and AC.tokens (which must fit the final result).
1460+
// Experimentally, fill can move by at least 5 per loop iteration.
1461+
// This buffer of might not be enough for all cases!
1462+
while ( tmptoptokens - fill < 20 ) {
1463+
LONG tmppos;
1464+
tmppos = s - AC.tokens;
1465+
DoubleBuffer((void**)&(AC.tokens), (void**)&(AC.toptokens), sizeof(SBYTE), "simp3btoken double");
1466+
s = AC.tokens + tmppos;
1467+
tmppos = fill - tmptokens;
1468+
DoubleBuffer((void**)&tmptokens, (void**)&tmptoptokens, sizeof(SBYTE), "simp3btoken scratch double");
1469+
fill = tmptokens + tmppos;
1470+
}
14521471
if ( *s == TEMPTY ) { s++; continue; }
14531472
denom = 1;
14541473
if ( *s == TDIVIDE ) { denom = -1; *fill++ = *s++; }
@@ -1806,9 +1825,17 @@ nodot: MesPrint("&Illegal second element in dotproduct");
18061825
}
18071826
}
18081827
*fill = TENDOFIT;
1828+
// Now copy the modified tokens back to the original buffer
1829+
fill = tmptokens;
1830+
s = AC.tokens;
1831+
do {
1832+
*s++ = *fill;
1833+
} while ( *fill++ != TENDOFIT );
1834+
M_free(tmptokens, "simp3btoken scratch");
18091835
return(error);
18101836
doublepower:;
18111837
MesPrint("&Dubious notation with power of power");
1838+
M_free(tmptokens, "simp3btoken scratch");
18121839
return(-1);
18131840
}
18141841

0 commit comments

Comments
 (0)