diff options
author | Tor Norbye <tnorbye@google.com> | 2013-10-10 00:04:20 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-10-10 00:04:20 +0000 |
commit | f2be3c6a35095de7775fe5c62e798ba06f637e18 (patch) | |
tree | 15fb5efddec5bc5f4f2faf4fb336085a5f9fe881 | |
parent | baa15109e42be30745e3deb434b6b2de60ad962d (diff) | |
parent | 2545b451003624e1fcde856cb5dab7bd0a9b713e (diff) | |
download | base-f2be3c6a35095de7775fe5c62e798ba06f637e18.tar.gz |
Merge "Prevent stack overflow problem with improperly configured lint projects. DO NOT MERGE" into tools_r22.2
-rw-r--r-- | lint/cli/src/test/java/com/android/tools/lint/client/api/ProjectTest.java | 94 | ||||
-rw-r--r-- | lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java | 25 |
2 files changed, 116 insertions, 3 deletions
diff --git a/lint/cli/src/test/java/com/android/tools/lint/client/api/ProjectTest.java b/lint/cli/src/test/java/com/android/tools/lint/client/api/ProjectTest.java index 4f3c9ef783..c9193213a3 100644 --- a/lint/cli/src/test/java/com/android/tools/lint/client/api/ProjectTest.java +++ b/lint/cli/src/test/java/com/android/tools/lint/client/api/ProjectTest.java @@ -16,12 +16,18 @@ package com.android.tools.lint.client.api; +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; import com.android.tools.lint.checks.AbstractCheckTest; import com.android.tools.lint.checks.UnusedResourceDetector; import com.android.tools.lint.detector.api.Detector; +import com.android.tools.lint.detector.api.Project; +import com.android.tools.lint.detector.api.Severity; import java.io.File; import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class ProjectTest extends AbstractCheckTest { @Override @@ -53,6 +59,94 @@ public class ProjectTest extends AbstractCheckTest { checkLint(Arrays.asList(master, library))); } + public void testInvalidLibraryReferences1() throws Exception { + TestClient client = new TestClient(); + File dir = new File("project"); + TestProject project1 = new TestProject(client, dir); + client.registerProject(dir, project1); + project1.setDirectLibraries(Collections.<Project>singletonList(project1)); + List<Project> libraries = project1.getAllLibraries(); + assertNotNull(libraries); + assertEquals( + "Warning: Internal lint error: cyclic library dependency for Project [dir=project]", + client.getLoggedOutput()); + } + + public void testInvalidLibraryReferences2() throws Exception { + TestClient client = new TestClient(); + File dir1 = new File("project1"); + File dir2 = new File("project2"); + TestProject project1 = new TestProject(client, dir1); + client.registerProject(dir1, project1); + TestProject project2 = new TestProject(client, dir2); + client.registerProject(dir2, project2); + project2.setDirectLibraries(Collections.<Project>singletonList(project1)); + project1.setDirectLibraries(Collections.<Project>singletonList(project2)); + List<Project> libraries = project1.getAllLibraries(); + assertNotNull(libraries); + assertEquals( + "Warning: Internal lint error: cyclic library dependency for Project [dir=project1]", + client.getLoggedOutput()); + assertEquals(1, libraries.size()); + assertSame(project2, libraries.get(0)); + assertEquals(1, project2.getAllLibraries().size()); + assertSame(project1, project2.getAllLibraries().get(0)); + } + + public void testOkLibraryReferences() throws Exception { + TestClient client = new TestClient(); + File dir1 = new File("project1"); + File dir2 = new File("project2"); + File dir3 = new File("project3"); + TestProject project1 = new TestProject(client, dir1); + client.registerProject(dir1, project1); + TestProject project2 = new TestProject(client, dir2); + client.registerProject(dir2, project2); + TestProject project3 = new TestProject(client, dir3); + client.registerProject(dir3, project3); + project1.setDirectLibraries(Arrays.<Project>asList(project2, project3)); + project2.setDirectLibraries(Collections.<Project>singletonList(project3)); + project3.setDirectLibraries(Collections.<Project>emptyList()); + List<Project> libraries = project1.getAllLibraries(); + assertNotNull(libraries); + assertEquals( + "", + client.getLoggedOutput()); + assertEquals(2, libraries.size()); + assertTrue(libraries.contains(project2)); + assertTrue(libraries.contains(project3)); + assertEquals(1, project2.getAllLibraries().size()); + assertSame(project3, project2.getAllLibraries().get(0)); + assertTrue(project3.getAllLibraries().isEmpty()); + } + + private class TestClient extends TestLintClient { + @SuppressWarnings("StringBufferField") + private StringBuilder mLog = new StringBuilder(); + + @Override + public void log(@NonNull Severity severity, @Nullable Throwable exception, + @Nullable String format, @Nullable Object... args) { + assertNotNull(format); + mLog.append(severity.getDescription()).append(": "); + mLog.append(String.format(format, args)); + } + + public String getLoggedOutput() { + return mLog.toString(); + } + } + + private static class TestProject extends Project { + protected TestProject(@NonNull LintClient client, @NonNull File dir) { + super(client, dir, dir); + } + + public void setDirectLibraries(List<Project> libraries) { + mDirectLibraries = libraries; + } + } + @Override protected Detector getDetector() { return new UnusedResourceDetector(); diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java index 983d5cc03d..508d8043b5 100644 --- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java +++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/Project.java @@ -42,6 +42,7 @@ import com.google.common.annotations.Beta; import com.google.common.base.CharMatcher; import com.google.common.base.Charsets; import com.google.common.base.Splitter; +import com.google.common.collect.Sets; import com.google.common.io.Closeables; import com.google.common.io.Files; @@ -58,6 +59,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Properties; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -608,7 +610,11 @@ public class Project { } List<Project> all = new ArrayList<Project>(); - addLibraryProjects(all); + Set<Project> seen = Sets.newHashSet(); + Set<Project> path = Sets.newHashSet(); + seen.add(this); + path.add(this); + addLibraryProjects(all, seen, path); mAllLibraries = all; } @@ -620,12 +626,25 @@ public class Project { * recursively into the given collection of projects * * @param collection the collection to add the projects into + * @param seen full set of projects we've processed + * @param path the current path of library dependencies followed */ - private void addLibraryProjects(@NonNull Collection<Project> collection) { + private void addLibraryProjects(@NonNull Collection<Project> collection, + @NonNull Set<Project> seen, @NonNull Set<Project> path) { for (Project library : mDirectLibraries) { + if (seen.contains(library)) { + if (path.contains(library)) { + mClient.log(Severity.WARNING, null, + "Internal lint error: cyclic library dependency for %1$s", library); + } + continue; + } collection.add(library); + seen.add(library); + path.add(library); // Recurse - library.addLibraryProjects(collection); + library.addLibraryProjects(collection, seen, path); + path.remove(library); } } |