Skip to content

Commit d4a0825

Browse files
committed
issue #7325: Endless loop in preprocessor due to #define A()
1 parent 502d7aa commit d4a0825

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

src/pre.l

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ struct preYY_state
379379
bool ccomment;
380380
QCString delimiter;
381381
QDict<void> allIncludes;
382+
QDict<void> expansionDict;
382383
DefineManager defineManager;
383384
ConstExpressionParser constExpParser;
384385
};
@@ -1933,7 +1934,7 @@ static QCString extractTrailingComment(const char *s)
19331934
static int getNextChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,uint &pos);
19341935
static int getCurrentChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,uint pos);
19351936
static void unputChar(yyscan_t yyscanner,const QCString &expr,QCString *rest,uint &pos,char c);
1936-
static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,int pos);
1937+
static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,int pos,int level);
19371938

19381939
static QCString stringize(const QCString &s)
19391940
{
@@ -2068,10 +2069,10 @@ static inline void addTillEndOfString(yyscan_t yyscanner,const QCString &expr,QC
20682069
* The replacement string will be returned in \a result and the
20692070
* length of the (unexpanded) argument list is stored in \a len.
20702071
*/
2071-
static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result)
2072+
static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result,int level)
20722073
{
20732074
YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2074-
//printf("replaceFunctionMacro(expr=%s,rest=%s,pos=%d,def=%s) level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),state->level);
2075+
//printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),state->level);
20752076
uint j=pos;
20762077
len=0;
20772078
result.resize(0);
@@ -2225,7 +2226,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
22252226
// substitution of all formal arguments
22262227
QCString resExpr;
22272228
const QCString d=def->definition.stripWhiteSpace();
2228-
//printf("Macro definition: %s\n",d.data());
2229+
//printf("Macro definition: '%s'\n",d.data());
22292230
bool inString=FALSE;
22302231
while (k<d.length())
22312232
{
@@ -2269,7 +2270,10 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
22692270
//printf("substArg='%s'\n",substArg.data());
22702271
// only if no ## operator is before or after the argument
22712272
// marker we do macro expansion.
2272-
if (!hash) expandExpression(yyscanner,substArg,0,0);
2273+
if (!hash)
2274+
{
2275+
expandExpression(yyscanner,substArg,0,0,level+1);
2276+
}
22732277
if (inString)
22742278
{
22752279
//printf("'%s'=stringize('%s')\n",stringize(*subst).data(),subst->data());
@@ -2311,10 +2315,10 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin
23112315
}
23122316
len=j-pos;
23132317
result=resExpr;
2314-
//printf("result after substitution '%s' expr='%s'\n",
2315-
// result.data(),expr.mid(pos,len).data());
2318+
//printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%d return=TRUE\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),result.data(),state->level);
23162319
return TRUE;
23172320
}
2321+
//printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%d return=FALSE\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),result.data(),state->level);
23182322
return FALSE;
23192323
}
23202324

