Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sample Python auto generation #205

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
48 changes: 47 additions & 1 deletion experiment/builder_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ def _pre_build_check(self, target_path: str,
return False
return True

def build_and_run_python(self, generated_project: str, target_path: str):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid adding language specific methods here? We should ideally make this class language agnostic.

build_result = BuildResult()

self.build_target_local(generated_project,
"/tmp/log.txt",
language='python')

def build_and_run(self, generated_project: str, target_path: str,
iteration: int) -> tuple[BuildResult, Optional[RunResult]]:
"""Builds and runs the fuzz target for fuzzing."""
Expand All @@ -145,6 +152,36 @@ def build_and_run(self, generated_project: str, target_path: str,
generated_project, benchmark_target_name))
return build_result, run_result

def run_target_local_python(self, generated_project: str, target_name: str,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very similar to run_target_local. Is the only difference we're not passing things from self.benchmark ?

We should find some better way to refactor things so there's less duplication here. One simple way I can think of now is to perhaps factor out a general run_oss_fuzz_helper(...) which is called by both run_target_local and python_fuzzgen.

log_path: str):
"""Runs a target in the fixed target directory."""
# If target name is not overridden, use the basename of the target path
# in the Dockerfile.
print(f'Running {target_name}')
command = [
'python3', 'infra/helper.py', 'run_fuzzer', generated_project,
target_name, '--'
] + self._libfuzzer_args()

with open(log_path, 'w') as f:
proc = sp.Popen(command,
stdin=sp.DEVNULL,
stdout=f,
stderr=sp.STDOUT,
cwd=oss_fuzz_checkout.OSS_FUZZ_DIR)

# TODO(ochang): Handle the timeout exception.
try:
proc.wait(timeout=self.run_timeout + 5)
except sp.TimeoutExpired:
print(f'{generated_project} timed out during fuzzing.')
# Try continuing and parsing the logs even in case of timeout.

if proc.returncode != 0:
print(f'********** Failed to run {generated_project}. **********')
else:
print(f'Successfully run {generated_project}.')

def run_target_local(self, generated_project: str, benchmark_target_name: str,
log_path: str):
"""Runs a target in the fixed target directory."""
Expand Down Expand Up @@ -179,7 +216,8 @@ def run_target_local(self, generated_project: str, benchmark_target_name: str,
def build_target_local(self,
generated_project: str,
log_path: str,
sanitizer: str = 'address') -> bool:
sanitizer: str = 'address',
language: str = 'cpp') -> bool:
"""Builds a target with OSS-Fuzz."""
print(f'Building {generated_project} with {sanitizer}')
command = [
Expand All @@ -199,6 +237,14 @@ def build_target_local(self,
print(f'Failed to build image for {generated_project}')
return False

if language == 'python':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What breaks if we let this run through the existing code from line 248 instead? IS there a way to make this work by changing the env vars being set there instead?

command = 'python3 infra/helper.py build_fuzzers %s' % (generated_project)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use fstrings here to be consistent?

try:
sp.check_call(command, shell=True, cwd=oss_fuzz_checkout.OSS_FUZZ_DIR)
except sp.CalledProcessError:
return False
return True

outdir = get_outdir(generated_project)
command = [
'docker',
Expand Down
3 changes: 2 additions & 1 deletion experiment/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ def _parse_libfuzzer_logs(
lines = fuzzlog.split('\n')
except MemoryError as e:
# Some logs from abnormal drivers are too large to be parsed.
logger.log('%s is too large to parse: %s', log_handle.name, e)
if logger:
logger.log('%s is too large to parse: %s', log_handle.name, e)
return 0, 0, False, True, 'LOG_MESS_UP'

cov_pcs = 0
Expand Down
9 changes: 5 additions & 4 deletions experiment/oss_fuzz_checkout.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def _remove_temp_oss_fuzz_repo():
logging.warning('No OSS-Fuzz directory %s', OSS_FUZZ_DIR)


def _set_temp_oss_fuzz_repo():
def _set_temp_oss_fuzz_repo(delete_at_exit: bool):
"""Creates a temporary directory for OSS-Fuzz repo and update |OSS_FUZZ_DIR|.
"""
# Holding the temp directory in a global object to ensure it won't be deleted
Expand All @@ -55,7 +55,8 @@ def _set_temp_oss_fuzz_repo():
GLOBAL_TEMP_DIR = tempfile.mkdtemp()
global OSS_FUZZ_DIR
OSS_FUZZ_DIR = GLOBAL_TEMP_DIR
atexit.register(_remove_temp_oss_fuzz_repo)
if delete_at_exit:
atexit.register(_remove_temp_oss_fuzz_repo)
_clone_oss_fuzz_repo()


Expand All @@ -75,10 +76,10 @@ def _clone_oss_fuzz_repo():
print(stderr)


def clone_oss_fuzz(temp_repo: bool = True):
def clone_oss_fuzz(temp_repo: bool = True, delete_at_exit: bool = True):
"""Clones the OSS-Fuzz repository."""
if temp_repo:
_set_temp_oss_fuzz_repo()
_set_temp_oss_fuzz_repo(delete_at_exit)
if not os.path.exists(OSS_FUZZ_DIR):
_clone_oss_fuzz_repo()
# Remove existing targets.
Expand Down
9 changes: 9 additions & 0 deletions python_fuzzgen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Python auto-gen
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we place this in /languages/python instead?


Logic for auto-generating python fuzzers.

Sample:

```sh
python3 -m python_fuzzgen.build -r https://github.com/html5lib/html5lib-python -l mylog1.txt -m 50
```
Empty file added python_fuzzgen/__init__.py
Empty file.
Loading
Loading