From 586726fb1373954929729dada850775f6fa8ad68 Mon Sep 17 00:00:00 2001 From: Moritz Raabe Date: Wed, 19 May 2021 13:17:28 +0200 Subject: [PATCH] lint statements for single child statements --- CHANGELOG.md | 1 + scripts/lint.py | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cafeda7f..313b3e43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,6 +101,7 @@ It includes many new rules, including all new techniques introduced in MITRE ATT - ci: add capa release link to capa-rules tag #517 @Ana06 - ci, changelog: update `New Rules` section in CHANGELOG automatically https://github.com/fireeye/capa-rules/pull/374 #549 @Ana06 - ci, changelog: support multiple author in sync GH https://github.com/fireeye/capa-rules/pull/378 @Ana06 +- ci, lint: check statements for single child statements #563 @mr-tz ### Raw diffs diff --git a/scripts/lint.py b/scripts/lint.py index 893b8cfd..47f260f7 100644 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -218,6 +218,29 @@ class DoesntMatchExample(Lint): return True +class StatementWithSingleChildStatement(Lint): + name = "rule contains one or more statements with a single child statement" + recommendation = "remove the superfluous parent statement" + recommendation_template = "remove the superfluous parent statement: {:s}" + violation = False + + def check_rule(self, ctx, rule): + self.violation = False + + def rec(statement, is_root=False): + if isinstance(statement, (capa.engine.And, capa.engine.Or)): + children = list(statement.get_children()) + if not is_root and len(children) == 1 and isinstance(children[0], capa.engine.Statement): + self.recommendation = self.recommendation_template.format(str(statement)) + self.violation = True + for child in children: + rec(child) + + rec(rule.statement, is_root=True) + + return self.violation + + class UnusualMetaField(Lint): name = "unusual meta field" recommendation = "Remove the meta field" @@ -472,7 +495,10 @@ def get_rule_features(rule): return features -LOGIC_LINTS = (DoesntMatchExample(),) +LOGIC_LINTS = ( + DoesntMatchExample(), + StatementWithSingleChildStatement(), +) def lint_logic(ctx, rule):