Skip to content

Commit b5ce10d

Browse files
authored
feat: Fuzz Testing RubyParser (#3736)
Signed-off-by: Joydeep Tripathy <[email protected]>
1 parent 774bb4d commit b5ce10d

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed

fuzz/fuzz_gemfile_lock.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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.gemfile_lock_pb2 as gemfile_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.ruby import RubyParser
18+
19+
cve_db = CVEDB()
20+
logger = LOGGER.getChild("Fuzz")
21+
22+
23+
def GemfileLockBuilder(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 git_pkg in json_data.get("git_packages", []):
30+
f.write("GIT\n")
31+
f.write(f' remote: {git_pkg.get("remote", "")}\n')
32+
f.write(f' revision: {git_pkg.get("revision", "")}\n')
33+
if git_pkg.get("branch"):
34+
f.write(f' branch: {git_pkg.get("branch", "")}\n')
35+
f.write(" specs:\n")
36+
for spec in git_pkg.get("specs", []):
37+
f.write(f' {spec.get("name", "")} ({spec.get("version", "")})\n')
38+
for dep in spec.get("dependencies", []):
39+
f.write(f" {dep}\n")
40+
41+
# Handling PATH packages
42+
for path_pkg in json_data.get("path_packages", []):
43+
f.write("PATH\n")
44+
f.write(f' remote: {path_pkg.get("remote", "")}\n')
45+
f.write(" specs:\n")
46+
for spec in path_pkg.get("specs", []):
47+
f.write(f' {spec.get("name", "")} ({spec.get("version", "")})\n')
48+
for dep in spec.get("dependencies", []):
49+
f.write(f" {dep}\n")
50+
51+
# Handling GEM packages
52+
for gem_pkg in json_data.get("gem_packages", []):
53+
f.write("GEM\n")
54+
f.write(f' remote: {gem_pkg.get("remote", "")}\n')
55+
f.write(" specs:\n")
56+
for spec in gem_pkg.get("specs", []):
57+
f.write(f' {spec.get("name", "")} ({spec.get("version", "")})\n')
58+
for dep in spec.get("dependencies", []):
59+
f.write(f" {dep}\n")
60+
61+
# Handling platforms
62+
f.write("PLATFORMS\n")
63+
for platform in json_data.get("platforms", []):
64+
f.write(f" {platform}\n")
65+
66+
# Handling dependencies
67+
f.write("DEPENDENCIES\n")
68+
for dep in json_data.get("dependencies", []):
69+
f.write(f" {dep}\n")
70+
71+
# Handling bundled with
72+
bundled_with = json_data.get("bundled_with", "")
73+
if bundled_with:
74+
f.write(f"BUNDLED WITH\n {bundled_with}\n")
75+
76+
77+
def TestParseData(data):
78+
try:
79+
GemfileLockBuilder(data)
80+
81+
ruby_parser = RubyParser(cve_db, logger)
82+
ruby_parser.run_checker(file_path)
83+
84+
except SystemExit:
85+
return
86+
87+
88+
file_path = str(Path(tempfile.mkdtemp(prefix="cve-bin-tool-")) / "Gemfile.lock")
89+
90+
atheris_libprotobuf_mutator.Setup(
91+
sys.argv, TestParseData, proto=gemfile_lock_pb2.GemfileLock
92+
)
93+
atheris.Fuzz()

fuzz/generated/gemfile_lock_pb2.py

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

fuzz/proto_files/gemfile_lock.proto

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (C) 2023 Intel Corporation
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
syntax = "proto3";
5+
6+
// Represents the state of a GIT package
7+
message GitPackage {
8+
string remote = 1;
9+
string revision = 2;
10+
string branch = 3;
11+
repeated Spec specs = 4;
12+
}
13+
14+
// Represents the state of a PATH package
15+
message PathPackage {
16+
string remote = 1;
17+
repeated Spec specs = 2;
18+
}
19+
20+
// Represents a spec in a package
21+
message Spec {
22+
string name = 1;
23+
string version = 2;
24+
repeated string dependencies = 3;
25+
}
26+
27+
// Represents the state of a GEM package
28+
message GemPackage {
29+
string remote = 1;
30+
repeated Spec specs = 2;
31+
}
32+
33+
// Represents the entire Gemfile.lock file
34+
message GemfileLock {
35+
repeated GitPackage git_packages = 1;
36+
repeated PathPackage path_packages = 2;
37+
repeated GemPackage gem_packages = 3;
38+
repeated string platforms = 4;
39+
repeated string dependencies = 5;
40+
string bundled_with = 6;
41+
}

0 commit comments

Comments
 (0)