fix(test-steps): correct YAML structure handling in bare re-raise check
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 30s
CI / helm (pull_request) Successful in 40s
CI / build (pull_request) Successful in 47s
CI / lint (pull_request) Failing after 1m8s
CI / quality (pull_request) Successful in 1m9s
CI / typecheck (pull_request) Successful in 1m19s
CI / security (pull_request) Successful in 1m41s
CI / integration_tests (pull_request) Successful in 3m20s
CI / e2e_tests (pull_request) Successful in 4m23s
CI / unit_tests (pull_request) Successful in 4m44s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 30s
CI / helm (pull_request) Successful in 40s
CI / build (pull_request) Successful in 47s
CI / lint (pull_request) Failing after 1m8s
CI / quality (pull_request) Successful in 1m9s
CI / typecheck (pull_request) Successful in 1m19s
CI / security (pull_request) Successful in 1m41s
CI / integration_tests (pull_request) Successful in 3m20s
CI / e2e_tests (pull_request) Successful in 4m23s
CI / unit_tests (pull_request) Successful in 4m44s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
The Semgrep patterns node is a YAML list (not dict), so the previous implementation's .get() call on patterns would fail with AttributeError. Fix: properly handle 'patterns' as a list of alternation groups, each containing pattern-either -> patterns -> pattern-not entries. This ensures the BDD assertion robustly finds bare raise pattern-nots in the xml-no-suppressed-exception rule's nested structure. Issues Closed: #9103
This commit is contained in:
@@ -252,39 +252,44 @@ def step_semgrep_rule_has_reraise_pattern_not(context: Any, rule_id: str) -> Non
|
||||
rules = config.get("rules", [])
|
||||
for rule in rules:
|
||||
if rule.get("id") == rule_id:
|
||||
# Walk the patterns structure to find pattern-not entries with bare raise
|
||||
patterns = rule.get("patterns", {})
|
||||
pattern_either = patterns.get("pattern-either", [])
|
||||
# Walk the Semgrep patterns structure to find pattern-not entries with bare raise.
|
||||
# In YAML, 'patterns' is a list of alternative match groups (pattern-either).
|
||||
patterns = rule.get("patterns", [])
|
||||
if not isinstance(patterns, list):
|
||||
raise AssertionError(
|
||||
f"Rule '{rule_id}' has unexpected 'patterns' type: "
|
||||
f"{type(patterns).__name__}"
|
||||
)
|
||||
|
||||
found_bare_reraise = False
|
||||
for option in pattern_either:
|
||||
sub_patterns = option.get("patterns", [])
|
||||
for sp in sub_patterns:
|
||||
pn = sp.get("pattern-not", "")
|
||||
if isinstance(pn, str):
|
||||
# A bare re-raise pattern-not should have "raise" on its own
|
||||
# (not followed by $EXC or from clause)
|
||||
import re
|
||||
# Look for a pattern that has raise without arguments
|
||||
# e.g., "raise$" at end of a line (bare raise)
|
||||
lines = pn.split("\n")
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
# Bare re-raise: just "raise" with no trailing code
|
||||
if stripped == "raise":
|
||||
found_bare_reraise = True
|
||||
break
|
||||
for group in patterns:
|
||||
either_list = group.get("pattern-either", [])
|
||||
if not isinstance(either_list, list):
|
||||
continue
|
||||
for alt in either_list:
|
||||
sub_pats = alt.get("patterns", [])
|
||||
if not isinstance(sub_pats, list):
|
||||
continue
|
||||
for sp in sub_pats:
|
||||
pn = sp.get("pattern-not", "")
|
||||
if isinstance(pn, str):
|
||||
# A bare re-raise pattern-not must contain "raise" on its own line
|
||||
# (not raise $EXC or raise ... from ...)
|
||||
lines = pn.split("\n")
|
||||
for line in lines:
|
||||
if line.strip() == "raise":
|
||||
found_bare_reraise = True
|
||||
break
|
||||
|
||||
# Also check nested pattern-either blocks
|
||||
nested_either = option.get("pattern-either")
|
||||
if nested_either:
|
||||
for nested_opt in nested_either:
|
||||
pn = nested_opt.get("pattern-not", "")
|
||||
# Also handle nested pattern-either blocks inside alternation groups
|
||||
nested_either = alt.get("pattern-either") if isinstance(alt, dict) else None
|
||||
if isinstance(nested_either, list):
|
||||
for nested_alt in nested_either:
|
||||
pn = nested_alt.get("pattern-not", "")
|
||||
if isinstance(pn, str):
|
||||
lines = pn.split("\n")
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
if stripped == "raise":
|
||||
if line.strip() == "raise":
|
||||
found_bare_reraise = True
|
||||
break
|
||||
|
||||
|
||||
Reference in New Issue
Block a user