Skip to content

Commit 0c1d8ce

Browse files
authored
feat: fuzz testing RustParser
fixes: #3328 added fuzz testing for RustParser(Cargo.lock) based on [Rust docs](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html) and [Cargo.lock of Rust itself](https://github.com/rust-lang/rust/blob/master/Cargo.lock).
1 parent 0861a9a commit 0c1d8ce

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

fuzz/fuzz_cargo_lock.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright (C) 2023 Intel Corporation
2+
# SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
import sys
5+
import tempfile
6+
from pathlib import Path
7+
8+
import atheris
9+
import atheris_libprotobuf_mutator
10+
from google.protobuf.json_format import MessageToDict
11+
12+
import fuzz.generated.cargo_lock_pb2 as cargo_lock_pb2
13+
from cve_bin_tool.cvedb import CVEDB
14+
from cve_bin_tool.log import LOGGER
15+
16+
with atheris.instrument_imports():
17+
from cve_bin_tool.parsers.rust import RustParser
18+
19+
cve_db = CVEDB()
20+
logger = LOGGER.getChild("Fuzz")
21+
22+
23+
def CargoLockBuilder(data):
24+
json_data = MessageToDict(
25+
data, preserving_proto_field_name=True, including_default_value_fields=True
26+
)
27+
28+
with open(file_path, "w") as f:
29+
for package_data in json_data.get("packages", []):
30+
package_name = package_data.get("name", "")
31+
package_version = package_data.get("version", "")
32+
f.write("[[package]]\n")
33+
f.write(f'name = "{package_name}"\n')
34+
f.write(f'version = "{package_version}"\n')
35+
package_source = package_data.get("source", "")
36+
if package_source != "":
37+
f.write(f'source = "{package_source}"\n')
38+
package_checksum = package_data.get("checksum", "")
39+
if package_checksum != "":
40+
f.write(f'checksum = "{package_checksum}"\n')
41+
42+
dependencies = package_data.get("dependency", [])
43+
f.write("dependencies = [\n")
44+
for dependency in dependencies:
45+
name = dependency.get("name", "")
46+
version = dependency.get("version", "")
47+
url = dependency.get("url", "")
48+
f.write(f' "{name}')
49+
if version != "":
50+
f.write(f" {version}")
51+
if url != "":
52+
f.write(f" {url}")
53+
f.write('",\n')
54+
f.write("]\n")
55+
f.write("\n")
56+
57+
58+
def TestParseData(data):
59+
try:
60+
CargoLockBuilder(data)
61+
62+
rust_parser = RustParser(cve_db, logger)
63+
rust_parser.run_checker(file_path)
64+
65+
except SystemExit:
66+
return
67+
68+
69+
file_path = str(Path(tempfile.mkdtemp(prefix="cve-bin-tool-")) / "Cargo.lock")
70+
71+
atheris_libprotobuf_mutator.Setup(
72+
sys.argv, TestParseData, proto=cargo_lock_pb2.CargoLock
73+
)
74+
atheris.Fuzz()

fuzz/generated/cargo_lock_pb2.py

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

fuzz/proto_files/cargo_lock.proto

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (C) 2023 Intel Corporation
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
syntax = "proto3";
5+
6+
message CargoLock {
7+
message Package {
8+
string name = 1;
9+
string version = 2;
10+
optional string source = 3;
11+
optional string checksum = 4;
12+
repeated Dependencies dependency = 5;
13+
}
14+
message Dependencies {
15+
string name = 1;
16+
optional string version = 2;
17+
optional string url = 3;
18+
}
19+
repeated Package packages = 1;
20+
}

0 commit comments

Comments
 (0)