Skip to content

Commit 8b1274b

Browse files
Add instance_create_advanced_fuzzer runner
OSS-Fuzz added an 'advanced' fuzzer which creates multiple files by parsing the fuzz input file into multiple separate files. To add the fuzz test we needed to recreate the same logic that enables creating files.
1 parent dc509c2 commit 8b1274b

File tree

5 files changed

+89
-13
lines changed

5 files changed

+89
-13
lines changed

tests/framework/shim/shim.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@
6363

6464
enum class GpuType { unspecified, integrated, discrete, external };
6565

66+
struct TempFile {
67+
explicit TempFile(std::filesystem::path filename) : filename(filename) {}
68+
~TempFile() { std::filesystem::remove(filename); }
69+
std::filesystem::path filename;
70+
};
71+
6672
#if defined(_WIN32)
6773
#define VK_VARIANT_REG_STR ""
6874
#define VK_VARIANT_REG_STR_W L""
@@ -231,6 +237,8 @@ struct PlatformShim {
231237
std::string bundle_contents;
232238
#endif
233239
#endif
240+
std::vector<uint8_t> fuzz_data;
241+
std::vector<TempFile> temp_fuzz_files;
234242
bool is_finished_setup = false;
235243
bool is_during_destruction = false;
236244
};

tests/framework/shim/unix_shim.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include "shim.h"
2929

30+
#include <cstring>
31+
3032
#include <algorithm>
3133
#include <iostream>
3234

@@ -266,17 +268,32 @@ FRAMEWORK_EXPORT FILE* FOPEN_FUNC_NAME(const char* in_filename, const char* mode
266268
if (platform_shim.is_during_destruction || !platform_shim.is_finished_setup) {
267269
return real_fopen(in_filename, mode);
268270
}
269-
271+
FILE* out_file = nullptr;
270272
std::filesystem::path path{in_filename};
271273
if (!path.has_parent_path()) {
272-
return real_fopen(in_filename, mode);
274+
out_file = real_fopen(in_filename, mode);
273275
} else if (auto real_path = platform_shim.file_system_manager->get_real_path_of_redirected_path(path.parent_path());
274276
!real_path.empty()) {
275277
real_path /= path.filename();
276-
return real_fopen(real_path.c_str(), mode);
278+
out_file = real_fopen(real_path.c_str(), mode);
277279
} else {
278-
return real_fopen(in_filename, mode);
280+
out_file = real_fopen(in_filename, mode);
281+
}
282+
283+
// Fuzz tests have sub files embedded in the input data file. This
284+
if (!platform_shim.fuzz_data.empty() && out_file == NULL) {
285+
fprintf(stderr, "create_callback_file: Creating file %s\n", in_filename);
286+
FILE* fp = fopen(in_filename, "wb");
287+
if (nullptr == fp) {
288+
abort();
289+
}
290+
fwrite(platform_shim.fuzz_data.data(), platform_shim.fuzz_data.size(), 1, fp);
291+
fclose(fp);
292+
platform_shim.temp_fuzz_files.emplace_back(in_filename);
293+
294+
out_file = fopen(in_filename, "rb");
279295
}
296+
return out_file;
280297
}
281298

