handle fake crash reports generated by debugging tools in regression tasks (#1233)

This commit is contained in:
bmc-msft
2021-09-22 13:16:35 -04:00
committed by GitHub
parent e137eacffb
commit 9413377c90
4 changed files with 89 additions and 14 deletions

View 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
}

View File

@ -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(())
}
}

View File

@ -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",

View File

@ -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")