mirror of
https://github.com/trailofbits/buttercup
synced 2026-06-21 14:11:39 +00:00
patcher: ignore build failures when on ARM (#209)
* Fix integration-test run * use the proper oss-fuzz-aixcc commit to run integration-test * determine OSS_FUZZ_CONTAINER_ORG at runtime * use `git diff` in the patcher to create the patch to fix a problem with patches affecting non-newline terminated files * fix parsing * Modify CRS to work on MacOS/ARM * Use LibUCL for testing * use example-libpng * fix linting * patcher: ignore build failures when on ARM On ARM some sanitizers (e.g. memory/undefined) could fail to build. This commit makes the patcher ignore those errors if at least one of the builds succeeds. The patcher just moves forward to testing the PoVs if at least one build passed, and if any of those failed builds is ever required, it will fail in the run_pov stage. * common: fix tests
This commit is contained in:
committed by
GitHub
parent
5cfa9bd26e
commit
27c75660c5
@@ -44,6 +44,7 @@ from buttercup.patcher.agents.tools import (
|
||||
get_callers,
|
||||
)
|
||||
from buttercup.common.llm import create_default_llm_with_temperature, ButtercupLLM
|
||||
from buttercup.common.constants import ARCHITECTURE
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langgraph.prebuilt import create_react_agent
|
||||
from langchain_core.prompts import MessagesPlaceholder
|
||||
@@ -313,6 +314,8 @@ class QEAgent(PatcherAgentBase):
|
||||
}
|
||||
|
||||
# Process completed builds and return immediately on first failure
|
||||
# (unless it is AArch64 architecture, where some sanitizers may fail
|
||||
# to build)
|
||||
for future in concurrent.futures.as_completed(future_to_sanitizer):
|
||||
sanitizer = future_to_sanitizer[future]
|
||||
try:
|
||||
@@ -320,47 +323,54 @@ class QEAgent(PatcherAgentBase):
|
||||
last_patch_attempt.build_stdout = cp_output.output
|
||||
last_patch_attempt.build_stderr = cp_output.error
|
||||
|
||||
if not patch_success or not build_success:
|
||||
if not patch_success:
|
||||
logger.warning(
|
||||
"Failed to apply patch to Challenge Task %s with sanitizer %s",
|
||||
self.challenge.name,
|
||||
sanitizer,
|
||||
)
|
||||
last_patch_attempt.status = PatchStatus.APPLY_FAILED
|
||||
else: # not build_success
|
||||
logger.warning(
|
||||
"Failed to rebuild Challenge Task %s with patch and sanitizer %s",
|
||||
self.challenge.name,
|
||||
sanitizer,
|
||||
)
|
||||
last_patch_attempt.status = PatchStatus.BUILD_FAILED
|
||||
|
||||
# Cancel remaining futures and clean up any built challenges
|
||||
for remaining_future in future_to_sanitizer:
|
||||
remaining_future.cancel()
|
||||
|
||||
# Clean up any successfully built challenge directories since we're failing
|
||||
for built_dir in last_patch_attempt.built_challenges.values():
|
||||
try:
|
||||
ChallengeTask(read_only_task_dir=built_dir, local_task_dir=built_dir).cleanup()
|
||||
except Exception:
|
||||
pass # Ignore cleanup errors
|
||||
|
||||
last_patch_attempt.built_challenges = {}
|
||||
|
||||
return Command(
|
||||
update={
|
||||
"patch_attempts": last_patch_attempt,
|
||||
"execution_info": execution_info,
|
||||
},
|
||||
goto=PatcherAgentName.REFLECTION.value,
|
||||
)
|
||||
else:
|
||||
if patch_success and build_success and built_task_dir:
|
||||
# Store the successfully built challenge directory
|
||||
if built_task_dir:
|
||||
last_patch_attempt.built_challenges[sanitizer] = built_task_dir
|
||||
last_patch_attempt.built_challenges[sanitizer] = built_task_dir
|
||||
continue
|
||||
|
||||
if not patch_success:
|
||||
logger.warning(
|
||||
"Failed to apply patch to Challenge Task %s with sanitizer %s",
|
||||
self.challenge.name,
|
||||
sanitizer,
|
||||
)
|
||||
last_patch_attempt.status = PatchStatus.APPLY_FAILED
|
||||
elif not build_success:
|
||||
if ARCHITECTURE == "aarch64":
|
||||
logger.warning(
|
||||
"Failed to rebuild Challenge Task %s with patch and sanitizer %s, but this may happen on AArch64, just move on.",
|
||||
self.challenge.name,
|
||||
sanitizer,
|
||||
)
|
||||
continue
|
||||
|
||||
logger.warning(
|
||||
"Failed to rebuild Challenge Task %s with patch and sanitizer %s",
|
||||
self.challenge.name,
|
||||
sanitizer,
|
||||
)
|
||||
last_patch_attempt.status = PatchStatus.BUILD_FAILED
|
||||
|
||||
# Cancel remaining futures and clean up any built challenges
|
||||
for remaining_future in future_to_sanitizer:
|
||||
remaining_future.cancel()
|
||||
|
||||
# Clean up any successfully built challenge directories since we're failing
|
||||
for built_dir in last_patch_attempt.built_challenges.values():
|
||||
try:
|
||||
ChallengeTask(read_only_task_dir=built_dir, local_task_dir=built_dir).cleanup()
|
||||
except Exception:
|
||||
pass # Ignore cleanup errors
|
||||
|
||||
last_patch_attempt.built_challenges = {}
|
||||
|
||||
return Command(
|
||||
update={
|
||||
"patch_attempts": last_patch_attempt,
|
||||
"execution_info": execution_info,
|
||||
},
|
||||
goto=PatcherAgentName.REFLECTION.value,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.error("Build with sanitizer %s generated an exception: %s", sanitizer, exc)
|
||||
last_patch_attempt.status = PatchStatus.BUILD_FAILED
|
||||
@@ -387,6 +397,17 @@ class QEAgent(PatcherAgentBase):
|
||||
goto=PatcherAgentName.REFLECTION.value,
|
||||
)
|
||||
|
||||
if not last_patch_attempt.built_challenges:
|
||||
logger.error("Failed to build Challenge Task %s with any sanitizer", self.challenge.name)
|
||||
last_patch_attempt.status = PatchStatus.BUILD_FAILED
|
||||
return Command(
|
||||
update={
|
||||
"patch_attempts": last_patch_attempt,
|
||||
"execution_info": execution_info,
|
||||
},
|
||||
goto=PatcherAgentName.REFLECTION.value,
|
||||
)
|
||||
|
||||
logger.info("Challenge Task %s rebuilt with patch", self.challenge.name)
|
||||
last_patch_attempt.build_succeeded = True
|
||||
return Command(
|
||||
|
||||
Reference in New Issue
Block a user