mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +02:00
Bug 298455: Stack overflow with deeply nested else if statements.
This commit is contained in:
parent
30bddf9ac0
commit
a867009329
3 changed files with 119 additions and 39 deletions
|
@ -7221,4 +7221,18 @@ public class AST2Tests extends AST2BaseTest {
|
|||
IASTTranslationUnit tu = parseAndCheckBindings(code, lang);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeepElseif_298455() throws Exception {
|
||||
sValidateCopy= false;
|
||||
StringBuilder buf= new StringBuilder("void f() {if (0) {}");
|
||||
for (int i = 0; i < 75000; i++) {
|
||||
buf.append("else if (0) {}");
|
||||
}
|
||||
buf.append("}");
|
||||
String code= buf.toString();
|
||||
for(ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu = parseAndCheckBindings(code, lang);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,26 +92,58 @@ public class CASTIfStatement extends ASTNode implements IASTIfStatement, IASTAmb
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept( ASTVisitor action ){
|
||||
if( action.shouldVisitStatements ){
|
||||
switch( action.visit( this ) ){
|
||||
case ASTVisitor.PROCESS_ABORT : return false;
|
||||
case ASTVisitor.PROCESS_SKIP : return true;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
if( condition != null ) if( !condition.accept( action ) ) return false;
|
||||
if( thenClause != null ) if( !thenClause.accept( action ) ) return false;
|
||||
if( elseClause != null ) if( !elseClause.accept( action ) ) return false;
|
||||
private static class N {
|
||||
final IASTIfStatement fIfStatement;
|
||||
N fNext;
|
||||
|
||||
if( action.shouldVisitStatements ){
|
||||
switch( action.leave( this ) ){
|
||||
case ASTVisitor.PROCESS_ABORT : return false;
|
||||
case ASTVisitor.PROCESS_SKIP : return true;
|
||||
default : break;
|
||||
}
|
||||
N(IASTIfStatement stmt) {
|
||||
fIfStatement = stmt;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(ASTVisitor action) {
|
||||
N stack= null;
|
||||
IASTIfStatement stmt= this;
|
||||
loop: for(;;) {
|
||||
if (action.shouldVisitStatements) {
|
||||
switch (action.visit(this)) {
|
||||
case ASTVisitor.PROCESS_ABORT: return false;
|
||||
case ASTVisitor.PROCESS_SKIP:
|
||||
stmt= null;
|
||||
break loop;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
IASTNode child = stmt.getConditionExpression();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child= stmt.getThenClause();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child= stmt.getElseClause();
|
||||
if (child instanceof IASTIfStatement) {
|
||||
if (action.shouldVisitStatements) {
|
||||
N n= new N(stmt);
|
||||
n.fNext= stack;
|
||||
stack= n;
|
||||
}
|
||||
stmt= (IASTIfStatement) child;
|
||||
} else {
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
if (action.shouldVisitStatements) {
|
||||
if (stmt != null && action.leave(stmt) == ASTVisitor.PROCESS_ABORT)
|
||||
return false;
|
||||
while (stack != null) {
|
||||
if (action.leave(stack.fIfStatement) == ASTVisitor.PROCESS_ABORT)
|
||||
return false;
|
||||
stack= stack.fNext;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
|
@ -98,28 +99,61 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
|
|||
}
|
||||
}
|
||||
|
||||
private static class N {
|
||||
final IASTIfStatement fIfStatement;
|
||||
N fNext;
|
||||
|
||||
N(IASTIfStatement stmt) {
|
||||
fIfStatement = stmt;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept( ASTVisitor action ){
|
||||
if( action.shouldVisitStatements ){
|
||||
switch( action.visit( this ) ){
|
||||
case ASTVisitor.PROCESS_ABORT : return false;
|
||||
case ASTVisitor.PROCESS_SKIP : return true;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
if( condition != null ) if( !condition.accept( action ) ) return false;
|
||||
if( condDecl != null ) if( !condDecl.accept( action )) return false;
|
||||
if( thenClause != null ) if( !thenClause.accept( action ) ) return false;
|
||||
if( elseClause != null ) if( !elseClause.accept( action ) ) return false;
|
||||
|
||||
if( action.shouldVisitStatements ){
|
||||
switch( action.leave( this ) ){
|
||||
case ASTVisitor.PROCESS_ABORT : return false;
|
||||
case ASTVisitor.PROCESS_SKIP : return true;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean accept(ASTVisitor action) {
|
||||
N stack= null;
|
||||
ICPPASTIfStatement stmt= this;
|
||||
loop: for(;;) {
|
||||
if (action.shouldVisitStatements) {
|
||||
switch (action.visit(this)) {
|
||||
case ASTVisitor.PROCESS_ABORT: return false;
|
||||
case ASTVisitor.PROCESS_SKIP:
|
||||
stmt= null;
|
||||
break loop;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
IASTNode child = stmt.getConditionExpression();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child= stmt.getConditionDeclaration();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child= stmt.getThenClause();
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
child= stmt.getElseClause();
|
||||
if (child instanceof ICPPASTIfStatement) {
|
||||
if (action.shouldVisitStatements) {
|
||||
N n= new N(stmt);
|
||||
n.fNext= stack;
|
||||
stack= n;
|
||||
}
|
||||
stmt= (ICPPASTIfStatement) child;
|
||||
} else {
|
||||
if (child != null && !child.accept(action))
|
||||
return false;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
if (action.shouldVisitStatements) {
|
||||
if (stmt != null && action.leave(stmt) == ASTVisitor.PROCESS_ABORT)
|
||||
return false;
|
||||
while (stack != null) {
|
||||
if (action.leave(stack.fIfStatement) == ASTVisitor.PROCESS_ABORT)
|
||||
return false;
|
||||
stack= stack.fNext;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue