Repository: mandiant/capa
File: scripts/lint.py (Python)

Code before:

class OptionalNotUnderAnd(Lint):
    name = "rule contains an `optional` or `0 or more` statement that's not found under an `and` statement"
    recommendation = "clarify the rule logic and ensure `optional` and `0 or more` is always found under `and`"
    violation = False

    def check_rule(self, ctx: Context, rule: Rule):
        self.violation = False

        def rec(statement):
            if isinstance(statement, capa.engine.Statement):
                if not isinstance(statement, capa.engine.And):
                    for child in statement.get_children():
                        if isinstance(child, capa.engine.Some) and child.count == 0:
                            self.violation = True

                for child in statement.get_children():
                    rec(child)

        rec(rule.statement)

        return self.violation


class DuplicateFeatureUnderStatement(Lint):
    name = "rule contains a duplicate feature under `or`/`and` statement"
    recommendation = "remove the duplicate features"
    recommendation_template = '\n\tduplicate line: "{:s}"\t: line numbers: {:s}'
    violation = False

    def check_rule(self, ctx: Context, rule: Rule) -> bool:
        STATEMENTS = frozenset(
            {
                "- or:",
                "- and:",
                "- not:",
                "- optional:",
                "- some:",
                "- basic block:",
                "- function:",
                "- instruction:",
                "- call:",
                " or more:",
            }
        )

        def is_statement(line: str) -> bool:
            return any(stmt in line for stmt in STATEMENTS)

        def get_indent(line: str) -> int:
            return line.find("-")

Review comment (refactor):
```suggestion
    name = "rule contains duplicate features"
```

Code after:

class RuleDependencyScopeMismatch(Lint):
    name = "rule dependency scope mismatch"
    level = Lint.FAIL
    recommendation_template: str = "rule '{:s}' ({:s}) depends on rule '{:s}' ({:s})."

    def check_rule(self, ctx: Context, rule: Rule):
        # get all rules by name for quick lookup
        rules_by_name = {r.name: r for r in ctx.rules.rules.values()}

        # get all dependencies of this rule
        namespaces = ctx.rules.rules_by_namespace
        dependencies = rule.get_dependencies(namespaces)

        for dep_name in dependencies:
            if dep_name not in rules_by_name:
                # another lint will catch missing dependencies
                continue

            dep_rule = rules_by_name[dep_name]

            if rule.scopes.static and not self._is_static_scope_compatible(rule, dep_rule):
                self.recommendation = self.recommendation_template.format(
                    rule.name,
                    rule.scopes.static or "static: unsupported",
                    dep_name,
                    dep_rule.scopes.static or "static: unsupported",
                )
                return True

            if rule.scopes.dynamic and not self._is_dynamic_scope_compatible(rule, dep_rule):
                self.recommendation = self.recommendation_template.format(
                    rule.name,
                    rule.scopes.dynamic or "dynamic: unsupported",
                    dep_name,
                    dep_rule.scopes.dynamic or "dynamic: unsupported",
                )
                return True

        return False

    @staticmethod
    def _is_static_scope_compatible(parent: Rule, child: Rule) -> bool:
        """
        A child rule's scope is compatible if it is equal to or lower than the parent scope.
        """

        if parent.scopes.static and not child.scopes.static and child.is_subscope_rule():
            # this is ok: the child isn't a static subscope rule
            return True