diff --git a/agent/prototyper.py b/agent/prototyper.py index 2048db6fa6..4468ad6b2c 100644 --- a/agent/prototyper.py +++ b/agent/prototyper.py @@ -6,8 +6,11 @@ import logger from agent.base_agent import BaseAgent +from data_prep.project_context.context_introspector import ContextRetriever from experiment.benchmark import Benchmark -from llm_toolkit.prompt_builder import DefaultTemplateBuilder +from llm_toolkit.prompt_builder import EXAMPLES as EXAMPLE_FUZZ_TARGETS +from llm_toolkit.prompt_builder import (DefaultTemplateBuilder, + PrototyperTemplateBuilder) from llm_toolkit.prompts import Prompt from results import BuildResult, Result from tool.container_tool import ProjectContainerTool @@ -21,10 +24,18 @@ class Prototyper(BaseAgent): def _initial_prompt(self, results: list[Result]) -> Prompt: """Constructs initial prompt of the agent.""" benchmark = results[-1].benchmark - - default_prompt_builder = DefaultTemplateBuilder(model=self.llm, - benchmark=benchmark) - prompt = default_prompt_builder.build([]) + retriever = ContextRetriever(benchmark) + context_info = retriever.get_context_info() + prompt_builder = PrototyperTemplateBuilder( + model=self.llm, + benchmark=benchmark, + ) + prompt = prompt_builder.build(example_pair=[], + project_context_content=context_info, + tool_guides=self.inspect_tool.tutorial()) + # prompt = prompt_builder.build(example_pair=EXAMPLE_FUZZ_TARGETS.get( + # benchmark.language, []), + # tool_guides=self.inspect_tool.tutorial()) return prompt def _update_fuzz_target_and_build_script(self, cur_round: int, response: str, @@ -163,13 +174,31 @@ def _container_handle_conclusion( compile_log = self.llm.truncate_prompt(build_result.compile_log) logger.info('***** Failed to recompile in %02d rounds *****', cur_round) prompt_text = ( - 'Failed to build fuzz target. Here is the fuzz target, build' - ' script, compliation command, and other compilation runtime' - ' output.\n\n' - f'{build_result.fuzz_target_source}\n\n' - f'\n{build_result.build_script_source}\n' - f'\n\n{compile_log}\n' - '\n') + 'Failed to build fuzz target. Here is the fuzz target, build script, ' + 'compliation command, and other compilation runtime output. Analyze ' + 'the error messages, the fuzz target, and the build script carefully ' + 'to identify the root cause. Avoid making random changes to the fuzz ' + 'target or build script without a clear understanding of the error. ' + 'If necessary, #include necessary headers and #define required macros' + 'or constants in the fuzz target, or adjust compiler flags to link ' + 'required libraries in the build script. After collecting information' + ', analyzing and understanding the error root cause, YOU MUST take at' + ' least one step to validate your theory with source code evidence. ' + 'Only if your theory is verified, respond the revised fuzz target and' + 'build script in FULL.\n' + 'Always try to learn from the source code about how to fix errors, ' + 'for example, search for the key words (e.g., function name, type ' + 'name, constant name) in the source code to learn how they are used. ' + 'Similarly, learn from the other fuzz targets and the build script to' + 'understand how to include the correct headers.\n' + 'Focus on writing a minimum buildable fuzz target that calls the ' + 'target function. We can increase its complexity later, but first try' + 'to make it compile successfully.' + 'If an error happens repeatedly and cannot be fixed, try to ' + 'mitigate it. For example, replace or remove the line.' + f'\n{build_result.fuzz_target_source}\n\n' + f'\n{build_result.build_script_source}\n' + f'\n\n{compile_log}\n\n') elif not build_result.is_function_referenced: logger.info( '***** Fuzz target does not reference function-under-test in %02d ' @@ -199,17 +228,16 @@ def execute(self, result_history: list[Result]) -> BuildResult: """Executes the agent based on previous result.""" logger.info('Executing Prototyper') last_result = result_history[-1] - prompt = self._initial_prompt(result_history) benchmark = last_result.benchmark self.inspect_tool = ProjectContainerTool(benchmark, name='inspect') self.inspect_tool.compile(extra_commands=' && rm -rf /out/* > /dev/null') cur_round = 1 - prompt.append(self.inspect_tool.tutorial()) build_result = BuildResult(benchmark=benchmark, trial=last_result.trial, work_dirs=last_result.work_dirs, author=self, chat_history={self.name: ''}) + prompt = self._initial_prompt(result_history) try: client = self.llm.get_chat_client(model=self.llm.get_model()) while prompt and cur_round < MAX_ROUND: diff --git a/llm_toolkit/models.py b/llm_toolkit/models.py index 7f264ae62c..990dedb764 100644 --- a/llm_toolkit/models.py +++ b/llm_toolkit/models.py @@ -654,16 +654,11 @@ def _do_generate(self, client: ChatSession, prompt: str, config: dict[str, Any]) -> Any: """Generates chat response.""" logger.info('%s generating response with config: %s', self.name, config) - try: - return client.send_message( - prompt, - stream=False, - generation_config=config, - safety_settings=self.safety_config).text # type: ignore - except Exception as e: - logger.error('%s failed to generated response: %s; Config: %s', e, - self.name, config) - return '' + return client.send_message( + prompt, + stream=False, + generation_config=config, + safety_settings=self.safety_config).text # type: ignore def truncate_prompt(self, raw_prompt_text: Any, diff --git a/llm_toolkit/prompt_builder.py b/llm_toolkit/prompt_builder.py index 0c39f4563b..07b4fb2bbe 100644 --- a/llm_toolkit/prompt_builder.py +++ b/llm_toolkit/prompt_builder.py @@ -32,6 +32,7 @@ logger = logging.getLogger(__name__) DEFAULT_TEMPLATE_DIR: str = 'prompts/template_xml/' +AGENT_TEMPLATE_DIR: str = 'prompts/agent/' # TODO(Dongge): Refactor this tot avoid hard-coding. # Example files. @@ -141,13 +142,13 @@ def __init__(self, self.triager_problem_template_file = self._find_template( template_dir, 'triager_problem.txt') - def _format_priming(self, target_file_type: FileType, - needs_extern: bool) -> str: + def _format_priming(self, benchmark: Benchmark) -> str: """Formats a priming based on the prompt template.""" priming = self._get_template(self.priming_template_file) - priming = priming.replace('{LANGUAGE}', target_file_type.value) + priming = priming.replace('{LANGUAGE}', benchmark.file_type.value) + priming = priming.replace('{FUZZ_TARGET_PATH}', benchmark.target_path) # TODO(Dongge): Add project name and fuzz target file path. - if needs_extern: + if benchmark.needs_extern: priming += ( 'IMPORTANT: The fuzz target is written in C++, whereas the ' 'project-under-test is written in C. All headers, functions, and code' @@ -155,7 +156,7 @@ def _format_priming(self, target_file_type: FileType, 'extern "C" to ensure error-free compilation and linkage' 'between C and C++:\n\nextern "C" {\n //Include necessary C ' 'headers, source files, functions, and code here.\n}\n\n') - if target_file_type == FileType.CPP: + if benchmark.file_type == FileType.CPP: type_specific_priming = self._get_template(self.cpp_priming_filler_file) else: type_specific_priming = '' @@ -287,8 +288,7 @@ def build(self, """Constructs a prompt using the templates in |self| and saves it.""" if not self.benchmark: return self._prompt - priming = self._format_priming(self.benchmark.file_type, - self.benchmark.needs_extern) + priming = self._format_priming(self.benchmark) final_problem = self.format_problem(self.benchmark.function_signature) final_problem += (f'You MUST call \n' f'{self.benchmark.function_signature}\n' @@ -537,6 +537,51 @@ def _slice_func_code(self, project: str, func_name: str, return '' +class PrototyperTemplateBuilder(DefaultTemplateBuilder): + """Builder specifically targeted C (and excluding C++).""" + + def __init__(self, + model: models.LLM, + benchmark: Benchmark, + template_dir: str = DEFAULT_TEMPLATE_DIR): + super().__init__(model) + self._template_dir = template_dir + self.agent_templare_dir = AGENT_TEMPLATE_DIR + self.benchmark = benchmark + + # Load templates. + self.priming_template_file = self._find_template(self.agent_templare_dir, + 'prototyper-priming.txt') + self.cpp_priming_filler_file = self._find_template( + template_dir, 'cpp-specific-priming-filler.txt') + self.problem_template_file = self._find_template(template_dir, + 'problem.txt') + self.solution_template_file = self._find_template(template_dir, + 'solution.txt') + self.context_template_file = self._find_template(template_dir, + 'context.txt') + + def build(self, + example_pair: list[list[str]], + project_example_content: Optional[list[list[str]]] = None, + project_context_content: Optional[dict] = None, + tool_guides: str = '') -> prompts.Prompt: + """Constructs a prompt using the templates in |self| and saves it.""" + if not self.benchmark: + return self._prompt + priming = self._format_priming(self.benchmark) + final_problem = self.format_problem(self.benchmark.function_signature) + final_problem += (f'You MUST call \n' + f'{self.benchmark.function_signature}\n' + f' in your solution!\n') + if project_context_content: + final_problem += self.format_context(project_context_content) + self._prepare_prompt(priming, final_problem, example_pair, + project_example_content) + self._prompt.append(tool_guides) + return self._prompt + + class DefaultJvmTemplateBuilder(PromptBuilder): """Default builder for JVM projects.""" diff --git a/prompts/agent/prototyper-priming.txt b/prompts/agent/prototyper-priming.txt new file mode 100644 index 0000000000..7b51cd8e67 --- /dev/null +++ b/prompts/agent/prototyper-priming.txt @@ -0,0 +1,143 @@ + +As a security testing engineer, you must write an `int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)` fuzz target in {LANGUAGE}. +Objective: Your goal is to modify an existing fuzz target `{FUZZ_TARGET_PATH}` to write a minimum fuzz target of a given function-under-test that can build successfully. + + + +Follow these steps to write a minimum fuzz target: + +Step 1. Determine the information you need to write an effective fuzz target. +This includes: + * **Source code** of the function under test. + * **Custom Types and Dependencies** definitions and implementations. + * **Initialization and setup** requirements and steps. + * **Build details** and integration steps. + * Valid and edge-case input values. + * Environmental and runtime dependencies. + +Step 2. Collect information using the Bash tool. +Use the bash tool (see section) and follow its rules to gather the necessary information. You can collect information from: + * The existing human written fuzz target at `{FUZZ_TARGET_PATH}`. + * The existing human written build script `/src/build.sh`. + * The project source code (in `.`, or `/src//`) clone from the project repository. + * Documentation about the project, the function, and the variables/constants involved. + * Environment variables. + * Knowledge about OSS-Fuzz's build infrastructure: It will compile your fuzz target in the same way as the exiting human written fuzz target with the build script. + +Step 3. Analyze the function and its parameters. +Understand the function under test by analyzing its source code and documentation: + * **Purpose and functionality** of the function. + * **Input processing** and internal logic. + * **Dependencies** on other functions or global variables. + * **Error handling** and edge cases. + +Step 4. Understand initialization requirements. +Identify what is needed to properly initialize the function: + * **Header files** and their relative paths used by include statements in the fuzz target. + * **Complex input parameters or objects** initialization. + * **Constructor functions** or initialization routines. + * **Global state** or configuration needs to be set up. + * **Mocking** external dependencies if necessary. + +Step 5. Understand Constraints and edge cases. +For each input parameter, understand: + * Valid ranges and data types. + * Invalid or edge-case values (e.g., zero, NULL, predefined constants, maximum values). + * Special values that trigger different code paths. + +Step 6: Plan Fuzz Target Implementation. +Decide how to implement the fuzz target: + * **Extract parameters** from the `data` and `size` variable of `LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)`. + * Handle fixed-size versus variable-size data. + * **Initialize function's parameters** by appropriately mapping the raw input bytes. + * Ensure that the fuzz target remains deterministic and avoids side effects. + * Avoid `goto` statements. + +Step 7: **Write** the fuzz target code. +Implement the `LLVMFuzzerTestOneInput` function: + * Header files: + * Investigate how existing fuzz targets include headers. + * Investigate where they are located in the project + * Collect all headers required by your fuzz target and their locations. + * Include their relative path in the same way as the existing fuzz targets. + * Macros or Constants: + * Include or define necessary macros or constants. + * Input Handling: + * Use `FuzzedDataProvider` if and only if the fuzz target at `{FUZZ_TARGET_PATH}` is a C++ file. + * Use `extern "C"` if and only if the fuzz target at `{FUZZ_TARGET_PATH}` is a C++ file. + * Check that the input size is sufficient. + * Extract parameters from the input data. + * Handle any necessary conversions or validations. + * Function Invocation: + * Initialize required objects or state. + * Modify the existing fuzz target at `{FUZZ_TARGET_PATH}` to fuzz the function under test with the fuzzed parameters. + * Ensure proper error handling. + * + * Cleanup: + * Free any allocated resources. + * Reset any global state if necessary. + +Step 8 (Optional): **Modify** the Build Script. +Write a new build script only if the existing one (`/src/build.sh`) is insufficient: + * Decide if you need to modify the build script at `/src/build.sh` to successfully build the new fuzz target. + * Include compilation steps for the project under test. + * Include compilation steps for the new fuzz target. + * Specify necessary compiler and linker flags. + * Ensure all dependencies are correctly linked. + +Step 9: Providing Your Conclusion: + * Provide your conclusion on the FULL new fuzz target and build script **ONLY AFTER** you have gathered all necessary information. + * **DO NOT SEND** any other content (e.g., bash tool commands) in the conclusion message. ALWAYS send other commands individually and ONLY SEND conclusion after collecting all information. + * Conclusion Format: + * Overall Description: + * Summarize your findings and describe your fuzz target design. + * Wrap this summary within and tags. + * Modified Fuzz Target: + * Provide the full code of the modified fuzz target. + * Wrap the code within and tags. + * Modified Build Script (if applicable): + * If you need to modify the build script, provide the full code. + * Wrap it within and tags. + * Format Example: + + I determined that the fuzz target needs to include specific header files and adjust the `LLVMFuzzerTestOneInput` function to call the new function-under-test. Additionally, the build script requires modification to link against the necessary libraries. + + + [Your FULL fuzz target code here.] + + + [Your FULL build script code here, if applicable.] + + + + +{TYPE_SPECIFIC_PRIMING} + + +3. Methodical Approach: + * Be systematic to cover all necessary aspects, such as: + * Understanding the function's parameters and dependencies. + * Identifying required header files and libraries. + * Recognizing any special initialization or environmental requirements. +1. Utilizing Existing Examples: + * Use the existing fuzz target at `{FUZZ_TARGET_PATH}` and other fuzz targets with `LLVMFuzzerTestOneInput` in its parent directory as references. + * Pay special attention to: + * How header files are included. + * The structure and content of the `LLVMFuzzerTestOneInput` function. + * Typically, you only need to modify the content of `LLVMFuzzerTestOneInput`. +2. Investigating Header Inclusions: + * Use bash tool to find required headers and libraries. + * Examine library files built by `/src/build.sh` to understand available functions and symbols. +3. Modifying the Build Script (if necessary): + * Modifying `/src/build.sh` to build the necessary components or include required libraries if function-under-test is not included. + * The project's directory may contain a `README.md` with build instructions (e.g., at `/src//README.md` +4. Do Not Compile: + * **Do not compile** the fuzz target during your investigation. + * Provide your conclusions based on the information gathered after you have a solution. +5. Formatting Code Snippets: + * Do not wrap code snippets with triple backticks (```). + * Use the specified XML-style tags for wrapping code and other content. +6. DO NOT send the early: Provide conclusions **only after** gathering all necessary information. +7. Focus on Final Goals: + * Ensure that your fuzz target and build script aim to successfully build the fuzz target and fuzz the function-under-test. + diff --git a/prompts/example/dns_message_parse.c b/prompts/example/dns_message_parse.c index 0a7692731f..ae6a37dc24 100644 --- a/prompts/example/dns_message_parse.c +++ b/prompts/example/dns_message_parse.c @@ -34,141 +34,152 @@ static uint8_t *output = NULL; static size_t output_len = 1024; static uint8_t render_buf[64 * 1024 - 1]; -int LLVMFuzzerInitialize(int *argc ISC_ATTR_UNUSED, char ***argv ISC_ATTR_UNUSED) { - isc_mem_create(&mctx); - output = isc_mem_get(mctx, output_len); +int +LLVMFuzzerInitialize(int *argc ISC_ATTR_UNUSED, char ***argv ISC_ATTR_UNUSED) { + isc_mem_create(&mctx); + output = isc_mem_get(mctx, output_len); - return (0); + return (0); } -static isc_result_t parse_message(isc_buffer_t *input, dns_message_t **messagep) { - isc_result_t result; - dns_message_t *message = NULL; +static isc_result_t +parse_message(isc_buffer_t *input, dns_message_t **messagep) { + isc_result_t result; + dns_message_t *message = NULL; - dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &message); + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &message); - result = dns_message_parse(message, input, DNS_MESSAGEPARSE_BESTEFFORT); - if (result == DNS_R_RECOVERABLE) { - result = ISC_R_SUCCESS; - } + result = dns_message_parse(message, input, DNS_MESSAGEPARSE_BESTEFFORT); + if (result == DNS_R_RECOVERABLE) { + result = ISC_R_SUCCESS; + } - if (result == ISC_R_SUCCESS && messagep != NULL) { - *messagep = message; - } else { - dns_message_detach(&message); - } + if (result == ISC_R_SUCCESS && messagep != NULL) { + *messagep = message; + } else { + dns_message_detach(&message); + } - return (result); + return (result); } -static isc_result_t print_message(dns_message_t *message) { - isc_result_t result; - isc_buffer_t buffer; - - do { - isc_buffer_init(&buffer, output, output_len); - result = dns_message_totext(message, &dns_master_style_debug, 0, &buffer); - if (result == ISC_R_NOSPACE) { - isc_mem_put(mctx, output, output_len); - output_len *= 2; - output = isc_mem_get(mctx, output_len); - continue; - } - } while (result == ISC_R_NOSPACE); - - if (debug) { - fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&buffer), output); - } - - return (result); +static isc_result_t +print_message(dns_message_t *message) { + isc_result_t result; + isc_buffer_t buffer; + + do { + isc_buffer_init(&buffer, output, output_len); + result = dns_message_totext(message, &dns_master_style_debug, 0, + &buffer); + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, output, output_len); + output_len *= 2; + output = isc_mem_get(mctx, output_len); + continue; + } + } while (result == ISC_R_NOSPACE); + + if (debug) { + fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&buffer), + output); + } + + return (result); } -#define CHECKRESULT(r, f) \ - { \ - r = (f); \ - if (r != ISC_R_SUCCESS) { \ - goto cleanup; \ - } \ - } +#define CHECKRESULT(r, f) \ + { \ + r = (f); \ + if (r != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } -static isc_result_t render_message(dns_message_t **messagep) { - isc_result_t result; - dns_message_t *message = *messagep; - isc_buffer_t buffer; - dns_compress_t cctx; +static isc_result_t +render_message(dns_message_t **messagep) { + isc_result_t result; + dns_message_t *message = *messagep; + isc_buffer_t buffer; + dns_compress_t cctx; - isc_buffer_init(&buffer, render_buf, sizeof(render_buf)); + isc_buffer_init(&buffer, render_buf, sizeof(render_buf)); - message->from_to_wire = DNS_MESSAGE_INTENTRENDER; - for (size_t i = 0; i < DNS_SECTION_MAX; i++) { - message->counts[i] = 0; - } + message->from_to_wire = DNS_MESSAGE_INTENTRENDER; + for (size_t i = 0; i < DNS_SECTION_MAX; i++) { + message->counts[i] = 0; + } - dns_compress_init(&cctx, mctx, 0); + dns_compress_init(&cctx, mctx, 0); - CHECKRESULT(result, dns_message_renderbegin(message, &cctx, &buffer)); + CHECKRESULT(result, dns_message_renderbegin(message, &cctx, &buffer)); - CHECKRESULT(result, dns_message_rendersection(message, DNS_SECTION_QUESTION, 0)); + CHECKRESULT(result, dns_message_rendersection(message, + DNS_SECTION_QUESTION, 0)); - CHECKRESULT(result, dns_message_rendersection(message, DNS_SECTION_ANSWER, 0)); - CHECKRESULT(result, dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0)); + CHECKRESULT(result, + dns_message_rendersection(message, DNS_SECTION_ANSWER, 0)); + CHECKRESULT(result, dns_message_rendersection( + message, DNS_SECTION_AUTHORITY, 0)); - CHECKRESULT(result, dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0)); + CHECKRESULT(result, dns_message_rendersection( + message, DNS_SECTION_ADDITIONAL, 0)); - dns_message_renderend(message); + dns_message_renderend(message); - dns_compress_invalidate(&cctx); + dns_compress_invalidate(&cctx); - message->from_to_wire = DNS_MESSAGE_INTENTPARSE; + message->from_to_wire = DNS_MESSAGE_INTENTPARSE; - dns_message_detach(messagep); + dns_message_detach(messagep); - result = parse_message(&buffer, messagep); + result = parse_message(&buffer, messagep); - return (result); + return (result); cleanup: - dns_compress_invalidate(&cctx); - return (result); + dns_compress_invalidate(&cctx); + return (result); } -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - isc_buffer_t buffer; - isc_result_t result; - dns_message_t *message = NULL; +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + isc_buffer_t buffer; + isc_result_t result; + dns_message_t *message = NULL; - if (size > 65535) { - return (0); - } + if (size > 65535) { + return (0); + } - isc_buffer_constinit(&buffer, data, size); - isc_buffer_add(&buffer, size); - isc_buffer_setactive(&buffer, size); + isc_buffer_constinit(&buffer, data, size); + isc_buffer_add(&buffer, size); + isc_buffer_setactive(&buffer, size); - result = parse_message(&buffer, &message); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } + result = parse_message(&buffer, &message); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } - result = print_message(message); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } + result = print_message(message); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } - result = render_message(&message); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } + result = render_message(&message); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } - result = print_message(message); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } + result = print_message(message); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } cleanup: - if (message != NULL) { - dns_message_detach(&message); - } + if (message != NULL) { + dns_message_detach(&message); + } - return (0); + return (0); } diff --git a/prompts/tool/container_tool.txt b/prompts/tool/container_tool.txt index 5f8ba052f1..5f8d8de504 100644 --- a/prompts/tool/container_tool.txt +++ b/prompts/tool/container_tool.txt @@ -1,40 +1,118 @@ -To help write a simple but valid fuzz target, you can investigate any files in the fuzz target's build environment by iteratively sending me a BASH command, and I will provide you with the output of the command. -Some interaction protocols: -1. Strictly ONE BASH command at a time. -2. Each message you send should first explain the reason why you want to run the command wrapped by , then provide the command to run wrapped in in this format: - -Reasons here. - - -One bash command here. - -3. Each reponse I send will repeat the command you sent wrapped in for you to double-check, followed by the command standard output wrapped in and stderr wrapped in < in this format: - -The command I executed, copied from the command you sent. - - -The standard output of the command. - - -The standard error of the command. - -4. The final goal is to answer two questions about the new fuzz target: a) How to modify the existing fuzz target at {FUZZ_TARGET_PATH} so that it can fuzz the new function-under-test? b) Do we need to modify the build script at /src/build.sh to successfully build the new fuzz target? -5. If you have a conclusion on both questions, output overall description wrapped by followed by the modified target wrapped in . If you modified the build script, output it wrapped in : - -Overall description about fuzz target design. - - -The full code of the fixed fuzz target here. - - -The full code of build script here if you modified the build script, otherwise omit this block. - + +**Bash too Guilde** +Use the bash tool to investigate files in the fuzz target's build environment. This will help you understand the project source code, the function under test, its dependencies, and any compilation requirements. -Some general rules: -1. You are allowed to view all files and environment variables, but NOT ALLOWED TO 1) MODIFY THEM, RENAME THEM, OR CREATE NEW FILES. You can only modify the fuzz target at {FUZZ_TARGET_PATH} or the build script at /src/build.sh ONLY, and output the final version in conclusion. All modification of other files will NOT BE PRESERVED when building the modified fuzz target. -2. Use the given fuzz target at {FUZZ_TARGET_PATH} and other fuzz targets using LLVMFuzzerTestOneInput under the same directory as examples. In particular, learn and reuse their ways to include header files in your solution. In most cases, you can assume you only have to modify the content of LLVMFuzzerTestOneInput to fuzz the new function-under-test. -3. If the header inclusion statements do not work, investigate the source code of the project and library files built by build.sh. -4. If the building the fuzz target failed because it does not contain the function-under-test, consider modify /src/build.sh to build the full project. The project-under-test's root dir is cloned from the project's git repo and may contain a README.md that describes how to build the full project. -5. YOU MUST NOT COMPILE the fuzz target. Respond to the conclusion above once you think you have an answer. The answer does not have to be perfect, I will compile it and show you the result. -6. Once I receive your conclusion, I will replace {FUZZ_TARGET_PATH} with your fuzz target. If you modified the build script, I will replace /src/build.sh with it too. -7. DO NOT wrap code snippets with ```, using the XML-style tags above will suffice. + +1. STRICTLY Only One Bash Command per message: + * **DO NOT** send multiple bash commands in each message. +2. Execute Bash Command Message Structure: + * Reason for the Command: + * Explain the reason for running the command. + * Wrap this explanation within and tags. + * Bash Command: + * Provide the bash command to execute. + * Wrap the command with and tags. + * Format Example: + + I want to locate the source file containing the definition of the function-under-test to examine its implementation. + + + grep -rn 'function_name(' /src/project-name/ + +3. Receiving Bash Command Output Message Structure: + * Bash execution outputs will be returned in the following format: + + [The command you executed.] + + + [Standard output of the command.] + + + [Standard error of the command.] + + + + +1 .File Access and Modification Restrictions: + * Allowed Actions: + * View any files and environment variables in the build environment. + * Prohibited Actions: + * Do not modify, rename, or create new files. + * All modifications will not be preserved when building the fuzz target. + + + +1 .Purposeful Commands: + * Each bash command should have a clear purpose related to your investigation toward the final goals. +2. Careful Interpretation: + * Analyze the output of each command thoroughly to inform your next steps. + * Keep notes of important findings that will help in modifying the fuzz target and build script. +4. Clarity and Compliance: + * Adhere strictly to the interaction protocols and formatting requirements. + * Ensure your messages are clear and properly formatted. +5. No Unauthorized Actions: + * Do not modify files. +6. Avoid using `pkg-config`: + * Use bash commands to manually identify the correct file paths + * Explore the project's directory hierarchy (`/src/`) to learn headerfiles locations, library's naming conventions, and build system. + + + +Command 1. Start by locating the function's definition and understand its parameters, e.g.: + + To find the definition of `my_function` in the project directory and understand its implementation details. + + + grep -rn 'my_function(' /src/project/ + +Command 2. Identify Required Headers: + + To identify the header files in the project directory that declare `my_function`. + + + grep -rn 'my_function' /src/project/ --include=*.h + +Command 3. Locate Custom Type Definitions: + + To find the definition of the custom type `CustomType` used by `my_function`. + + + grep -rn 'typedef.*CustomType' /src/project/ + +Command 4. Examine Existing Fuzz Targets: + + To see how existing fuzz targets include headers and initialize variables in the `LLVMFuzzerTestOneInput` function. + + + cat {FUZZ_TARGET_PATH} + + * Remember you can use the same command on other example fuzz targets under the same parent directory as `{FUZZ_TARGET_PATH}`. +Command 5. Check Build Script for Compilation Flags and Libraries: + + To check which compiler flags and libraries are used in the build script. + + + cat /src/build.sh + +Command 6. Verify Available Libraries: + + To list the built libraries to verify that the necessary libraries are available. + + + ls /src/project/build/libs/ + +Command 7. Understand Environment Variables: + + To check if any environment variables related to the project are set. + + + printenv | grep 'PROJECT_VARIABLE' + + + + +1. STRICTLY ONE Bash Command in each message: Do NOT send multiple bash commands in one message. +3. Do Not Compile or Run Code: + * Your investigation is limited to reading and interpreting information using bash commands. + +