41 lines
1.9 KiB
Diff
41 lines
1.9 KiB
Diff
# UNDF: UNDF-2026-000000222
|
||
From: agent-blackops <blackops@unturf.com>
|
||
Date: Fri, 27 Mar 2026 00:00:00 +0000
|
||
Subject: [PATCH] cache_policies: convert Inputs.exclude to frozenset in compute_key() for O(1) membership
|
||
|
||
CWE-407: Algorithmic complexity via O(N×M) linear membership test in the
|
||
task cache key computation hot path. Inputs.compute_key() performs
|
||
`key not in exclude` where exclude is a list[str], inside a for-loop over
|
||
all task inputs, producing O(N×M) comparisons per cached task invocation.
|
||
|
||
Fix: convert exclude list to a frozenset at compute_key() entry for O(1)
|
||
average membership test. The list field type is preserved for backward
|
||
compatibility with serialization and policy composition (`__add__`/`__sub__`);
|
||
conversion to set happens only during key computation where order is irrelevant.
|
||
|
||
Defect-Id: PRE-001
|
||
Severity: HIGH
|
||
CWE: CWE-407 (Inefficient Algorithmic Complexity)
|
||
---
|
||
src/prefect/cache_policies.py | 4 +++-
|
||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/src/prefect/cache_policies.py b/src/prefect/cache_policies.py
|
||
index xxxxxxx..yyyyyyy 100644
|
||
--- a/src/prefect/cache_policies.py
|
||
+++ b/src/prefect/cache_policies.py
|
||
@@ -372,7 +372,9 @@ class Inputs(CachePolicy):
|
||
def compute_key(self, task_ctx, inputs, flow_parameters, **kwargs):
|
||
hashed_inputs = {}
|
||
inputs = inputs or {}
|
||
- exclude = self.exclude or []
|
||
+ exclude = frozenset(self.exclude) if self.exclude else frozenset() # CWE-407 fix: O(1) membership
|
||
|
||
if not inputs:
|
||
return None
|
||
|
||
for key, val in inputs.items():
|
||
- if key not in exclude: # CWE-407: O(M) list scan
|
||
+ if key not in exclude: # CWE-407 fix: O(1) frozenset
|
||
transformer = STABLE_TRANSFORMS.get(type(val))
|
||
hashed_inputs[key] = transformer(val) if transformer else val
|