282299
FRAMEWORK_EXPORT void* DLOPEN_FUNC_NAME(const char* in_filename, int flags) {

tests/loader_fuzz_tests.cpp

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
* Author: Charles Giessen <[email protected]>
2626
*/
2727

28-
#include "test_environment.h"
28+
#include "framework/test_environment.h"
29+
30+
#include <fstream>
2931

3032
extern "C" {
3133
#include "loader.h"
@@ -45,14 +47,10 @@ void execute_instance_enumerate_fuzzer(std::filesystem::path const& filename) {
4547

4648
env.vulkan_functions.vkEnumerateInstanceExtensionProperties("test_auto", &pPropertyCount, &pProperties);
4749
}
48-
void execute_instance_create_fuzzer(std::filesystem::path const& filename) {
49-
FrameworkEnvironment env{};
50-
env.write_file_from_source((std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename).string().c_str(),
51-
ManifestCategory::implicit_layer, ManifestLocation::implicit_layer, "complex_layer.json");
52-
env.write_file_from_source((std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename).string().c_str(),
53-
ManifestCategory::settings, ManifestLocation::settings_location, "vk_loader_settings.json");
54-
env.write_file_from_source((std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename).string().c_str(),
55-
ManifestCategory::icd, ManifestLocation::driver, "icd_test.json");
50+
// Common code for execute_instance_create_fuzzer and execute_instance_create_fuzzer_advanced
51+
void execute_instance_create_fuzzer_logic(FrameworkEnvironment& env) {
52+
EnvVarWrapper enable_all_layers("VK_LOADER_LAYERS_ENABLE", "all");
53+
5654
VkInstance inst = {0};
5755
const char* instance_layers[] = {"VK_LAYER_KHRONOS_validation", "VK_LAYER_test_layer_1", "VK_LAYER_test_layer_2"};
5856
VkApplicationInfo app{};
@@ -81,6 +79,53 @@ void execute_instance_create_fuzzer(std::filesystem::path const& filename) {
8179
env.vulkan_functions.vkDestroyInstance(inst, NULL);
8280
}
8381

82+
void execute_instance_create_fuzzer(std::filesystem::path const& filename) {
83+
FrameworkEnvironment env{};
84+
env.write_file_from_source((std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename).string().c_str(),
85+
ManifestCategory::implicit_layer, ManifestLocation::unsecured_implicit_layer, "complex_layer.json");
86+
env.write_file_from_source((std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename).string().c_str(),
87+
ManifestCategory::settings, ManifestLocation::unsecured_settings, "vk_loader_settings.json");
88+
env.write_file_from_source((std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename).string().c_str(),
89+
ManifestCategory::icd, ManifestLocation::unsecured_driver, "icd_test.json");
90+
91+
execute_instance_create_fuzzer_logic(env);
92+
}
93+
94+
void execute_instance_create_advanced_fuzzer(std::filesystem::path const& filename) {
95+
FrameworkEnvironment env{};
96+
97+
// The file actually contains three subfiles with their lengths specified in the first 12 bytes of the file.
98+
auto source_file = std::filesystem::path(CLUSTERFUZZ_TESTCASE_DIRECTORY) / filename;
99+
std::fstream file{source_file.string(), std::ios_base::in | std::ios_base::binary};
100+
ASSERT_TRUE(file.is_open());
101+
std::stringstream file_stream;
102+
file_stream << file.rdbuf();
103+
104+
auto data_string = file_stream.str();
105+
auto data_cstring = data_string.c_str();
106+
std::array<uint64_t, 3> sections;
107+
memcpy(sections.data(), data_cstring, sizeof(uint64_t) * 3);
108+
sections[0] = sections[0] % 40000;
109+
sections[1] = sections[1] % 40000;
110+
sections[2] = sections[2] % 40000;
111+
112+
uint64_t data_index = 3 * sizeof(uint64_t);
113+
std::string first = data_string.substr(data_index, sections[0]);
114+
data_index += sections[0];
115+
std::string second = data_string.substr(data_index, sections[1]);
116+
data_index += sections[1];
117+
std::string third = data_string.substr(data_index, sections[2]);
118+
data_index += sections[2];
119+
120+
env.platform_shim->fuzz_data.resize(data_string.size() - data_index);
121+
memcpy(env.platform_shim->fuzz_data.data(), data_cstring + data_index, env.platform_shim->fuzz_data.size());
122+
123+
env.write_file_from_string(first, ManifestCategory::implicit_layer, ManifestLocation::implicit_layer, "complex_layer.json");
124+
env.write_file_from_string(second, ManifestCategory::settings, ManifestLocation::settings_location, "vk_loader_settings.json");
125+
env.write_file_from_string(third, ManifestCategory::settings, ManifestLocation::settings_location, "icd_test.json");
126+
127+
execute_instance_create_fuzzer_logic(env);
128+
}
84129
void execute_json_load_fuzzer(std::string const& filename) {
85130
FrameworkEnvironment env{};
86131

@@ -208,6 +253,12 @@ TEST(BadJsonInput, ClusterFuzzTestCase_5817896795701248) {
208253
TEST(BadJsonInput, ClusterFuzzTestCase_6541440380895232) {
209254
execute_instance_create_fuzzer("clusterfuzz-testcase-instance_create_fuzzer-6541440380895232");
210255
}
256+
TEST(BadJsonInput, ClusterFuzzTestCase_5612556809207808) {
257+
execute_instance_create_advanced_fuzzer("clusterfuzz-testcase-minimized-instance_create_advanced_fuzzer-5612556809207808");
258+
}
259+
TEST(BadJsonInput, ClusterFuzzTestCase_4788849181261824) {
260+
execute_instance_create_advanced_fuzzer("clusterfuzz-testcase-minimized-instance_create_advanced_fuzzer-4788849181261824");
261+
}
211262
TEST(BadJsonInput, ClusterFuzzTestCase_6465902356791296) {
212263
// Does crash with UBSAN
213264
// Doesn't crash with ASAN

0 commit comments

Comments
 (0)