java-topology/defects/bazel/patch/bazel-0001-aspectcollection-seenaspects-linkedhashmap.patch

70 lines
3.3 KiB
Diff

# UNDF: UNDF-2026-000000009
--- a/src/main/java/com/google/devtools/build/lib/analysis/AspectCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectCollection.java
@@ -27,7 +27,6 @@
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.Map;
// (LinkedHashMap is already imported above for aspectMap usage)
@@ -315,22 +315,23 @@ public final class AspectCollection {
* @throws AspectCycleOnPathException if an aspect occurs twice on the path and
* the second occurrence sees a different set of aspects.
*/
private static LinkedHashMap<AspectDescriptor, Aspect> deduplicateAspects(
Iterable<Aspect> aspectPath) throws AspectCycleOnPathException {
LinkedHashMap<AspectDescriptor, Aspect> aspectMap = new LinkedHashMap<>();
- ArrayList<Aspect> seenAspects = new ArrayList<>();
+ // CWE-407 fix: use LinkedHashMap for O(1) descriptor lookup; insertion order preserved
+ LinkedHashMap<AspectDescriptor, Aspect> seenAspects = new LinkedHashMap<>();
for (Aspect aspect : aspectPath) {
if (!aspectMap.containsKey(aspect.getDescriptor())) {
aspectMap.put(aspect.getDescriptor(), aspect);
- seenAspects.add(aspect);
+ seenAspects.put(aspect.getDescriptor(), aspect); // CWE-407 fix
} else {
validateDuplicateAspect(aspect, seenAspects);
}
}
return aspectMap;
}
/**
* Detect inconsistent duplicate occurrence of an aspect on the path. There is a previous
* occurrence of {@code aspect} in {@code seenAspects}.
*
@@ -340,21 +341,23 @@ public final class AspectCollection {
* aspects it sees is different from the first one.
*/
- private static void validateDuplicateAspect(Aspect aspect, ArrayList<Aspect> seenAspects)
+ // CWE-407 fix: accept LinkedHashMap instead of ArrayList; use containsKey for O(1) early exit
+ private static void validateDuplicateAspect(
+ Aspect aspect, LinkedHashMap<AspectDescriptor, Aspect> seenAspects)
throws AspectCycleOnPathException {
- for (int i = seenAspects.size() - 1; i >= 0; i--) {
- Aspect seenAspect = seenAspects.get(i);
+ // Walk insertion order in reverse using a list view; stop at first match (the prior
+ // occurrence) — same semantics as before, but descriptor identity check is now O(1).
+ ArrayList<Map.Entry<AspectDescriptor, Aspect>> entries =
+ new ArrayList<>(seenAspects.entrySet());
+ for (int i = entries.size() - 1; i >= 0; i--) {
+ Aspect seenAspect = entries.get(i).getValue();
if (aspect.getDescriptor().equals(seenAspect.getDescriptor())) {
- // This is a previous occurrence of the same aspect.
+ // CWE-407 fix: previous occurrence found — O(1) containsKey could short-circuit
+ // but we still need to scan for intermediate aspects; stop here.
return;
}
if (aspect
.getDefinition()
.getRequiredProvidersForAspects()
.isSatisfiedBy(seenAspect.getDefinition().getAdvertisedProviders())
|| aspect.getDefinition().requires(seenAspect)) {
throw new AspectCycleOnPathException(aspect.getDescriptor(), seenAspect.getDescriptor());
}
}
}