2.9 KiB
UNDF: UNDF-2026-000000360
camel-0001 — O(R²) Route Startup Endpoint Clash Scan
Severity: HIGH Complexity: O(R²) → O(R) CWE: CWE-407 (Algorithmic Complexity)
Affected File
| File | Lines | Notes |
|---|---|---|
core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/InternalRouteStartupManager.java |
357–444 | Route startup consumer clash check |
Defective Code
InternalRouteStartupManager.doStartOrResumeRouteConsumers lines 357–444
List<Endpoint> routeInputs = new ArrayList<>();
for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
// ...
Endpoint endpoint = consumer.getEndpoint();
// CHECK 1: O(R) linear scan inside O(R) outer loop → O(R²)
if (!doCheckMultipleConsumerSupportClash(endpoint, routeInputs)) {
throw new FailedToStartRouteException(...);
}
// CHECK 2: rebuild existingEndpoints as ArrayList each iteration → O(R²)
List<Endpoint> existingEndpoints = new ArrayList<>();
for (Route existingRoute : camelContext.getRoutes()) {
// ... add to existingEndpoints
}
if (!doCheckMultipleConsumerSupportClash(endpoint, existingEndpoints)) {
throw new FailedToStartRouteException(...);
}
routeInputs.add(endpoint); // List grows by 1 each iteration
}
doCheckMultipleConsumerSupportClash calls routeInputs.contains(endpoint) and
existingEndpoints.contains(endpoint). Both lists use ArrayList.contains() which
is O(N). The outer loop runs R times (R = number of routes). Total: O(R²).
Root Cause
routeInputs is declared as ArrayList<Endpoint>. The .contains() call scans
every existing element linearly. At R=1000 routes, this is ~500,000 comparisons
instead of ~1,000.
Fix
Replace ArrayList<Endpoint> with LinkedHashSet<Endpoint> (preserves insertion
order, provides O(1) contains()):
// Before
List<Endpoint> routeInputs = new ArrayList<>();
// After
Set<Endpoint> routeInputs = new LinkedHashSet<>();
doCheckMultipleConsumerSupportClash accepts a Collection<Endpoint> parameter
(declared as List<Endpoint>), so the call site parameter type must also be updated:
// Before
private boolean doCheckMultipleConsumerSupportClash(Endpoint endpoint, List<Endpoint> routeInputs)
// After
private boolean doCheckMultipleConsumerSupportClash(Endpoint endpoint, Collection<Endpoint> routeInputs)
For existingEndpoints, use LinkedHashSet as well:
// Before
List<Endpoint> existingEndpoints = new ArrayList<>();
// After
Set<Endpoint> existingEndpoints = new LinkedHashSet<>();
Impact
- Affects Camel applications with R ≥ 50 routes at startup
- Startup time grows quadratically with route count
- At R=500: ~12,500 comparisons → ~500 (25x reduction)
- At R=1000: ~500,000 comparisons → ~1,000 (500x reduction)
- Cloud deployments with large route counts (e.g., microservice monorepos using Camel) are most affected