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

Bug 429196 Eliminate StackOverflow on adaptBinding.

A pretty simple and kludgy fix to the problem, but if we detect that
we are adapting a binding that we are just in the middle of adapting,
we bail and return null. Added Andrew's JUnit that reproduces the
problem in case someone wants to try a better solution.

Change-Id: Ib4a85c161be6aee073fee7ac0501464b70020fac
Reviewed-on: https://git.eclipse.org/r/24396
Reviewed-by: Doug Schaefer <dschaefer@qnx.com>
IP-Clean: Doug Schaefer <dschaefer@qnx.com>
Tested-by: Doug Schaefer <dschaefer@qnx.com>
Reviewed-on: https://git.eclipse.org/r/24409
Tested-by: Hudson CI
This commit is contained in:
Doug Schaefer 2014-04-03 10:28:25 -04:00
parent 88ba69a961
commit 1c70ddf64a
2 changed files with 91 additions and 1 deletions

View file

@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTName;
@ -2537,4 +2538,81 @@ public class IndexBugsTests extends BaseTestCase {
IndexerPreferences.setUpdatePolicy(fCProject.getProject(), IndexerPreferences.getDefaultUpdatePolicy());
}
}
// extern int h1;
// extern int h2;
// #include "../p1/h1.hh"
// #include "h2.hh"
// static int i = h1;
public void test429196StackOverflow() throws Exception {
// Bug429196: StackOverflow when creating a PDOMBinding in the following case: 2550
// 1) The variable is file-local 2551
// 2) The TU's indexFileSet has more than one fragment 2552
IIndex index = null;
boolean locked = false;
String[] contents = getContentsForTest(3);
ICProject p1 = CProjectHelper.createCCProject("p1", "bin", IPDOMManager.ID_FAST_INDEXER);
try {
IProjectDescription desc = fCProject.getProject().getDescription();
desc.setReferencedProjects(new IProject[] { p1.getProject() });
fCProject.getProject().setDescription(desc, npm());
// make sure the header is read from the other pdom when the ast is created
IFile head1 = TestSourceReader.createFile(p1.getProject(), "h1.hh", contents[0]);
CCorePlugin.getIndexManager().reindex(p1);
waitForIndexer(p1);
IFile head2 = TestSourceReader.createFile(fCProject.getProject(), "h2.hh", contents[1]);
IFile impl2 = TestSourceReader.createFile(fCProject.getProject(), "file.cc", contents[2]);
CCorePlugin.getIndexManager().reindex(fCProject);
waitForIndexer(fCProject);
index = CCorePlugin.getIndexManager().getIndex(new ICProject[] { p1, fCProject });
ITranslationUnit tu = (ITranslationUnit) CoreModel.getDefault().create(impl2);
assertNotNull(tu);
index.acquireReadLock();
locked = true;
IASTTranslationUnit ast = tu.getAST(
index,
ITranslationUnit.AST_SKIP_ALL_HEADERS
| ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT
| ITranslationUnit.AST_SKIP_TRIVIAL_EXPRESSIONS_IN_AGGREGATE_INITIALIZERS
| ITranslationUnit.AST_PARSE_INACTIVE_CODE);
assertNotNull(ast);
IASTDeclaration[] decls = ast.getDeclarations();
assertNotNull(decls);
assertEquals(1, decls.length);
assertTrue(decls[0] instanceof IASTSimpleDeclaration);
IASTDeclarator[] decltors = ((IASTSimpleDeclaration)decls[0]).getDeclarators();
assertNotNull(decltors);
assertEquals(1, decltors.length);
IASTName name = decltors[0].getName();
assertNotNull(name);
assertEquals("i", name.getRawSignature());
IBinding var = name.resolveBinding();
assertNotNull(var);
IIndexBinding adapted = null;
try {
adapted = index.adaptBinding(var);
} catch (StackOverflowError e) {
fail();
}
assertNotNull(adapted);
} finally {
if (index != null && locked)
index.releaseReadLock();
if (p1 != null)
CProjectHelper.delete(p1);
}
}
}

View file

@ -1088,9 +1088,21 @@ public class PDOM extends PlatformObject implements IPDOM {
return fLinkageIDCache.get(linkage.getLinkageID());
}
private IBinding inProgress;
@Override
public IIndexFragmentBinding adaptBinding(IBinding binding) throws CoreException {
return adaptBinding(binding, true);
if (inProgress == binding) {
// Detect if we're recursing during the adapt. That shouldn't happen and
// leads to stack overflow when it does.
return null;
}
inProgress = binding;
IIndexFragmentBinding result = adaptBinding(binding, true);
inProgress = null;
return result;
}
private IIndexFragmentBinding adaptBinding(IBinding binding, boolean includeLocal) throws CoreException {