Skip to content

Commit 40d7fb0

Browse files
Merge pull request #148 from microsoft/main
Fork Sync: Update from parent repository
2 parents 1abbff9 + aa902d3 commit 40d7fb0

File tree

20 files changed

+1051
-0
lines changed

20 files changed

+1051
-0
lines changed

src/agent/Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/agent/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ members = [
1010
"onefuzz",
1111
"onefuzz-task",
1212
"onefuzz-agent",
13+
"onefuzz-file-format",
1314
"onefuzz-telemetry",
1415
"reqwest-retry",
1516
"srcview",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "onefuzz-file-format"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license = "MIT"
6+
7+
[dependencies]
8+
anyhow = "1.0"
9+
coverage = { path = "../coverage" }
10+
debuggable-module = { path = "../debuggable-module" }
11+
quick-xml = "0.26.0"
12+
serde = { version = "1.0", features = ["derive"] }
13+
serde_json = { version = "1.0", features = ["preserve_order"] }
14+
15+
[dev-dependencies]
16+
pretty_assertions = "1.3"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use anyhow::Result;
5+
6+
use coverage::source::{Count, FileCoverage, Line, SourceCoverage};
7+
use debuggable_module::path::FilePath;
8+
use onefuzz_file_format::coverage::cobertura::CoberturaCoverage;
9+
10+
fn main() -> Result<()> {
11+
let modoff = vec![
12+
(r"/missing/lib.c", vec![1, 2, 3, 5, 8]),
13+
(
14+
r"test-data/fuzz.c",
15+
vec![
16+
7, 8, 10, 13, 16, 17, 21, 22, 23, 27, 28, 29, 30, 32, 33, 37, 39, 42, 44,
17+
],
18+
),
19+
(r"test-data\fuzz.h", vec![3, 4, 5]),
20+
(r"test-data\lib\explode.h", vec![1, 2, 3]),
21+
];
22+
23+
let mut coverage = SourceCoverage::default();
24+
25+
for (path, lines) in modoff {
26+
let file_path = FilePath::new(path)?;
27+
28+
let mut file = FileCoverage::default();
29+
30+
for line in lines {
31+
let count = if line % 3 == 0 { 1 } else { 0 };
32+
file.lines.insert(Line::new(line)?, Count(count));
33+
}
34+
35+
coverage.files.insert(file_path, file);
36+
}
37+
38+
let cobertura = CoberturaCoverage::from(coverage);
39+
40+
let text = cobertura.to_string()?;
41+
println!("{text}");
42+
43+
Ok(())
44+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
pub mod binary;
5+
pub mod cobertura;
6+
pub mod source;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use anyhow::Result;
5+
use coverage::binary::BinaryCoverage;
6+
7+
pub mod v0;
8+
pub mod v1;
9+
10+
#[derive(Serialize, Deserialize)]
11+
#[serde(tag = "version")]
12+
pub enum BinaryCoverageJson {
13+
#[serde(rename = "0")]
14+
V0(v0::BinaryCoverageJson),
15+
16+
#[serde(rename = "1")]
17+
V1(v1::BinaryCoverageJson),
18+
}
19+
20+
impl TryFrom<BinaryCoverageJson> for BinaryCoverage {
21+
type Error = anyhow::Error;
22+
23+
fn try_from(json: BinaryCoverageJson) -> Result<Self> {
24+
use BinaryCoverageJson::*;
25+
26+
match json {
27+
V0(v0) => v0.try_into(),
28+
V1(v1) => v1.try_into(),
29+
}
30+
}
31+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use anyhow::Result;
5+
use coverage::binary::{BinaryCoverage, Count, ModuleBinaryCoverage};
6+
use debuggable_module::path::FilePath;
7+
use debuggable_module::Offset;
8+
use serde::{Deserialize, Serialize};
9+
10+
#[derive(Deserialize, Serialize)]
11+
#[serde(transparent)]
12+
pub struct BinaryCoverageJson {
13+
#[serde(flatten)]
14+
pub modules: Vec<BinaryModuleCoverageJson>,
15+
}
16+
17+
#[derive(Deserialize, Serialize)]
18+
pub struct BinaryModuleCoverageJson {
19+
pub module: String,
20+
pub blocks: Vec<BinaryBlockCoverageJson>,
21+
}
22+
23+
#[derive(Deserialize, Serialize)]
24+
pub struct BinaryBlockCoverageJson {
25+
pub offset: u32,
26+
pub count: u32,
27+
}
28+
29+
impl TryFrom<BinaryCoverage> for BinaryCoverageJson {
30+
type Error = anyhow::Error;
31+
32+
fn try_from(binary: BinaryCoverage) -> Result<Self> {
33+
let mut modules = Vec::new();
34+
35+
for (module, offsets) in binary.modules {
36+
let mut blocks = Vec::new();
37+
38+
for (offset, count) in offsets.as_ref() {
39+
let offset = u32::try_from(offset.0)?;
40+
let count = count.0;
41+
let block = BinaryBlockCoverageJson { offset, count };
42+
blocks.push(block);
43+
}
44+
45+
let module = module.as_str().to_owned();
46+
let module = BinaryModuleCoverageJson { module, blocks };
47+
48+
modules.push(module);
49+
}
50+
51+
Ok(Self { modules })
52+
}
53+
}
54+
55+
impl TryFrom<BinaryCoverageJson> for BinaryCoverage {
56+
type Error = anyhow::Error;
57+
58+
fn try_from(json: BinaryCoverageJson) -> Result<Self> {
59+
let mut process = BinaryCoverage::default();
60+
61+
for coverage_json in json.modules {
62+
let mut coverage = ModuleBinaryCoverage::default();
63+
64+
for block in coverage_json.blocks {
65+
let offset = Offset(u64::from(block.offset));
66+
let count = Count(block.count);
67+
coverage.offsets.insert(offset, count);
68+
}
69+
70+
let path = FilePath::new(coverage_json.module)?;
71+
72+
process.modules.insert(path, coverage);
73+
}
74+
75+
Ok(process)
76+
}
77+
}
78+
79+
#[cfg(test)]
80+
mod tests;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use anyhow::Result;
5+
use pretty_assertions::assert_eq;
6+
use serde_json::json;
7+
8+
use super::*;
9+
10+
const MAIN_EXE: &str = "/setup/main.exe";
11+
const SOME_DLL: &str = "/setup/lib/some.dll";
12+
13+
const EXPECTED: &str = r#"
14+
[
15+
{
16+
"module": "/setup/main.exe",
17+
"blocks": [
18+
{
19+
"offset": 1,
20+
"count": 0
21+
},
22+
{
23+
"offset": 300,
24+
"count": 1
25+
},
26+
{
27+
"offset": 5000,
28+
"count": 0
29+
}
30+
]
31+
},
32+
{
33+
"module": "/setup/lib/some.dll",
34+
"blocks": [
35+
{
36+
"offset": 123,
37+
"count": 0
38+
},
39+
{
40+
"offset": 456,
41+
"count": 10
42+
}
43+
]
44+
}
45+
]
46+
"#;
47+
48+
#[test]
49+
fn test_serialize_deseralize() -> Result<()> {
50+
let value = json!([
51+
{
52+
"module": MAIN_EXE,
53+
"blocks": [
54+
{ "offset": 1, "count": 0 },
55+
{ "offset": 300, "count": 1 },
56+
{ "offset": 5000, "count": 0 },
57+
],
58+
},
59+
{
60+
"module": SOME_DLL,
61+
"blocks": [
62+
{ "offset": 123, "count": 0 },
63+
{ "offset": 456, "count": 10 },
64+
],
65+
},
66+
]);
67+
let coverage: BinaryCoverageJson = serde_json::from_value(value)?;
68+
69+
let text = serde_json::to_string_pretty(&coverage)?;
70+
assert_eq!(text.trim(), EXPECTED.trim());
71+
72+
Ok(())
73+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use std::collections::BTreeMap;
5+
6+
use anyhow::Result;
7+
use coverage::binary::{BinaryCoverage, Count, ModuleBinaryCoverage};
8+
use debuggable_module::path::FilePath;
9+
use debuggable_module::Offset;
10+
11+
use crate::hex::Hex;
12+
13+
#[derive(Deserialize, Serialize)]
14+
pub struct BinaryCoverageJson {
15+
#[serde(flatten)]
16+
pub modules: BTreeMap<String, BTreeMap<Hex, u32>>,
17+
}
18+
19+
impl From<BinaryCoverage> for BinaryCoverageJson {
20+
fn from(binary: BinaryCoverage) -> Self {
21+
let mut modules = BTreeMap::new();
22+
23+
for (module, offsets) in &binary.modules {
24+
let mut map: BTreeMap<Hex, u32> = BTreeMap::new();
25+
26+
for (offset, count) in offsets.as_ref() {
27+
map.insert(Hex(offset.0), count.0);
28+
}
29+
30+
let path = module.as_str().to_owned();
31+
modules.insert(path, map);
32+
}
33+
34+
Self { modules }
35+
}
36+
}
37+
38+
impl TryFrom<BinaryCoverageJson> for BinaryCoverage {
39+
type Error = anyhow::Error;
40+
41+
fn try_from(json: BinaryCoverageJson) -> Result<Self> {
42+
let mut process = BinaryCoverage::default();
43+
44+
for (module, offsets) in json.modules {
45+
let mut coverage = ModuleBinaryCoverage::default();
46+
47+
for (hex, count) in offsets {
48+
let offset = Offset(hex.0);
49+
coverage.offsets.insert(offset, Count(count));
50+
}
51+
52+
let path = FilePath::new(module)?;
53+
process.modules.insert(path, coverage);
54+
}
55+
56+
Ok(process)
57+
}
58+
}

0 commit comments

Comments
 (0)