java-topology/defects/luigi/patch/luigi-0001-deps-dfs-path-set.patch

25 lines
1.2 KiB
Diff

# UNDF: UNDF-2026-000000159
diff --git a/luigi/tools/deps.py b/luigi/tools/deps.py
--- a/luigi/tools/deps.py
+++ b/luigi/tools/deps.py
@@ -55,9 +55,14 @@ def get_task_requires(task):
return set(flatten(task.requires()))
-def dfs_paths(start_task, goal_task_family, path=None):
+def dfs_paths(start_task, goal_task_family, path=None, path_set=None):
+ # CWE-407 fix: maintain a parallel set alongside the path list so the
+ # visited-ancestor check is O(1) instead of rebuilding set(path) — O(depth)
+ # — on every recursive call. Previously: O(D²) total; now: O(D).
if path is None:
path = [start_task]
- if start_task.task_family == goal_task_family or goal_task_family is None:
+ path_set = {start_task}
+ if start_task.task_family == goal_task_family or goal_task_family is None:
for item in path:
yield item
- for next in get_task_requires(start_task) - set(path):
- for t in dfs_paths(next, goal_task_family, path + [next]):
+ for next in get_task_requires(start_task) - path_set:
+ for t in dfs_paths(next, goal_task_family, path + [next], path_set | {next}):
yield t