Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/check_file_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Check testfiles data directory for non-executable permissions.
"""

import sys
import logging
import argparse
import subprocess
from pathlib import Path

logger = logging.getLogger("capa.tests.data")


def main(argv=None):
if argv is None:
argv = sys.argv[1:]

parser = argparse.ArgumentParser()
parser.add_argument("testfiles", type=str, help="Path to tests/data repository root")
args = parser.parse_args(args=argv)

test_failed = check_permissions(Path(args.testfiles))
if test_failed:
return 1
else:
logger.info("test file permissions look good!")
return 0


def check_permissions(testfiles_path: Path) -> bool:
"""
Ensure all files in the testfiles repository are tracked in Git as non-executable (100644).
"""
test_failed = False
try:
output = subprocess.check_output(
["git", "ls-files", "-s"],
cwd=testfiles_path,
text=True,
)
for line in output.splitlines():
if not line:
continue

# Git format: <mode> <hash> <stage>\t<filename>
header, _, filename = line.partition("\t")
mode = header.split(" ", 1)[0]

if mode == "100755":
logger.error("file tracked as executable (100755): %s", filename.strip('"'))
test_failed = True
except (subprocess.SubprocessError, FileNotFoundError) as e:
logger.warning("could not verify git file modes: %s", e)

return test_failed


if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
sys.exit(main())
24 changes: 14 additions & 10 deletions .github/check_runtimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from pathlib import Path

import capa.main
from capa.main import E_FILE_LIMITATION

logger = logging.getLogger("capa.tests.data")

Expand Down Expand Up @@ -49,19 +50,22 @@ def main(argv=None):
continue

time0 = time.time()
capa_ret = capa.main.main(["-q", "-v", "-d", str(file)])
diff = time.time() - time0
try:
capa_ret = capa.main.main(["-q", "-v", "-d", str(file)])
diff = time.time() - time0

if capa_ret:
logger.info("capa failed on file %s", file)
if capa_ret not in (0, E_FILE_LIMITATION):
logger.error("capa failed on file %s with return code %s", file, capa_ret)
test_failed = True
elif diff > THRESHOLD:
logger.error("capa ran for %s seconds on %s, please provide a different sample so we can test more quickly", diff, file)
test_failed = True
else:
logger.info("all good, capa ran for %.2f seconds on %s", diff, file)
except Exception as e:
logger.error("capa encountered an exception on file %s: %s", file, e, exc_info=True)
test_failed = True

if diff > THRESHOLD:
logger.info("capa ran for %s seconds, please provide a different sample so we can test more quickly", diff)
test_failed = True
else:
logger.info("all good, capa ran for %s seconds", diff)

if test_failed:
return 1
else:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ jobs:
python-version: '3.10'
- name: Test repository files
run: python .github/check_sample_filenames.py .
# file permission consistency
test_permissions:
runs-on: ubuntu-latest
steps:
- name: Checkout testfiles repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Python 3.10
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.10'
- name: Test repository file permissions
run: python .github/check_file_permissions.py .
# to allow quicker tests, capa should run less than THRESHOLD seconds on added/modified test files
test_runtime:
runs-on: ubuntu-latest
Expand Down
Empty file modified 055da8e6ccfe5a9380231ea04b850e18.elf_
100755 → 100644
Empty file.
Empty file modified 2055994ff75b4309eee3a49c5749d306.exe_
100755 → 100644
Empty file.
Empty file modified 22d0a2e4c9c2163b2bf5f0e41a2e1762.exe_
100755 → 100644
Empty file.
Empty file modified 276f691a3df25481f59d79781799e35f.exe_
100755 → 100644
Empty file.
Empty file modified 2855ba06b90e7c64d9bce888e47baf6d.exe_
100755 → 100644
Empty file.
Empty file modified 2f9ff544d5cc945b453356f9b20c07d8.exe_
100755 → 100644
Empty file.
Empty file modified 32b3678f8c29437e9ea10eab10194f66.exe_
100755 → 100644
Empty file.
Empty file modified 3446b3889a52d81119d8c482a2a282b9.exe_
100755 → 100644
Empty file.
Empty file modified 35f9cfe5110471a82e330d904c97466a.dll_
100755 → 100644
Empty file.
Empty file modified 368239d36d221d8877a07ab6799e643a.elf_
100755 → 100644
Empty file.
Empty file.
Empty file modified 44461306a604d2cd9883c2bb623af276.dll_
100755 → 100644
Empty file.
Empty file modified 4b9efd882c49ef7525370ffb5197ad86.raw64
100755 → 100644
Empty file.
Empty file modified 4e9c546a54e40d0da89bb4616dd7f8c4.exe_
100755 → 100644
Empty file.
Empty file.
Empty file modified 5b99fa01c72cebc53a76cc72e9581189.dll_
100755 → 100644
Empty file.
Empty file.
Empty file modified 7fd2e2e3c88675d877190abaa3002b55.dll_
100755 → 100644
Empty file.
Empty file modified 91b08896fbda9edb8b6f93a6bc811ec6.dll_
100755 → 100644
Empty file.
Empty file modified 92d8ea10ea30e8b534334a1c9857a455.exe_
100755 → 100644
Empty file.
Empty file modified 9e4d06759f278255073f9ac7b31a115a.dll_
100755 → 100644
Empty file.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ We use the following conventions to organize the capa test data.
- `/dotnet`: .NET test binaries
- `/sigs`: test signatures
- `/source`: source language test files e.g. C# and Python

## File permissions
All files in this repository must be tracked in Git with non-executable permissions (`100644`).
Do not set the executable bit (`+x` / `100755`) on any test files or test scripts.
Empty file modified a1451e3108e85769302ad25c74757180.exe_
100755 → 100644
Empty file.
Empty file modified a563c50c5fa0fd541248acaf72cc4e7d.exe_
100755 → 100644
Empty file.
Empty file.
Empty file.
Empty file modified c3699d0c7bd1276184249a487c1f0d7f.exe_
100755 → 100644
Empty file.
Empty file modified c66172b12971a329f8d5ff01665f204b.exe_
100755 → 100644
Empty file.
Empty file.
Empty file modified dotnet/692f7fd6d198e804d6af98eb9e390d61.exe_
100755 → 100644
Empty file.
Empty file modified e4c33ac3638eef68311f8ac0d72483c7.exe_
100755 → 100644
Empty file.
Empty file.
Empty file.
Empty file modified ffeae4a391a1d5203bd04b4161557227.exe_
100755 → 100644
Empty file.
Loading