fix: close file handle in get_file_taste using a with statement

`get_file_taste` opened a file handle with `sample_path.open("rb").read(8)`,
discarding the file object without explicitly closing it. CPython reference-
counting closes it promptly in practice, but other implementations (PyPy,
Jython) and CPython under GC pressure may defer closure. Use a `with` statement
to guarantee the handle is released immediately after reading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Willi Ballenthin
2026-04-22 17:38:45 +03:00
co-authored by Claude Sonnet 4.6
parent cb3376d9e2
commit 243e6408b0
3 changed files with 24 additions and 3 deletions
+1
View File
@@ -11,6 +11,7 @@
-
### Bug Fixes
- fix: close file handle in get_file_taste using a with statement @williballenthin
- fix: correct off-by-one in dynamic analysis call_count debug log (enumerate -> explicit counter) @williballenthin
- fix: correct capa/subscope-rule key in RuleMetadata so is_subscope_rule is no longer always False @williballenthin
- fix: remove unreachable backports.functools_lru_cache fallback and dead dependency @williballenthin
+2 -2
View File
@@ -88,8 +88,8 @@ def hex(n: int) -> str:
def get_file_taste(sample_path: Path) -> bytes:
if not sample_path.exists():
raise IOError(f"sample path {sample_path} does not exist or cannot be accessed")
taste = sample_path.open("rb").read(8)
return taste
with sample_path.open("rb") as f:
return f.read(8)
def is_runtime_ida():
+21 -1
View File
@@ -14,10 +14,13 @@
import codecs
import tempfile
from pathlib import Path
import pytest
import capa.helpers
from capa.helpers import get_format_from_extension
from capa.helpers import get_file_taste, get_format_from_extension
from capa.features.common import (
FORMAT_ELF,
FORMAT_SC32,
@@ -101,3 +104,20 @@ def test_get_format_from_extension():
assert get_format_from_extension(Path("sample.BinExport2")) == FORMAT_BINEXPORT2
assert get_format_from_extension(Path("sample.bndb")) == FORMAT_BINJA_DB
assert get_format_from_extension(Path("sample.exe")) == FORMAT_UNKNOWN
def test_get_file_taste_reads_first_bytes():
with tempfile.NamedTemporaryFile(delete=False) as tmp:
tmp.write(b"\x4d\x5a\x90\x00\x01\x02\x03\x04\xff\xfe")
tmp_path = Path(tmp.name)
try:
taste = get_file_taste(tmp_path)
assert taste == b"\x4d\x5a\x90\x00\x01\x02\x03\x04"
assert len(taste) == 8
finally:
tmp_path.unlink()
def test_get_file_taste_missing_file_raises():
with pytest.raises(IOError):
get_file_taste(Path("/nonexistent/path/sample.exe"))