1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 294969: Stack overflow with deeply nested binary expressions.

This commit is contained in:
Markus Schorn 2010-01-04 15:01:47 +00:00
parent d27a79d465
commit 30bddf9ac0
5 changed files with 199 additions and 54 deletions

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others. * Copyright (c) 2004, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7208,4 +7208,17 @@ public class AST2Tests extends AST2BaseTest {
final String code = getAboveComment(); final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.C, false, true); parseAndCheckBindings(code, ParserLanguage.C, false, true);
} }
public void testDeepBinaryExpression_294969() throws Exception {
sValidateCopy= false;
StringBuilder buf= new StringBuilder("void f() {0");
for (int i = 0; i < 150000; i++) {
buf.append('+').append(i);
}
buf.append(";}");
String code= buf.toString();
for(ParserLanguage lang : ParserLanguage.values()) {
IASTTranslationUnit tu = parseAndCheckBindings(code, lang);
}
}
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2009 IBM Corporation and others. * Copyright (c) 2005, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -63,13 +63,8 @@ public abstract class ASTNode implements IASTNode {
return active; return active;
} }
public void freeze() { void setIsFrozen() {
frozen = true; frozen = true;
for(IASTNode child : getChildren()) {
if(child != null) {
((ASTNode)child).freeze();
}
}
} }
public void setInactive() { public void setInactive() {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2008, 2009 Wind River Systems, Inc. and others. * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -14,6 +14,7 @@ import java.util.List;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
@ -383,4 +384,14 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
copy.setOffsetAndLength(this); copy.setOffsetAndLength(this);
} }
public final void freeze() {
accept(new ASTGenericVisitor(true) {
@Override
protected int genericVisit(IASTNode node) {
((ASTNode) node).setIsFrozen();
return PROCESS_CONTINUE;
}
});
}
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2009 IBM Corporation and others. * Copyright (c) 2005, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -90,6 +90,10 @@ public class CASTBinaryExpression extends ASTNode implements
@Override @Override
public boolean accept( ASTVisitor action ){ public boolean accept( ASTVisitor action ){
if (operand1 instanceof IASTBinaryExpression || operand2 instanceof IASTBinaryExpression) {
return acceptWithoutRecursion(this, action);
}
if( action.shouldVisitExpressions ){ if( action.shouldVisitExpressions ){
switch( action.visit( this ) ){ switch( action.visit( this ) ){
case ASTVisitor.PROCESS_ABORT : return false; case ASTVisitor.PROCESS_ABORT : return false;
@ -98,19 +102,76 @@ public class CASTBinaryExpression extends ASTNode implements
} }
} }
if( operand1 != null ) if( !operand1.accept( action ) ) return false; if (operand1 != null && !operand1.accept(action))
if( operand2 != null ) if( !operand2.accept( action ) ) return false; return false;
if (operand2 != null && !operand2.accept(action))
return false;
if(action.shouldVisitExpressions ){ if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT)
switch( action.leave( this ) ){ return false;
case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true; return true;
default : break;
}
}
return true;
} }
private static class N {
final IASTBinaryExpression fExpression;
int fState;
N fNext;
N(IASTBinaryExpression expr) {
fExpression = expr;
}
}
public static boolean acceptWithoutRecursion(IASTBinaryExpression bexpr, ASTVisitor action) {
N stack= new N(bexpr);
while(stack != null) {
IASTBinaryExpression expr= stack.fExpression;
if (stack.fState == 0) {
if (action.shouldVisitExpressions) {
switch (action.visit(expr)) {
case ASTVisitor.PROCESS_ABORT :
return false;
case ASTVisitor.PROCESS_SKIP:
stack= stack.fNext;
continue;
}
}
stack.fState= 1;
IASTExpression op1 = expr.getOperand1();
if (op1 instanceof IASTBinaryExpression) {
N n= new N((IASTBinaryExpression) op1);
n.fNext= stack;
stack= n;
continue;
}
if (op1 != null && !op1.accept(action))
return false;
}
if (stack.fState == 1) {
stack.fState= 2;
IASTExpression op2 = expr.getOperand2();
if (op2 instanceof IASTBinaryExpression) {
N n= new N((IASTBinaryExpression) op2);
n.fNext= stack;
stack= n;
continue;
}
if (op2 != null && !op2.accept(action))
return false;
}
if (action.shouldVisitExpressions && action.leave(expr) == ASTVisitor.PROCESS_ABORT)
return false;
stack= stack.fNext;
}
return true;
}
public void replace(IASTNode child, IASTNode other) { public void replace(IASTNode child, IASTNode other) {
if( child == operand1 ) if( child == operand1 )
{ {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others. * Copyright (c) 2004, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
@ -112,51 +113,115 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
} }
@Override @Override
public boolean accept( ASTVisitor action ){ public boolean accept(ASTVisitor action) {
if( action.shouldVisitExpressions ){ if (operand1 instanceof IASTBinaryExpression || operand2 instanceof IASTBinaryExpression) {
switch( action.visit( this ) ){ return acceptWithoutRecursion(this, action);
}
if (action.shouldVisitExpressions) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT : return false; case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true; case ASTVisitor.PROCESS_SKIP : return true;
default : break; default : break;
} }
} }
if( operand1 != null ) if( !operand1.accept( action ) ) return false; if (operand1 != null && !operand1.accept(action))
return false;
if(action.shouldVisitImplicitNames) { if (action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) { for (IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false; if (!name.accept(action))
} return false;
} }
}
if( operand2 != null ) if( !operand2.accept( action ) ) return false; if (operand2 != null && !operand2.accept(action))
return false;
if(action.shouldVisitExpressions ){
switch( action.leave( this ) ){ if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT)
case ASTVisitor.PROCESS_ABORT : return false; return false;
case ASTVisitor.PROCESS_SKIP : return true;
default : break; return true;
}
}
return true;
} }
public void replace(IASTNode child, IASTNode other) { private static class N {
if( child == operand1 ) final IASTBinaryExpression fExpression;
{ int fState;
other.setPropertyInParent( child.getPropertyInParent() ); N fNext;
other.setParent( child.getParent() );
operand1 = (IASTExpression) other; N(IASTBinaryExpression expr) {
} fExpression = expr;
if( child == operand2 ) }
{ }
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() ); public static boolean acceptWithoutRecursion(IASTBinaryExpression bexpr, ASTVisitor action) {
operand2 = (IASTExpression) other; N stack= new N(bexpr);
} while(stack != null) {
} IASTBinaryExpression expr= stack.fExpression;
if (stack.fState == 0) {
if (action.shouldVisitExpressions) {
switch (action.visit(expr)) {
case ASTVisitor.PROCESS_ABORT :
return false;
case ASTVisitor.PROCESS_SKIP:
stack= stack.fNext;
continue;
}
}
stack.fState= 1;
IASTExpression op1 = expr.getOperand1();
if (op1 instanceof IASTBinaryExpression) {
N n= new N((IASTBinaryExpression) op1);
n.fNext= stack;
stack= n;
continue;
}
if (op1 != null && !op1.accept(action))
return false;
}
if (stack.fState == 1) {
if (action.shouldVisitImplicitNames) {
for (IASTImplicitName name : ((IASTImplicitNameOwner) expr).getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
stack.fState= 2;
IASTExpression op2 = expr.getOperand2();
if (op2 instanceof IASTBinaryExpression) {
N n= new N((IASTBinaryExpression) op2);
n.fNext= stack;
stack= n;
continue;
}
if (op2 != null && !op2.accept(action))
return false;
}
if (action.shouldVisitExpressions && action.leave(expr) == ASTVisitor.PROCESS_ABORT)
return false;
stack= stack.fNext;
}
return true;
}
public void replace(IASTNode child, IASTNode other) {
if (child == operand1) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
operand1 = (IASTExpression) other;
}
if (child == operand2) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
operand2 = (IASTExpression) other;
}
}
public IType getExpressionType() { public IType getExpressionType() {
if (type == null) { if (type == null) {