fix: MissingExampleOffset lint reads scopes.static instead of obsolete scope key

The check was reading rule.meta.get("scope") which no longer exists in the
current schema (replaced by scopes.static/scopes.dynamic), causing the lint
to never fire for function/basic-block rules missing example offsets.
This commit is contained in:
Willi Ballenthin
2026-04-22 21:58:19 +03:00
committed by Willi Ballenthin
parent 4da1addfb3
commit c5ae9be3e1
3 changed files with 61 additions and 3 deletions
+1 -2
View File
@@ -48,8 +48,7 @@
- fix: remove unreachable backports.functools_lru_cache fallback and dead dependency @williballenthin
- fix: Scopes.from_dict uses cls instead of self so subclasses return the correct type @williballenthin
- fix: correct wrong dict key in VMRay _compute_monitor_threads assertion (used thread_id instead of process_id) @williballenthin
fix: replace assert with isinstance guard in get_callee for invalid MethodSpec tokens @williballenthin
- fix: replace assert with isinstance guard in get_callee for invalid MethodSpec tokens @williballenthin
- fix: MissingExampleOffset lint now reads scopes.static instead of obsolete scope key @williballenthin (SURF-82)
- fix: invert scope filter in import-to-ida.py so function-scope rules are annotated instead of skipped @williballenthin (SURF-81)
- fix: remove dead string literal in test_detect_duplicate_features @williballenthin (SURF-80)
- fix: remove duplicate Rule.from_yaml call in test_scope_instruction_description @williballenthin (SURF-79)
+2 -1
View File
@@ -237,7 +237,8 @@ class MissingExampleOffset(Lint):
recommendation = "Add offset of example function"
def check_rule(self, ctx: Context, rule: Rule):
if rule.meta.get("scope") in ("function", "basic block"):
static_scope = rule.meta.get("scopes", {}).get("static")
if static_scope in ("function", "basic block"):
examples = rule.meta.get("examples")
if isinstance(examples, list):
for example in examples:
+58
View File
@@ -22,6 +22,8 @@ from pathlib import Path
import pytest
import capa.rules
logger = logging.getLogger(__name__)
CD = Path(__file__).resolve().parent
@@ -230,3 +232,59 @@ def test_detect_duplicate_features(tmpdir):
args = [rule_dir.strpath, rule_path]
overlaps_found = run_program(script_path, args)
assert overlaps_found.returncode == expected_overlaps
def test_missing_example_offset_uses_scopes():
sys.path.insert(0, str(CD / ".." / "scripts"))
import lint as lint_module
lint_instance = lint_module.MissingExampleOffset()
ctx = lint_module.Context(samples={}, rules=capa.rules.RuleSet([]), is_thorough=False)
function_scope_rule_missing_offset = capa.rules.Rule.from_yaml(
textwrap.dedent("""
rule:
meta:
name: test rule function scope no offset
scopes:
static: function
dynamic: process
examples:
- 9324d1a8ae37a36ae560c37448c9705a.exe_
features:
- api: CreateFile
""")
)
assert lint_instance.check_rule(ctx, function_scope_rule_missing_offset) is True
function_scope_rule_with_offset = capa.rules.Rule.from_yaml(
textwrap.dedent("""
rule:
meta:
name: test rule function scope with offset
scopes:
static: function
dynamic: process
examples:
- 9324d1a8ae37a36ae560c37448c9705a.exe_:0x407970
features:
- api: CreateFile
""")
)
assert lint_instance.check_rule(ctx, function_scope_rule_with_offset) is not True
file_scope_rule_no_offset = capa.rules.Rule.from_yaml(
textwrap.dedent("""
rule:
meta:
name: test rule file scope no offset
scopes:
static: file
dynamic: process
examples:
- 9324d1a8ae37a36ae560c37448c9705a.exe_
features:
- api: CreateFile
""")
)
assert lint_instance.check_rule(ctx, file_scope_rule_no_offset) is not True