Compiler: Fix in recursion detection.

Original fix imported from pawn 3.1.3522.
This fixes where for some plugins you would have:

   Stack/heap size:      16384 bytes; usage is unknown, due to recursion

Now, you get:

   Stack/heap size:      16384 bytes; estimated max. usage=782 cells (3128 bytes)
This commit is contained in:
Arkshine 2014-08-13 13:39:35 +02:00
parent 520493fab1
commit 6978e2dc4c

View File

@ -4178,7 +4178,7 @@ static void reduce_referrers(symbol *root)
} }
#if !defined SC_LIGHT #if !defined SC_LIGHT
static long max_stacksize_recurse(symbol *sym,long basesize,int *pubfuncparams) static long max_stacksize_recurse(symbol *sourcesym, symbol *sym, long basesize, int *pubfuncparams)
{ {
long size,maxsize; long size,maxsize;
int i; int i;
@ -4186,17 +4186,15 @@ static long max_stacksize_recurse(symbol *sym,long basesize,int *pubfuncparams)
assert(sym!=NULL); assert(sym!=NULL);
assert(sym->ident==iFUNCTN); assert(sym->ident==iFUNCTN);
assert((sym->usage & uNATIVE)==0); assert((sym->usage & uNATIVE)==0);
/* recursion detection */
if (sym->compound==0)
return -1; /* this function was processed already -> recursion */
sym->compound=0;
maxsize=sym->x.stacksize; maxsize=sym->x.stacksize;
for (i=0; i<sym->numrefers; i++) { for (i=0; i<sym->numrefers; i++) {
if (sym->refer[i]!=NULL) { if (sym->refer[i]!=NULL) {
assert(sym->refer[i]->ident==iFUNCTN); assert(sym->refer[i]->ident==iFUNCTN);
assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */ assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */
size=max_stacksize_recurse(sym->refer[i],sym->x.stacksize,pubfuncparams); if (sym->refer[i] == sourcesym)
return -1; /* recursion detection */
size = max_stacksize_recurse(sourcesym, sym->refer[i], sym->x.stacksize, pubfuncparams);
if (size<0) if (size<0)
return size; /* recursion was detected, quit */ return size; /* recursion was detected, quit */
if (maxsize<size) if (maxsize<size)
@ -4248,27 +4246,17 @@ static long max_stacksize(symbol *root)
maxsize=0; maxsize=0;
maxparams=0; maxparams=0;
for (sym=root->next; sym!=NULL; sym=sym->next) { for (sym=root->next; sym!=NULL; sym=sym->next) {
symbol *tmpsym;
/* drop out if this is not a user-implemented function */ /* drop out if this is not a user-implemented function */
if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0) if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0)
continue; continue;
/* set a "mark" on all functions */
for (tmpsym=root->next; tmpsym!=NULL; tmpsym=tmpsym->next)
if (tmpsym->ident==iFUNCTN)
tmpsym->compound=1;
/* accumulate stack size for this symbol */ /* accumulate stack size for this symbol */
size=max_stacksize_recurse(sym,0L,&maxparams); size=max_stacksize_recurse(sym,sym,0L,&maxparams);
if (size<0) if (size<0)
return size; /* recursion was detected */ return size; /* recursion was detected */
if (maxsize<size) if (maxsize<size)
maxsize=size; maxsize=size;
} /* for */ } /* for */
/* clear all marks */
for (sym=root->next; sym!=NULL; sym=sym->next)
if (sym->ident==iFUNCTN)
sym->compound=0;
maxsize++; /* +1 because a zero cell is always pushed on top maxsize++; /* +1 because a zero cell is always pushed on top
* of the stack to catch stack overwrites */ * of the stack to catch stack overwrites */
return maxsize+(maxparams+1);/* +1 because # of parameters is always pushed on entry */ return maxsize+(maxparams+1);/* +1 because # of parameters is always pushed on entry */