From 1351cacc09389f78d7b57cd2716d24499800053f Mon Sep 17 00:00:00 2001 From: Robert Stupp Date: Wed, 21 Aug 2019 13:16:38 +0200 Subject: [PATCH] Prevent StackOverflowException caused by excessive 'or' via PatternMatcher Signed-off-by: Robert Stupp --- .../internal/file/pattern/PatternMatcher.java | 67 +++++++++++++++---- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/subprojects/files/src/main/java/org/gradle/api/internal/file/pattern/PatternMatcher.java b/subprojects/files/src/main/java/org/gradle/api/internal/file/pattern/PatternMatcher.java index 352cb46f8740..020bd62edfa6 100644 --- a/subprojects/files/src/main/java/org/gradle/api/internal/file/pattern/PatternMatcher.java +++ b/subprojects/files/src/main/java/org/gradle/api/internal/file/pattern/PatternMatcher.java @@ -16,6 +16,9 @@ package org.gradle.api.internal.file.pattern; +import java.util.ArrayList; +import java.util.List; + public abstract class PatternMatcher { public static final PatternMatcher MATCH_ALL = new PatternMatcher() { @Override @@ -37,21 +40,11 @@ public PatternMatcher or(PatternMatcher other) { public abstract boolean test(String[] segments, boolean isFile); public PatternMatcher and(final PatternMatcher other) { - return new PatternMatcher() { - @Override - public boolean test(String[] segments, boolean isFile) { - return PatternMatcher.this.test(segments, isFile) && other.test(segments, isFile); - } - }; + return new And(PatternMatcher.this, other); } public PatternMatcher or(final PatternMatcher other) { - return new PatternMatcher() { - @Override - public boolean test(String[] segments, boolean isFile) { - return PatternMatcher.this.test(segments, isFile) || other.test(segments, isFile); - } - }; + return new Or(PatternMatcher.this, other); } public PatternMatcher negate() { @@ -62,4 +55,54 @@ public boolean test(String[] segments, boolean isFile) { } }; } + + private static final class Or extends PatternMatcher { + private final List parts = new ArrayList(); + + public Or(PatternMatcher patternMatcher, PatternMatcher other) { + parts.add(patternMatcher); + parts.add(other); + } + + @Override + public PatternMatcher or(PatternMatcher other) { + parts.add(other); + return this; + } + + @Override + public boolean test(String[] segments, boolean isFile) { + for (PatternMatcher part : parts) { + if (part.test(segments, isFile)) { + return true; + } + } + return false; + } + } + + private static final class And extends PatternMatcher { + private final List parts = new ArrayList(); + + public And(PatternMatcher patternMatcher, PatternMatcher other) { + parts.add(patternMatcher); + parts.add(other); + } + + @Override + public PatternMatcher and(PatternMatcher other) { + parts.add(other); + return this; + } + + @Override + public boolean test(String[] segments, boolean isFile) { + for (PatternMatcher part : parts) { + if (!part.test(segments, isFile)) { + return false; + } + } + return true; + } + } }