From 1c70ddf64a9827286fb0fdc72cb91e2cfee1d5aa Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 3 Apr 2014 10:28:25 -0400 Subject: [PATCH] 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 IP-Clean: Doug Schaefer Tested-by: Doug Schaefer Reviewed-on: https://git.eclipse.org/r/24409 Tested-by: Hudson CI --- .../internal/index/tests/IndexBugsTests.java | 78 +++++++++++++++++++ .../eclipse/cdt/internal/core/pdom/PDOM.java | 14 +++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index c66c25bd986..1b5ba244d32 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -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); + } + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 444ecc90df3..3ea3111057e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -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 {