B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
43 lines
2.1 KiB
Diff
43 lines
2.1 KiB
Diff
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
|
|
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
|
|
@@ -203,13 +203,11 @@ public interface Path extends Cloneable, Iterable<Object> {
|
|
* @return whether the path is not a cycle
|
|
*/
|
|
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;
|
|
- }
|
|
+ final Set<Object> seen = new HashSet<>();
|
|
+ for (final Object object : this.objects()) {
|
|
+ if (!seen.add(object)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Add required import at top of file:
|
|
+import java.util.HashSet;
|
|
+import java.util.Set;
|
|
|
|
# CWE-407: O(n²) nested loop → O(n) HashSet
|
|
#
|
|
# Path.java:206-214 — default isSimple() implementation uses a nested double-loop
|
|
# to check for duplicate vertices in a path. This is O(n²) where n is path length.
|
|
# Called on every traverser evaluated by .simplePath() or .cyclicPath() Gremlin steps.
|
|
# The inner PathFilterStep triggers this via subPath() → MutablePath (which has no
|
|
# override), bypassing ImmutablePath's correct HashSet implementation at line 292.
|
|
#
|
|
# Impact: Every Gremlin graph traversal using .simplePath() or .cyclicPath() with
|
|
# from()/to() label scoping, or with by() modulators, executes O(n²) membership
|
|
# testing per traverser. For long paths in large graphs (e.g. social graph friend-of-
|
|
# friend queries, supply chain paths), this is quadratic in path length.
|
|
#
|
|
# Fix: Replace O(n²) nested loop with O(n) HashSet membership test. Matches the
|
|
# correct implementation already present in ImmutablePath.isSimple() at line 292.
|
|
#
|
|
# Upstream: apache/tinkerpop — gremlin-core/src/main/java/org/apache/tinkerpop/
|
|
# gremlin/process/traversal/Path.java
|
|
# Activated by: PathFilterStep.java:60,62,79 via subPath() → MutablePath
|
|
# Fixed by: HashSet dedup in default isSimple() — O(n²) → O(n)
|