Files
trailofbits-buttercup/fuzzer/pyproject.toml
Henrik Brodin 58c52cf6e2 Improve coverage tracking precision (#401)
* Improve coverage tracking precision

Previously coverage tracking included all regions. This changes coverage tracking to be more precise.

Macros that result in code are represented as a single line in the function, and any executed line in the macro will make that line 'covered'. Beyound that, only CodeRegions will count. This will prevent code guarded by #if that aren't in the binary from being considered reachable for example. The idea is that seed-gen would have more accurate information when selecting functions to target.

I've done some testing and it appears as if the new implementation in general reaches more lines and covers more functions.

* Fix macro coverage leaking across files due to missing filename in key

The expansion_coverage map used (line, col) as key without filename,
causing coverage from one file to incorrectly appear in another when
macros were at the same coordinates.

* Recursively expand macros and add named types for coverage data

- Process ExpansionRegion target_regions recursively instead of counting
  only the call site line
- Add coordinate index for O(1) expansion lookups
- Cache computed expansion lines to avoid recomputation across functions
- Use bulk set operations for better performance
- Prevent infinite loops with visited set for circular macro references
- Add named types for coverage data structures:
  - RegionCoords, ExpansionKey, CachedExpansionLines
  - Type aliases: ExpansionMap, CoordToFilenames, ExpansionLinesCache
- Add comprehensive tests for nested macros and edge cases
2025-12-18 08:36:07 +01:00

86 lines
2.2 KiB
TOML

[project]
name = "fuzzing-infra"
version = "0.1.0"
description = "Automated vulnerability discovery and fuzzing infrastructure"
authors = [{ name = "Trail of Bits", email = "opensource@trailofbits.com" }]
license = "AGPL-3.0-only"
requires-python = ">=3.12,<3.13"
dependencies = [
"common[full]",
"redis ~=5.2.1",
"pydantic-settings ~=2.7.1",
"beautifulsoup4 ~=4.13.3",
"lxml ~=5.3.1",
"cxxfilt>=0.3.0",
]
[project.urls]
Repository = "https://github.com/trailofbits/buttercup"
Issues = "https://github.com/trailofbits/buttercup/issues"
[project.scripts]
buttercup-fuzzer-builder = "buttercup.fuzzing_infra.builder_bot:main"
buttercup-fuzzer = "buttercup.fuzzing_infra.fuzzer_bot:main"
buttercup-coverage-bot = "buttercup.fuzzing_infra.coverage_bot:main"
buttercup-tracer-bot = "buttercup.fuzzing_infra.tracer_bot:main"
buttercup-corpus-sync = "buttercup.fuzzing_infra.corpus_sync:main"
buttercup-corpus-merger = "buttercup.fuzzing_infra.corpus_merger:main"
buttercup-fuzzer-utils = "buttercup.fuzzing_infra.utils_cli:main"
[tool.uv.sources]
common = { path = "../common", editable = true }
[tool.hatch.build.targets.wheel]
packages = ["src/buttercup"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[dependency-groups]
dev = [
# Testing tools
"pytest ~=8.3.4",
"pytest-cov ~=6.0.0",
# Linting and type checking
"ruff ~=0.12.8",
"mypy ~=1.17.1",
# Type stubs
"types-redis ~=4.6.0",
"hypothesis>=6.148.7",
]
[tool.ruff]
line-length = 120
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "W", "UP"]
ignore = [
"COM812", "ISC001", # Formatter conflicts
]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "D"] # Allow asserts, no docstrings in tests
[tool.mypy]
plugins = ["pydantic.mypy"]
mypy_path = "src"
packages = "buttercup"
allow_redefinition = true
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
ignore_missing_imports = true
no_implicit_optional = true
show_error_codes = true
sqlite_cache = true
strict_equality = true
warn_no_return = true
warn_redundant_casts = true
warn_return_any = true
warn_unreachable = true
warn_unused_configs = true
warn_unused_ignores = true
exclude = []