diff options
author | Markus Schorn | 2010-01-04 16:31:32 +0000 |
---|---|---|
committer | Markus Schorn | 2010-01-04 16:31:32 +0000 |
commit | a867009329cb5fc94f60d65860c573d3163b89d4 (patch) | |
tree | e62b118f89db774fc0ee0194671a2b367ca42a3f | |
parent | 30bddf9ac04076b1900908e858d04352ffef2b62 (diff) | |
download | org.eclipse.cdt-a867009329cb5fc94f60d65860c573d3163b89d4.tar.gz org.eclipse.cdt-a867009329cb5fc94f60d65860c573d3163b89d4.tar.xz org.eclipse.cdt-a867009329cb5fc94f60d65860c573d3163b89d4.zip |
Bug 298455: Stack overflow with deeply nested else if statements.
3 files changed, 120 insertions, 40 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index e8c9b3218f2..c01a6ee36f4 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -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); + } + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIfStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIfStatement.java index ba8ccb9aaa2..2a2a7fd56e5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIfStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIfStatement.java @@ -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; - - if( action.shouldVisitStatements ){ - switch( action.leave( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; - } + private static class N { + final IASTIfStatement fIfStatement; + N fNext; + + 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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java index 63f49f3b2a9..c850b0641da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java @@ -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 } } - @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; - } + private static class N { + final IASTIfStatement fIfStatement; + N fNext; + + N(IASTIfStatement stmt) { + fIfStatement = stmt; } - + } + + @Override + 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; } |