Skip to content

Commit f2c03e5

Browse files
authored
Improved redundant-existence-check (#1897)
By looking in both directions. Still not exhaustive, but that's way too expensive.. and most redundant checks are adjacent to the place of use. Fixes #1805 Signed-off-by: Anders Eknert <anders.eknert@apple.com>
1 parent b68d3ed commit f2c03e5

2 files changed

Lines changed: 99 additions & 25 deletions

File tree

bundle/regal/rules/bugs/redundant-existence-check/redundant_existence_check.rego

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,13 @@ import data.regal.result
88
# METADATA
99
# description: check rule bodies for redundant existence checks
1010
report contains violation if {
11-
some rule_index, rule in input.rules
12-
some expr_index, expr in _exprs[rule_index]
11+
some rule_index, expr_index
12+
expr := _static_ref_exprs[rule_index][expr_index]
1313

14-
expr.terms.type == "ref"
15-
16-
not expr.with
17-
18-
not rule.body[expr_index + 1].negated
19-
ast.static_ref(expr.terms)
20-
21-
some term in rule.body[expr_index + 1].terms
14+
some adjacent in [-1, 1]
15+
some term in _exprs[rule_index][expr_index + adjacent].terms
2216

17+
term.type == "ref"
2318
ast.is_terms_subset(expr.terms.value, term.value)
2419

2520
violation := result.fail(rego.metadata.chain(), result.ranged_from_ref(expr.terms.value))
@@ -34,37 +29,51 @@ report contains violation if {
3429
# quite unlikely that existence checks are found there
3530
report contains violation if {
3631
some func in ast.functions
32+
33+
arg_vars := {term.value |
34+
some term in func.head.args
35+
term.type == "var"
36+
}
37+
3738
some expr in func.body
3839

3940
not expr.negated
4041
expr.terms.type == "var"
41-
42-
some arg in func.head.args
43-
44-
arg.type == "var"
45-
arg.value == expr.terms.value
42+
expr.terms.value in arg_vars
4643

4744
violation := result.fail(rego.metadata.chain(), result.location(expr.terms))
4845
}
4946

5047
# METADATA
5148
# description: check for redundant existence checks in rule head assignment
5249
report contains violation if {
53-
some rule_index, rule in input.rules
50+
some rule_index
51+
input.rules[rule_index].head.value.type == "ref"
5452

55-
rule.head.value.type == "ref"
53+
head := input.rules[rule_index].head
5654

5755
some expr in _exprs[rule_index]
5856

59-
not expr.negated
6057
expr.terms.type == "ref"
61-
ast.is_terms_subset(expr.terms.value, rule.head.value.value)
58+
ast.is_terms_subset(expr.terms.value, head.value.value)
6259

6360
violation := result.fail(rego.metadata.chain(), result.ranged_from_ref(expr.terms.value))
6461
}
6562

6663
# all top-level expressions in module
6764
_exprs[rule_index][expr_index] := expr if {
68-
some rule_index, rule in input.rules
69-
some expr_index, expr in rule.body
65+
some rule_index, expr_index
66+
input.rules[rule_index].body[expr_index]
67+
68+
expr := input.rules[rule_index].body[expr_index]
69+
not expr.with
70+
not expr.negated
71+
}
72+
73+
_static_ref_exprs[rule_index][expr_index] := expr if {
74+
some rule_index, expr_index
75+
_exprs[rule_index][expr_index].terms.type == "ref"
76+
77+
expr := _exprs[rule_index][expr_index]
78+
ast.static_ref(expr.terms)
7079
}

bundle/regal/rules/bugs/redundant-existence-check/redundant_existence_check_test.rego

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ test_fail_redundant_existence_check if {
1616
"category": "bugs",
1717
"description": "Redundant existence check",
1818
"level": "error",
19-
"location": {"col": 3, "file": "policy.rego", "row": 7, "text": "\t\tinput.foo", "end": {"col": 12, "row": 7}},
19+
"location": {
20+
"col": 3,
21+
"file": "policy.rego",
22+
"row": 7,
23+
"text": "\t\tinput.foo",
24+
"end": {
25+
"col": 12,
26+
"row": 7,
27+
},
28+
},
2029
"related_resources": [{
2130
"description": "documentation",
2231
"ref": config.docs.resolve_url("$baseUrl/$category/redundant-existence-check", "bugs"),
@@ -36,7 +45,16 @@ test_fail_redundant_existence_check_subset if {
3645
"category": "bugs",
3746
"description": "Redundant existence check",
3847
"level": "error",
39-
"location": {"col": 3, "file": "policy.rego", "row": 7, "text": "\t\tinput.foo", "end": {"col": 12, "row": 7}},
48+
"location": {
49+
"col": 3,
50+
"file": "policy.rego",
51+
"row": 7,
52+
"text": "\t\tinput.foo",
53+
"end": {
54+
"col": 12,
55+
"row": 7,
56+
},
57+
},
4058
"related_resources": [{
4159
"description": "documentation",
4260
"ref": config.docs.resolve_url("$baseUrl/$category/redundant-existence-check", "bugs"),
@@ -75,7 +93,16 @@ test_fail_redundant_existence_check_head_assignment_of_ref if {
7593
"category": "bugs",
7694
"description": "Redundant existence check",
7795
"level": "error",
78-
"location": {"col": 3, "file": "policy.rego", "row": 7, "text": "\t\tinput.foo", "end": {"col": 12, "row": 7}},
96+
"location": {
97+
"col": 3,
98+
"file": "policy.rego",
99+
"row": 7,
100+
"text": "\t\tinput.foo",
101+
"end": {
102+
"col": 12,
103+
"row": 7,
104+
},
105+
},
79106
"related_resources": [{
80107
"description": "documentation",
81108
"ref": config.docs.resolve_url("$baseUrl/$category/redundant-existence-check", "bugs"),
@@ -94,7 +121,45 @@ test_fail_redundant_existence_check_function_arg if {
94121
"category": "bugs",
95122
"description": "Redundant existence check",
96123
"level": "error",
97-
"location": {"col": 3, "end": {"col": 6, "row": 7}, "file": "policy.rego", "row": 7, "text": "\t\tfoo"},
124+
"location": {
125+
"col": 3,
126+
"end": {
127+
"col": 6,
128+
"row": 7,
129+
},
130+
"file": "policy.rego",
131+
"row": 7,
132+
"text": "\t\tfoo",
133+
},
134+
"related_resources": [{
135+
"description": "documentation",
136+
"ref": config.docs.resolve_url("$baseUrl/$category/redundant-existence-check", "bugs"),
137+
}],
138+
"title": "redundant-existence-check",
139+
}}
140+
}
141+
142+
test_fail_redundant_existence_check_function_arg_reference_after_use if {
143+
r := rule.report with input as ast.with_rego_v1(`
144+
fun(foo) if {
145+
foo.type == "object"
146+
foo.type
147+
}`)
148+
149+
r == {{
150+
"category": "bugs",
151+
"description": "Redundant existence check",
152+
"level": "error",
153+
"location": {
154+
"col": 3,
155+
"end": {
156+
"col": 11,
157+
"row": 8,
158+
},
159+
"file": "policy.rego",
160+
"row": 8,
161+
"text": "\t\tfoo.type",
162+
},
98163
"related_resources": [{
99164
"description": "documentation",
100165
"ref": config.docs.resolve_url("$baseUrl/$category/redundant-existence-check", "bugs"),

0 commit comments

Comments
 (0)