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:
parent
88ba69a961
commit
1c70ddf64a
2 changed files with 91 additions and 1 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue