mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-15 03:18:07 +00:00
libfuzzer-dotnet integration (#535)
This commit is contained in:
@ -31,7 +31,7 @@ from onefuzz.backend import ContainerWrapper, wait
|
||||
from onefuzz.cli import execute_api
|
||||
from onefuzztypes.enums import OS, ContainerType, TaskState, VmState
|
||||
from onefuzztypes.models import Job, Pool, Repro, Scaleset
|
||||
from onefuzztypes.primitives import Directory, File
|
||||
from onefuzztypes.primitives import Container, Directory, File, PoolName, Region
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
LINUX_POOL = "linux-test"
|
||||
@ -41,6 +41,7 @@ BUILD = "0"
|
||||
|
||||
class TemplateType(Enum):
|
||||
libfuzzer = "libfuzzer"
|
||||
libfuzzer_dotnet = "libfuzzer_dotnet"
|
||||
afl = "afl"
|
||||
radamsa = "radamsa"
|
||||
|
||||
@ -51,6 +52,7 @@ class Integration(BaseModel):
|
||||
target_exe: str
|
||||
inputs: Optional[str]
|
||||
use_setup: bool = Field(default=False)
|
||||
nested_setup_dir: Optional[str]
|
||||
wait_for_files: List[ContainerType]
|
||||
check_asan_log: Optional[bool] = Field(default=False)
|
||||
disable_check_debugger: Optional[bool] = Field(default=False)
|
||||
@ -73,6 +75,15 @@ TARGETS: Dict[str, Integration] = {
|
||||
wait_for_files=[ContainerType.unique_reports, ContainerType.coverage],
|
||||
reboot_after_setup=True,
|
||||
),
|
||||
"linux-libfuzzer-dotnet": Integration(
|
||||
template=TemplateType.libfuzzer_dotnet,
|
||||
os=OS.linux,
|
||||
target_exe="wrapper",
|
||||
nested_setup_dir="my-fuzzer",
|
||||
inputs="inputs",
|
||||
use_setup=True,
|
||||
wait_for_files=[ContainerType.inputs, ContainerType.crashes],
|
||||
),
|
||||
"linux-libfuzzer-rust": Integration(
|
||||
template=TemplateType.libfuzzer,
|
||||
os=OS.linux,
|
||||
@ -159,7 +170,7 @@ class TestOnefuzz:
|
||||
def setup(
|
||||
self,
|
||||
*,
|
||||
region: Optional[str] = None,
|
||||
region: Optional[Region] = None,
|
||||
user_pools: Optional[Dict[str, str]] = None,
|
||||
) -> None:
|
||||
for entry in self.os:
|
||||
@ -169,7 +180,7 @@ class TestOnefuzz:
|
||||
)
|
||||
self.pools[entry] = self.of.pools.get(user_pools[entry.name])
|
||||
else:
|
||||
name = "pool-%s-%s" % (self.project, entry.name)
|
||||
name = PoolName("pool-%s-%s" % (self.project, entry.name))
|
||||
self.logger.info("creating pool: %s:%s", entry.name, name)
|
||||
self.pools[entry] = self.of.pools.create(name, entry)
|
||||
self.logger.info("creating scaleset for pool: %s", name)
|
||||
@ -195,6 +206,9 @@ class TestOnefuzz:
|
||||
else None
|
||||
)
|
||||
|
||||
if setup and config.nested_setup_dir:
|
||||
setup = Directory(os.path.join(setup, config.nested_setup_dir))
|
||||
|
||||
job: Optional[Job] = None
|
||||
if config.template == TemplateType.libfuzzer:
|
||||
job = self.of.template.libfuzzer.basic(
|
||||
@ -207,7 +221,21 @@ class TestOnefuzz:
|
||||
setup_dir=setup,
|
||||
duration=1,
|
||||
vm_count=1,
|
||||
reboot_after_setup=config.reboot_after_setup,
|
||||
reboot_after_setup=config.reboot_after_setup or False,
|
||||
)
|
||||
elif config.template == TemplateType.libfuzzer_dotnet:
|
||||
if setup is None:
|
||||
raise Exception("setup required for libfuzzer_dotnet")
|
||||
job = self.of.template.libfuzzer.dotnet(
|
||||
self.project,
|
||||
target,
|
||||
BUILD,
|
||||
self.pools[config.os].name,
|
||||
target_harness=config.target_exe,
|
||||
inputs=inputs,
|
||||
setup_dir=setup,
|
||||
duration=1,
|
||||
vm_count=1,
|
||||
)
|
||||
elif config.template == TemplateType.radamsa:
|
||||
job = self.of.template.radamsa.basic(
|
||||
@ -362,7 +390,7 @@ class TestOnefuzz:
|
||||
self.logger.info("checking jobs")
|
||||
return wait(self.check_jobs_impl)
|
||||
|
||||
def get_job_crash(self, job_id: UUID) -> Optional[Tuple[str, str]]:
|
||||
def get_job_crash(self, job_id: UUID) -> Optional[Tuple[Container, str]]:
|
||||
# get the crash container for a given job
|
||||
|
||||
for task in self.of.tasks.list(job_id=job_id, state=None):
|
||||
@ -396,6 +424,7 @@ class TestOnefuzz:
|
||||
self.logger.info("launching repro: %s", self.target_jobs[job_id])
|
||||
report = self.get_job_crash(job_id)
|
||||
if report is None:
|
||||
self.logger.warning("target does not include crash reports: %s", self.target_jobs[job_id])
|
||||
return
|
||||
(container, path) = report
|
||||
self.repros[job_id] = self.of.repro.create(container, path, duration=1)
|
||||
@ -555,7 +584,7 @@ class Run(Command):
|
||||
endpoint: Optional[str] = None,
|
||||
user_pools: Optional[Dict[str, str]] = None,
|
||||
pool_size: int = 10,
|
||||
region: Optional[str] = None,
|
||||
region: Optional[Region] = None,
|
||||
os_list: List[OS] = [OS.linux, OS.windows],
|
||||
targets: List[str] = list(TARGETS.keys()),
|
||||
skip_repro: bool = False,
|
||||
@ -580,6 +609,7 @@ class Run(Command):
|
||||
if skip_repro:
|
||||
self.logger.warning("not testing crash repro")
|
||||
else:
|
||||
self.logger.info("launching crash repro tests")
|
||||
tester.launch_repro()
|
||||
tester.check_repro()
|
||||
except Exception as e:
|
||||
|
Reference in New Issue
Block a user