java-topology/defects/spring-framework/patch/spring-framework-0003-encoded-resource-resolver-content-codings-o-a-c.patch
russell@unturf.com 0b37443f11 spring-framework: 3 CWE-407 defects (UNDF-2026-000000734 through UNDF-2026-000000736)
spring-framework-0001 (UNDF-734): CorsConfiguration.checkHeaders() O(R×A)
  - requestHeaders list (R) × allowedHeaders ArrayList (A) nested loop
  - equalsIgnoreCase() scan per header — 14x measured at R=20, A=50
  - Fix: build lowercase LinkedHashSet once O(A), lookup O(1) per header

spring-framework-0002 (UNDF-735): AcceptHeaderLocaleResolver O(R×S)
  - Accept-Language locales (R) × supportedLocales ArrayList (S)
  - per-request linear scan: 9x at R=15, S=20
  - Same defect in AcceptHeaderLocaleContextResolver (reactive)
  - Fix: LinkedHashSet for O(1) full-locale match

spring-framework-0003 (UNDF-736): EncodedResourceResolver.contentCodings O(A×C)
  - acceptedCodings (A) × contentCodings ArrayList (C) per static resource request
  - 8x at A=10, C=8
  - Fix: LinkedHashSet for O(1) contains per accepted encoding
  - Both spring-webmvc and spring-webflux variants

3/3 unit tests PASS
2026-03-30 08:27:16 -04:00

54 lines
2.2 KiB
Diff

# UNDF: UNDF-2026-000000736
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.LinkedHashSet;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
@@ -66,7 +67,8 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
- private final List<String> contentCodings = new ArrayList<>(DEFAULT_CODINGS);
+ // FIX: Use LinkedHashSet so that contentCodings.contains() is O(1) per
+ // accepted-encoding token on every static-resource request, not O(C).
+ private final LinkedHashSet<String> contentCodings = new LinkedHashSet<>(DEFAULT_CODINGS);
public void setContentCodings(List<String> codings) {
this.contentCodings.clear();
this.contentCodings.addAll(codings);
}
public List<String> getContentCodings() {
- return Collections.unmodifiableList(this.contentCodings);
+ return Collections.unmodifiableList(new ArrayList<>(this.contentCodings));
}
--- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java
+++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.LinkedHashSet;
import java.util.Map;
@@ -67,7 +68,8 @@ public class EncodedResourceResolver extends AbstractResourceResolver {
- private final List<String> contentCodings = new ArrayList<>(DEFAULT_CODINGS);
+ // FIX: LinkedHashSet for O(1) contains() on per-request accept-encoding scan.
+ private final LinkedHashSet<String> contentCodings = new LinkedHashSet<>(DEFAULT_CODINGS);
public void setContentCodings(List<String> codings) {
this.contentCodings.clear();
this.contentCodings.addAll(codings);
}
public List<String> getContentCodings() {
- return Collections.unmodifiableList(this.contentCodings);
+ return Collections.unmodifiableList(new ArrayList<>(this.contentCodings));
}