@@ -2380,13 +2384,19 @@ static int getNextId(const QCString &expr,int p,int *l)
23802384
/*! performs recursive macro expansion on the string \a expr
23812385
* starting at position \a pos.
23822386
* May read additional characters from the input while re-scanning!
2383-
* If \a expandAll is \c TRUE then all macros in the expression are
2384-
* expanded, otherwise only the first is expanded.
23852387
*/
2386-
static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,int pos)
2388+
static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,int pos,int level)
23872389
{
23882390
YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2389-
//printf("expandExpression(%s,%s)\n",expr.data(),rest ? rest->data() : 0);
2391+
printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",expr.data(),rest ? rest->data() : 0, pos, level);
2392+
if (state->expansionDict.find(expr)!=0) // check for recursive expansions
2393+
{
2394+
return;
2395+
}
2396+
else
2397+
{
2398+
state->expansionDict.insert(expr,(void*)0x8);
2399+
}
23902400
QCString macroName;
23912401
QCString expMacro;
23922402
bool definedTest=FALSE;
@@ -2395,7 +2405,7 @@ static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in
23952405
{
23962406
bool replaced=FALSE;
23972407
macroName=expr.mid(p,l);
2398-
//printf("macroName=%s\n",macroName.data());
2408+
//printf(" p=%d macroName=%s\n",p,macroName.data());
23992409
if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
24002410
{
24012411
if (state->expandedDict->find(macroName)==0) // expand macro
@@ -2432,29 +2442,33 @@ static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in
24322442
}
24332443
else if (def && def->nargs>=0) // function macro
24342444
{
2435-
replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro);
2445+
//printf(" >>>> call replaceFunctionMacro\n");
2446+
replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
2447+
//printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
24362448
len+=l;
24372449
}
2450+
//printf(" macroName='%s' expMacro='%s' replaced=%d\n",macroName.data(),expMacro.data(),replaced);
24382451

24392452
if (replaced) // expand the macro and rescan the expression
24402453
{
2441-
//printf("replacing '%s'->'%s'\n",expr.mid(p,len).data(),expMacro.data());
2454+
//printf(" replacing '%s'->'%s'\n",expr.mid(p,len).data(),expMacro.data());
24422455
QCString resultExpr=expMacro;
24432456
QCString restExpr=expr.right(expr.length()-len-p);
24442457
processConcatOperators(resultExpr);
2458+
//printf(" macroName=%s def->nonRecursive=%d\n",macroName.data(),def->nonRecursive);
24452459
if (def && !def->nonRecursive)
24462460
{
24472461
state->expandedDict->insert(macroName,def);
2448-
expandExpression(yyscanner,resultExpr,&restExpr,0);
2462+
expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
24492463
state->expandedDict->remove(macroName);
24502464
}
24512465
expr=expr.left(p)+resultExpr+restExpr;
2466+
//printf(" new expression: '%s' old i=%d new i=%d\n",expr.data(),i,p);
24522467
i=p;
2453-
//printf("new expression: %s\n",expr.data());
24542468
}
24552469
else // move to the next macro name
24562470
{
2457-
//printf("moving to the next macro old=%d new=%d\n",i,p+l);
2471+
//printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
24582472
i=p+l;
24592473
}
24602474
}
@@ -2472,6 +2486,7 @@ static void expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in
24722486
i=p+l;
24732487
}
24742488
}
2489+
printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",expr.data(),rest ? rest->data() : 0, pos,level);
24752490
}
24762491

24772492
/*! @brief Process string or character literal.
@@ -2700,7 +2715,8 @@ static bool computeExpression(yyscan_t yyscanner,const QCString &expr)
27002715
{
27012716
YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
27022717
QCString e=expr;
2703-
expandExpression(yyscanner,e,0,0);
2718+
state->expansionDict.clear();
2719+
expandExpression(yyscanner,e,0,0,0);
27042720
//printf("after expansion '%s'\n",e.data());
27052721
e = removeIdsAndMarkers(e);
27062722
if (e.isEmpty()) return FALSE;
@@ -2714,8 +2730,10 @@ static bool computeExpression(yyscan_t yyscanner,const QCString &expr)
27142730

27152731
static QCString expandMacro(yyscan_t yyscanner,const QCString &name)
27162732
{
2733+
YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
27172734
QCString n=name;
2718-
expandExpression(yyscanner,n,0,0);
2735+
state->expansionDict.clear();
2736+
expandExpression(yyscanner,n,0,0,0);
27192737
n=removeMarkers(n);
27202738
//printf("expandMacro '%s'->'%s'\n",name.data(),n.data());
27212739
return n;
@@ -2750,7 +2768,7 @@ static void addDefine(yyscan_t yyscanner)
27502768
// conditional section (cond command) that is disabled.
27512769
if (!Doxygen::gatherDefines) return;
27522770

2753-
//printf("addDefine %s %s\n",state->defName.data(),state->defArgsStr.data());
2771+
//printf("addDefine '%s' '%s'\n",state->defName.data(),state->defArgsStr.data());
27542772
//ArgumentList *al = new ArgumentList;
27552773
//stringToArgumentList(state->defArgsStr,al);
27562774
MemberDef *md=createMemberDef(
@@ -3180,6 +3198,11 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output
31803198
yyscan_t yyscanner = p->yyscanner;
31813199
YY_EXTRA_TYPE state = preYYget_extra(p->yyscanner);
31823200
struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3201+
3202+
#ifdef FLEX_DEBUG
3203+
preYYset_debug(1,yyscanner);
3204+
#endif
3205+
31833206
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
31843207
uint orgOffset=output.curPos();
31853208
//printf("##########################\n%s\n####################\n",

0 commit comments

Comments
 (0)