mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-15 03:18:07 +00:00
handle fake crash reports generated by debugging tools in regression tasks (#1233)
This commit is contained in:
29
src/agent/onefuzz-agent/data/fake-crash-report.json
Normal file
29
src/agent/onefuzz-agent/data/fake-crash-report.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"input_url": null,
|
||||
"input_blob": {
|
||||
"account": "fakestorageaccount",
|
||||
"container": "fake-storage-container",
|
||||
"name": "fake-crash-sample"
|
||||
},
|
||||
"executable": "dds.exe",
|
||||
"crash_type": "fake crash report",
|
||||
"crash_site": "fake crash site",
|
||||
"call_stack": [
|
||||
"#0 fake",
|
||||
"#1 call",
|
||||
"#2 stack"
|
||||
],
|
||||
"call_stack_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"input_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"asan_log": "fake asan log",
|
||||
"task_id": "2061fc8d-9f02-4d06-838a-87f59880e4e8",
|
||||
"job_id": "510f8e4e-3c4d-4b54-968c-4da459d09f04",
|
||||
"scariness_score": null,
|
||||
"scariness_description": null,
|
||||
"minimized_stack": [],
|
||||
"minimized_stack_sha256": null,
|
||||
"minimized_stack_function_names": [],
|
||||
"minimized_stack_function_names_sha256": null,
|
||||
"minimized_stack_function_lines": null,
|
||||
"minimized_stack_function_lines_sha256": null
|
||||
}
|
@ -40,8 +40,8 @@ pub struct CrashReport {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub minimized_stack_function_names_sha256: Option<String>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub minimized_stack_function_lines: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub minimized_stack_function_lines: Option<Vec<String>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub minimized_stack_function_lines_sha256: Option<String>,
|
||||
|
||||
@ -206,6 +206,21 @@ impl CrashReport {
|
||||
} else {
|
||||
Some(crash_log.minimized_stack_function_names_sha256(minimized_stack_depth))
|
||||
};
|
||||
|
||||
let minimized_stack_function_lines = if crash_log.minimized_stack_function_lines.is_empty()
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(crash_log.minimized_stack_function_lines)
|
||||
};
|
||||
|
||||
let minimized_stack_function_names = if crash_log.minimized_stack_function_names.is_empty()
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(crash_log.minimized_stack_function_names)
|
||||
};
|
||||
|
||||
Self {
|
||||
input_sha256,
|
||||
input_blob,
|
||||
@ -215,9 +230,9 @@ impl CrashReport {
|
||||
call_stack_sha256,
|
||||
minimized_stack: Some(crash_log.minimized_stack),
|
||||
minimized_stack_sha256,
|
||||
minimized_stack_function_names: Some(crash_log.minimized_stack_function_names),
|
||||
minimized_stack_function_names,
|
||||
minimized_stack_function_names_sha256,
|
||||
minimized_stack_function_lines: crash_log.minimized_stack_function_lines,
|
||||
minimized_stack_function_lines,
|
||||
minimized_stack_function_lines_sha256,
|
||||
call_stack: crash_log.call_stack,
|
||||
asan_log: crash_log.text,
|
||||
@ -251,15 +266,25 @@ pub async fn parse_report_file(path: PathBuf) -> Result<CrashTestResult> {
|
||||
.with_context(|| format_err!("invalid json: {} - {:?}", path.display(), raw))?;
|
||||
|
||||
let report: Result<CrashReport, serde_json::Error> = serde_json::from_value(json.clone());
|
||||
if let Ok(report) = report {
|
||||
return Ok(CrashTestResult::CrashReport(report));
|
||||
}
|
||||
let no_repro: Result<NoCrash, serde_json::Error> = serde_json::from_value(json);
|
||||
if let Ok(no_repro) = no_repro {
|
||||
return Ok(CrashTestResult::NoRepro(no_repro));
|
||||
}
|
||||
|
||||
bail!("unable to parse report: {} - {:?}", path.display(), raw)
|
||||
let report_err = match report {
|
||||
Ok(report) => return Ok(CrashTestResult::CrashReport(report)),
|
||||
Err(err) => err,
|
||||
};
|
||||
let no_repro: Result<NoCrash, serde_json::Error> = serde_json::from_value(json);
|
||||
|
||||
let no_repro_err = match no_repro {
|
||||
Ok(no_repro) => return Ok(CrashTestResult::NoRepro(no_repro)),
|
||||
Err(err) => err,
|
||||
};
|
||||
|
||||
bail!(
|
||||
"unable to parse report: {} - {:?} - report error: {:?} no_repo error: {:?}",
|
||||
path.display(),
|
||||
raw,
|
||||
report_err,
|
||||
no_repro_err
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn monitor_reports(
|
||||
@ -281,3 +306,16 @@ pub async fn monitor_reports(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use anyhow::Result;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parse_fake_crash_report() -> Result<()> {
|
||||
let path = std::path::PathBuf::from("data/fake-crash-report.json");
|
||||
parse_report_file(path).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -631,7 +631,7 @@ class DebugNotification(Command):
|
||||
|
||||
def job(
|
||||
self,
|
||||
job_id: str,
|
||||
job_id: UUID_EXPANSION,
|
||||
*,
|
||||
report_container_type: ContainerType = ContainerType.unique_reports,
|
||||
crash_name: str = "fake-crash-sample",
|
||||
@ -655,7 +655,7 @@ class DebugNotification(Command):
|
||||
|
||||
def task(
|
||||
self,
|
||||
task_id: str,
|
||||
task_id: UUID_EXPANSION,
|
||||
*,
|
||||
report_container_type: ContainerType = ContainerType.unique_reports,
|
||||
crash_name: str = "fake-crash-sample",
|
||||
|
@ -69,6 +69,7 @@ class Integration(BaseModel):
|
||||
reboot_after_setup: Optional[bool] = Field(default=False)
|
||||
test_repro: Optional[bool] = Field(default=True)
|
||||
target_options: Optional[List[str]]
|
||||
inject_fake_regression: bool = Field(default=False)
|
||||
|
||||
|
||||
TARGETS: Dict[str, Integration] = {
|
||||
@ -90,6 +91,7 @@ TARGETS: Dict[str, Integration] = {
|
||||
ContainerType.inputs: 2,
|
||||
},
|
||||
reboot_after_setup=True,
|
||||
inject_fake_regression=True,
|
||||
),
|
||||
"linux-libfuzzer-with-options": Integration(
|
||||
template=TemplateType.libfuzzer,
|
||||
@ -161,6 +163,7 @@ TARGETS: Dict[str, Integration] = {
|
||||
target_exe="fuzz.exe",
|
||||
inputs="seeds",
|
||||
wait_for_files={ContainerType.unique_reports: 1},
|
||||
inject_fake_regression=True,
|
||||
),
|
||||
"linux-trivial-crash-asan": Integration(
|
||||
template=TemplateType.radamsa,
|
||||
@ -181,6 +184,7 @@ TARGETS: Dict[str, Integration] = {
|
||||
ContainerType.unique_reports: 1,
|
||||
ContainerType.coverage: 1,
|
||||
},
|
||||
inject_fake_regression=True,
|
||||
),
|
||||
"windows-libfuzzer-linked-library": Integration(
|
||||
template=TemplateType.libfuzzer,
|
||||
@ -212,6 +216,7 @@ TARGETS: Dict[str, Integration] = {
|
||||
target_exe="fuzz.exe",
|
||||
inputs="seeds",
|
||||
wait_for_files={ContainerType.unique_reports: 1},
|
||||
inject_fake_regression=True,
|
||||
),
|
||||
}
|
||||
|
||||
@ -337,6 +342,9 @@ class TestOnefuzz:
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
if config.inject_fake_regression and job is not None:
|
||||
self.of.debug.notification.job(job.job_id)
|
||||
|
||||
if not job:
|
||||
raise Exception("missing job")
|
||||
|
||||
|
Reference in New Issue
Block a user