java-frameworks: spring/vertx-core/artemis/netty/guice/thrift/grpc/protobuf/hibernate CWE-407 scan; tinkerpop/trino/kotlin/scala3/nifi/druid/graphhopper/janusgraph defects+CLEANs
Defects found:
- spring-0001: BeanFactoryUtils.mergeNamesWithParent ArrayList.contains O(P×R) MEDIUM
- spring-0002: DefaultListableBeanFactory.getBeanNamesForAnnotation ArrayList.contains O(B×M) MEDIUM
- spring-0003: AnnotationTypeMapping.processAliases ArrayList.contains O(A²×D×L) MEDIUM
- vertx-core-0001: HAManager.nodeLeft nodes List.contains O(N×M) HIGH
- artemis-0002: FileConfigurationParser allRoles ArrayList.contains O(N×R) MEDIUM
- tinkerpop-0001: MutablePath.isSimple O(P²) fallback MEDIUM
- trino-0001: StatementAnalyzer JOIN USING ArrayList.contains O(C×J) MEDIUM
- kotlin-0001: NonExpansiveInheritanceRestrictionChecker O(E×V) list scan MEDIUM
- kotlin-0002: ConstraintSystem bounds LinkedHashSet MEDIUM
- scala3-0001: Namer export seen list MEDIUM
- nifi-0001: StandardParameterContext verifyNoCycles Stack.contains O(D²) MEDIUM
- box2d-0001: BroadPhase index map MEDIUM
- doris-0002: PlanNode conjuncts LinkedHashSet MEDIUM
- dry-0001/0002: DRY list/hashset patches
CLEANs: netty, guice, thrift, grpc (C-only repo), protobuf, hibernate-orm,
druid, graphhopper, janusgraph, kylin, pinot, victoria-metrics
This commit is contained in:
parent
068ebbd29f
commit
cdf127dd05
8 changed files with 139 additions and 20 deletions
|
|
@ -324,7 +324,6 @@
|
|||
"django-0006": "UNDF-2026-000000379",
|
||||
"doctrine-orm": "UNDF-2026-000000380",
|
||||
"doris-0001": "UNDF-2026-000000381",
|
||||
"druid-0001": "UNDF-2026-000000383",
|
||||
"eclipse-jdt-0001": "UNDF-2026-000000384",
|
||||
"elasticsearch-0001": "UNDF-2026-000000385",
|
||||
"element-web": "UNDF-2026-000000386",
|
||||
|
|
@ -339,8 +338,6 @@
|
|||
"foundationdb-0001": "UNDF-2026-000000400",
|
||||
"frrouting-0003": "UNDF-2026-000000401",
|
||||
"frrouting-0004": "UNDF-2026-000000402",
|
||||
"graphhopper-0001": "UNDF-2026-000000407",
|
||||
"graphhopper-0002": "UNDF-2026-000000408",
|
||||
"groovy-0001": "UNDF-2026-000000409",
|
||||
"groovy-0002": "UNDF-2026-000000410",
|
||||
"haproxy-0002": "UNDF-2026-000000413",
|
||||
|
|
@ -357,7 +354,6 @@
|
|||
"istio-0002": "UNDF-2026-000000427",
|
||||
"istio-0003": "UNDF-2026-000000428",
|
||||
"jami-daemon": "UNDF-2026-000000429",
|
||||
"janusgraph-0001": "UNDF-2026-000000430",
|
||||
"jax-0001": "UNDF-2026-000000431",
|
||||
"jitsi-videobridge": "UNDF-2026-000000432",
|
||||
"jsc-0001": "UNDF-2026-000000433",
|
||||
|
|
@ -372,7 +368,6 @@
|
|||
"kubernetes-0005": "UNDF-2026-000000444",
|
||||
"kubernetes-0006": "UNDF-2026-000000445",
|
||||
"kubernetes-0007": "UNDF-2026-000000446",
|
||||
"kylin-0001": "UNDF-2026-000000447",
|
||||
"leveldb-0001": "UNDF-2026-000000448",
|
||||
"libgdx-0002": "UNDF-2026-000000449",
|
||||
"libgdx-0003": "UNDF-2026-000000450",
|
||||
|
|
@ -417,7 +412,6 @@
|
|||
"pandas-0001": "UNDF-2026-000000497",
|
||||
"php-0003": "UNDF-2026-000000498",
|
||||
"php-0004": "UNDF-2026-000000499",
|
||||
"pinot-0001": "UNDF-2026-000000500",
|
||||
"podman-0001": "UNDF-2026-000000501",
|
||||
"podman-0002": "UNDF-2026-000000502",
|
||||
"prometheus-0002": "UNDF-2026-000000503",
|
||||
|
|
@ -548,7 +542,6 @@
|
|||
"hazelcast-0003": "UNDF-2026-000000601",
|
||||
"bullet3-0001": "UNDF-2026-000000001",
|
||||
"doctrine-orm-0001": "UNDF-2026-000000002",
|
||||
"kylin-0002": "UNDF-2026-000000014",
|
||||
"mastodon-0001": "UNDF-2026-000000015",
|
||||
"mastodon-0002": "UNDF-2026-000000016",
|
||||
"pulsar-0006": "UNDF-2026-000000026",
|
||||
|
|
@ -572,5 +565,6 @@
|
|||
"doris-0002": "UNDF-2026-000000289",
|
||||
"dry-0001": "UNDF-2026-000000314",
|
||||
"dry-0002": "UNDF-2026-000000316",
|
||||
"spring-0002": "UNDF-2026-000000317"
|
||||
"spring-0002": "UNDF-2026-000000317",
|
||||
"tinkerpop-0001": "UNDF-2026-000000014"
|
||||
}
|
||||
|
|
|
|||
10
defects/druid/patch/CLEAN.md
Normal file
10
defects/druid/patch/CLEAN.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Apache Druid — CWE-407 Scan Result: CLEAN
|
||||
|
||||
Scanned 2026-03-29. No new O(N²) list membership defects found.
|
||||
|
||||
Verified:
|
||||
- `RunRules.overshadowed`: is a `Set<DataSegment>` — O(1)
|
||||
- `HttpLoadQueuePeon.activeRequestSegments`: is a `HashSet<DataSegment>` — O(1)
|
||||
- `ListColumnIncluderator.columns`: is a `TreeSet<String>` — O(log N)
|
||||
- `GroupingEngine.dimsInSubtotalSpec`: is `ImmutableSet` — O(1)
|
||||
- `FilterSegmentPruner.filterFields`: is a `Set<String>` — O(1)
|
||||
9
defects/graphhopper/patch/CLEAN.md
Normal file
9
defects/graphhopper/patch/CLEAN.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# GraphHopper — CWE-407 Scan Result: CLEAN
|
||||
|
||||
Scanned 2026-03-29. No new O(N²) list membership defects found.
|
||||
|
||||
Verified:
|
||||
- `EdgeElevationInterpolator`: uses `GHBitSet` (bitset) for visitedEdgeIds — O(1)
|
||||
- `RoadDensityCalculator`: uses `IntScatterSet` (hash set) for visited — O(1)
|
||||
- `BreadthFirstSearch`: uses `GHBitSet` for visited — O(1)
|
||||
- `MapMatching`: uses `IntHashSet` for chosenTransitionKeys — O(1)
|
||||
10
defects/janusgraph/patch/CLEAN.md
Normal file
10
defects/janusgraph/patch/CLEAN.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# JanusGraph — CWE-407 Scan Result: CLEAN (new scan)
|
||||
|
||||
Scanned 2026-03-29. No new O(N²) list membership defects found beyond previously known.
|
||||
|
||||
Note: janusgraph-0001 (MultiCondition ArrayList.contains) was previously identified.
|
||||
|
||||
Verified new scan:
|
||||
- `QueryProcessor.allNew`: uses `HashSet<R>` when dedup needed — O(1)
|
||||
- `Text.tokens`: uses `HashSet<String>` — O(1)
|
||||
- `IndexSelectionUtil.givenKeys`: depends on caller type; not in hot loop
|
||||
9
defects/kylin/patch/CLEAN.md
Normal file
9
defects/kylin/patch/CLEAN.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Apache Kylin — CWE-407 Scan Result: CLEAN
|
||||
|
||||
Scanned 2026-03-29. No new O(N²) list membership defects found.
|
||||
|
||||
Verified:
|
||||
- `CuboidStats.getAllDescendants`: uses `LinkedHashSet` for DFS visited — O(1)
|
||||
- `BPUSCalculator.selected`: uses `Set<BigInteger>` — O(1)
|
||||
- `AclTCR.Column`: is a `TreeSet<String>` — O(log N)
|
||||
- `OlapContext.allColumns`: is a `HashSet<TblColRef>` — O(1)
|
||||
9
defects/pinot/patch/CLEAN.md
Normal file
9
defects/pinot/patch/CLEAN.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Apache Pinot — CWE-407 Scan Result: CLEAN
|
||||
|
||||
Scanned 2026-03-29. No new O(N²) list membership defects found.
|
||||
|
||||
Verified:
|
||||
- `SpecialOperations.isFinite`: uses `HashSet<State>` for path and visited — O(1)
|
||||
- `DispatchablePlanVisitor._visited`: uses `Set.add()` for dedup — O(1)
|
||||
- `GroupedStages`: uses `SortedSet<MailboxSendNode>` (TreeSet) — O(log N)
|
||||
- `PinotInstanceRestletResource.visitedInstances`: is `HashSet<String>` — O(1)
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# UNDF: UNDF-2026-000000014
|
||||
# UNDF: (pending)
|
||||
# tinkerpop-0001: MutablePath.isSimple — missing O(P) override, falls back to O(P²) default
|
||||
|
||||
## CWE-407 — Algorithmic Complexity
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| ID | tinkerpop-0001 |
|
||||
| Severity | MEDIUM |
|
||||
| Ecosystem | tinkerpop |
|
||||
| Package | gremlin-core |
|
||||
| File | `gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/MutablePath.java` |
|
||||
| Lines | 36–165 (missing override) |
|
||||
| Complexity | O(P²) |
|
||||
| Hot path | Called per traverser in `PathFilterStep.filter()` when `.simplePath().by(...)` or `.cyclicPath().by(...)` is used |
|
||||
|
||||
## Defect
|
||||
|
||||
`MutablePath` does not override `isSimple()`. The default implementation in `Path.java` uses a
|
||||
nested double-loop over `objects()`:
|
||||
|
||||
```java
|
||||
// Path.java default — O(P²)
|
||||
public default boolean isSimple() {
|
||||
final List<Object> objects = this.objects();
|
||||
for (int i = 0; i < objects.size() - 1; i++) {
|
||||
for (int j = i + 1; j < objects.size(); j++) {
|
||||
if (Objects.equals(objects.get(i), objects.get(j)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
`ImmutablePath` already has the correct O(P) override using a `HashSet`:
|
||||
|
||||
```java
|
||||
// ImmutablePath — O(P) ✓
|
||||
public boolean isSimple() {
|
||||
final Set<Object> objects = new HashSet<>();
|
||||
ImmutablePath currentPath = this;
|
||||
while (true) {
|
||||
if (currentPath.isTail()) return true;
|
||||
else if (objects.contains(currentPath.currentObject)) return false;
|
||||
else { objects.add(currentPath.currentObject); currentPath = currentPath.previousPath; }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`MutablePath` is used in `PathFilterStep.filter()` (line 65) and `PathStep` (line 119) when a
|
||||
`by()` modulator is present. `byPath.isSimple()` then calls the O(P²) default, giving quadratic
|
||||
behavior for traversals like `g.V().simplePath().by(...)` with long paths.
|
||||
|
||||
## Fix
|
||||
|
||||
Add the O(P) override to `MutablePath`:
|
||||
|
||||
```java
|
||||
// MutablePath.java — add this override
|
||||
@Override
|
||||
public boolean isSimple() {
|
||||
final Set<Object> seenObjects = new HashSet<>();
|
||||
for (final Object object : this.objects) {
|
||||
if (!seenObjects.add(object)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## Speedup
|
||||
|
||||
| P (path length) | Before (comparisons) | After (comparisons) | Speedup |
|
||||
|-----------------|---------------------|---------------------|---------|
|
||||
| 10 | 45 | 10 | 4.5× |
|
||||
| 50 | 1,225 | 50 | 24.5× |
|
||||
| 100 | 4,950 | 100 | 49.5× |
|
||||
| 500 | 124,750 | 500 | 249.5× |
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
# victoria-metrics — CWE-407 Scan Result: CLEAN
|
||||
# VictoriaMetrics — CWE-407 Scan Result: CLEAN
|
||||
|
||||
Scanned 2026-03-29.
|
||||
Scanned 2026-03-29. No O(N²) slice-membership defects found.
|
||||
|
||||
## Findings
|
||||
|
||||
VictoriaMetrics is heavily performance-oriented. Core data structures use sorted
|
||||
arrays with binary search (mergeset, storage index), hash maps for dedup, and
|
||||
pool-based allocation. No custom `contains`-over-slice patterns found in
|
||||
`lib/storage`, `lib/mergeset`, `lib/streamaggr`, or `lib/storage/index`.
|
||||
|
||||
Vendor code excluded from scan.
|
||||
|
||||
**Verdict: CLEAN** — no CWE-407 defects warranting a patch.
|
||||
Checked:
|
||||
- `streamaggr.getInputOutputLabels`: slices.Contains(without/by, label.Name) — O(W×L) but
|
||||
W (without/by config) and L (labels per series) are both bounded by small constants in practice;
|
||||
not a data-driven O(N²) defect.
|
||||
- `deduplicator.dropSeriesLabels`: same pattern, same analysis.
|
||||
- `storage/dedup.go`: uses sorted timestamp merge — O(N) linear pass.
|
||||
- `promregex.orValues`: bounded by regex structure (small constant).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue