-
Notifications
You must be signed in to change notification settings - Fork 587
Refactor reproduce #4988
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
base: master
Are you sure you want to change the base?
Refactor reproduce #4988
Changes from 11 commits
c66e532
6743445
7601d47
3810e85
7f78664
0724c3d
9a253af
bf40023
0cd6c83
6a26ab0
d6ea7a9
dc06e76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,7 @@ | |
_DATA_BUNDLE_SYNC_INTERVAL_IN_SECONDS = 6 * 60 * 60 | ||
_SYNC_FILENAME = '.sync' | ||
_TESTCASE_ARCHIVE_EXTENSION = '.zip' | ||
_EXECUTABLE_PERMISSIONS = 0o750 | ||
|
||
|
||
def _set_timeout_value_from_user_upload(testcase_id, uworker_env): | ||
|
@@ -352,10 +353,12 @@ def _get_testcase_key_and_archive_status(testcase): | |
|
||
|
||
def _is_testcase_minimized(testcase): | ||
"""Returns True if the testcase is minimized.""" | ||
return testcase.minimized_keys and testcase.minimized_keys != 'NA' | ||
|
||
|
||
def download_testcase(testcase_download_url, dst): | ||
"""Downloads a testcase from a signed url""" | ||
return storage.download_signed_url_to_file(testcase_download_url, dst) | ||
|
||
|
||
|
@@ -651,7 +654,7 @@ def _update_fuzzer( | |
return False | ||
|
||
# Make fuzzer executable. | ||
os.chmod(fuzzer_path, 0o750) | ||
os.chmod(fuzzer_path, _EXECUTABLE_PERMISSIONS) | ||
|
||
# Cleanup unneeded archive. | ||
shell.remove_file(archive_path) | ||
|
@@ -799,8 +802,10 @@ def get_fuzzer_directory(fuzzer_name): | |
return fuzzer_directory | ||
|
||
|
||
def archive_testcase_and_dependencies_in_gcs(resource_list, testcase_path: str, | ||
upload_url: str): | ||
def archive_testcase_and_dependencies_in_gcs( | ||
resource_list, | ||
testcase_path: str, # pylint: disable=line-too-long | ||
|
||
upload_url: str): | ||
"""Archive testcase and its dependencies, and store in blobstore. Returns | ||
whether it is archived, the absolute_filename, and the zip_filename.""" | ||
if not os.path.exists(testcase_path): | ||
|
@@ -890,3 +895,119 @@ def archive_testcase_and_dependencies_in_gcs(resource_list, testcase_path: str, | |
shell.remove_file(zip_path) | ||
|
||
return archived, absolute_filename, zip_filename | ||
|
||
|
||
def setup_local_testcase(testcase: data_types.Testcase) -> str | None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a Also, I noticed that in this function, it sets the |
||
"""Sets up the testcase file locally. | ||
|
||
Args: | ||
testcase: The Testcase object. | ||
|
||
Returns: | ||
- str | None : The local file path to the testcase, or None on failure. | ||
""" | ||
try: | ||
shell.clear_testcase_directories() | ||
except Exception as e: | ||
logs.error(f'Error clearing testcase directories: {e}') | ||
return None | ||
|
||
try: | ||
_, testcase_file_path = _get_testcase_file_and_path(testcase) | ||
if testcase.minimized_keys and testcase.minimized_keys != 'NA': | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use the |
||
blob_key = testcase.minimized_keys | ||
else: | ||
blob_key = testcase.fuzzed_keys | ||
if not blobs.read_blob_to_disk(blob_key, testcase_file_path): | ||
logs.error(f'Failed to download testcase from blobstore: {blob_key}') | ||
# Returning None for path when download fails | ||
return None | ||
prepare_environment_for_testcase(testcase) | ||
except Exception as e: | ||
logs.error(f'Error setting up testcase locally: {e}') | ||
return None | ||
|
||
return testcase_file_path | ||
|
||
|
||
def setup_local_fuzzer(fuzzer_name: str) -> bool: | ||
"""Sets up the fuzzer binaries and environment. | ||
|
||
Args: | ||
fuzzer_name: The name of the fuzzer to set up. | ||
|
||
Returns: | ||
True if setup was successful, False otherwise. | ||
""" | ||
fuzzer = data_types.Fuzzer.query(data_types.Fuzzer.name == fuzzer_name).get() | ||
if not fuzzer: | ||
logs.error(f'Fuzzer {fuzzer_name} not found.') | ||
return False | ||
|
||
if fuzzer.untrusted_content: | ||
logs.warning('You are about to run an untrusted fuzzer locally. ' | ||
'This can be dangerous.') | ||
|
||
environment.set_value('UNTRUSTED_CONTENT', fuzzer.untrusted_content) | ||
|
||
if fuzzer.data_bundle_name: | ||
logs.info( | ||
f'Fuzzer {fuzzer_name} uses data bundle: {fuzzer.data_bundle_name}') | ||
|
||
if fuzzer.launcher_script: | ||
logs.error('Fuzzers with launch script not supported yet.') | ||
return False | ||
|
||
if fuzzer.builtin: | ||
logs.info(f'Fuzzer {fuzzer_name} is builtin, no setup required.') | ||
return True | ||
|
||
fuzzer_directory: str = get_fuzzer_directory(fuzzer.name) | ||
|
||
try: | ||
if not shell.remove_directory(fuzzer_directory, recreate=True): | ||
logs.error(f'Failed to clear fuzzer directory: {fuzzer_directory}') | ||
return False | ||
except Exception as e: | ||
logs.error(f'Error clearing fuzzer directory {fuzzer_directory}: {e}') | ||
return False | ||
|
||
archive_path = os.path.join(fuzzer_directory, fuzzer.filename) | ||
if not blobs.read_blob_to_disk(fuzzer.blobstore_key, archive_path): | ||
logs.error('Failed to download fuzzer archive from blobstore: ' | ||
f'{fuzzer.blobstore_key}') | ||
return False | ||
|
||
try: | ||
with archive.open(archive_path) as reader: | ||
reader.extract_all(fuzzer_directory) | ||
except archive.ArchiveError as e: | ||
logs.error(f'Failed to unpack fuzzer archive {fuzzer.filename}: {e}') | ||
return False | ||
except Exception as e: | ||
logs.error( | ||
f'Unexpected error unpacking fuzzer archive {fuzzer.filename}: {e}') | ||
return False | ||
finally: | ||
if os.path.exists(archive_path): | ||
try: | ||
shell.remove_file(archive_path) | ||
except Exception as e: | ||
logs.warning( | ||
f'Failed to remove temporary archive file {archive_path}: {e}') | ||
|
||
fuzzer_path = os.path.join(fuzzer_directory, fuzzer.executable_path) | ||
if not os.path.exists(fuzzer_path): | ||
logs.error( | ||
f'Fuzzer executable {fuzzer.executable_path} not found in archive. ' | ||
'Check fuzzer configuration.') | ||
return False | ||
|
||
try: | ||
os.chmod(fuzzer_path, _EXECUTABLE_PERMISSIONS) | ||
except OSError as e: | ||
logs.error( | ||
f'Failed to set permissions on fuzzer executable {fuzzer_path}: {e}') | ||
return False | ||
|
||
return True |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1001,6 +1001,12 @@ def set_bot_environment(): | |
return True | ||
|
||
|
||
def set_local_log_only(): | ||
"""Force logs to be local-only.""" | ||
set_value('LOG_TO_GCP', '') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, add a short comment explaining that we set this to an empty string because currently the logs module does not correctly evaluate env vars (i.e., 'false' is evaluated to true). |
||
set_value('LOG_TO_CONSOLE', 'True') | ||
|
||
|
||
def set_tsan_max_history_size(): | ||
"""Sets maximum history size for TSAN tool.""" | ||
tsan_options = get_value('TSAN_OPTIONS') | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice