Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Commit

Permalink
handle fake crash reports generated by debugging tools in regression …
Browse files Browse the repository at this point in the history
…tasks (#1233)
  • Loading branch information
bmc-msft authored Sep 22, 2021
1 parent e137eac commit 9413377
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 13 deletions.
29 changes: 29 additions & 0 deletions src/agent/onefuzz-agent/data/fake-crash-report.json
Original file line number Diff line number Diff line change
@@ -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
}
60 changes: 49 additions & 11 deletions src/agent/onefuzz-agent/src/tasks/report/crash_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 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);
if let Ok(no_repro) = no_repro {
return Ok(CrashTestResult::NoRepro(no_repro));
}

bail!("unable to parse report: {} - {:?}", path.display(), raw)
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(
Expand All @@ -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(())
}
}
4 changes: 2 additions & 2 deletions src/cli/onefuzz/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ def _get_storage_account(self, container_name: Container) -> str:

def job(
self,
job_id: str,
job_id: UUID_EXPANSION,
*,
report_container_type: ContainerType = ContainerType.unique_reports,
crash_name: str = "fake-crash-sample",
Expand All @@ -655,7 +655,7 @@ def job(

def task(
self,
task_id: str,
task_id: UUID_EXPANSION,
*,
report_container_type: ContainerType = ContainerType.unique_reports,
crash_name: str = "fake-crash-sample",
Expand Down
8 changes: 8 additions & 0 deletions src/integration-tests/integration-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand All @@ -90,6 +91,7 @@ class Integration(BaseModel):
ContainerType.inputs: 2,
},
reboot_after_setup=True,
inject_fake_regression=True,
),
"linux-libfuzzer-with-options": Integration(
template=TemplateType.libfuzzer,
Expand Down Expand Up @@ -161,6 +163,7 @@ class Integration(BaseModel):
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,
Expand All @@ -181,6 +184,7 @@ class Integration(BaseModel):
ContainerType.unique_reports: 1,
ContainerType.coverage: 1,
},
inject_fake_regression=True,
),
"windows-libfuzzer-linked-library": Integration(
template=TemplateType.libfuzzer,
Expand Down Expand Up @@ -212,6 +216,7 @@ class Integration(BaseModel):
target_exe="fuzz.exe",
inputs="seeds",
wait_for_files={ContainerType.unique_reports: 1},
inject_fake_regression=True,
),
}

Expand Down Expand Up @@ -337,6 +342,9 @@ def launch(
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")

Expand Down

0 comments on commit 9413377

Please sign in to comment.