Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Schorn2010-01-04 16:31:32 +0000
committerMarkus Schorn2010-01-04 16:31:32 +0000
commita867009329cb5fc94f60d65860c573d3163b89d4 (patch)
treee62b118f89db774fc0ee0194671a2b367ca42a3f
parent30bddf9ac04076b1900908e858d04352ffef2b62 (diff)
downloadorg.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.
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java14
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTIfStatement.java70
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIfStatement.java76
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;
}

Back to the top