Skip to content

Commit fb22e75

Browse files
Allow tests to directly call loader internal functions
This allows the fuzz tests to faithfully recreate the calling environment of OSS-Fuzz, meaning reproduction of failing fuzz tests can be done in the repo for regression testing. The implementation of this requires exporting several functions that the fuzz tests need which is done with a new macro that is only active when a specific compiler definition is set, which the build does when testing is active.
1 parent 78fa00f commit fb22e75

File tree

12 files changed

+78
-25
lines changed

12 files changed

+78
-25
lines changed

loader/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,10 @@ if (UNKNOWN_FUNCTIONS_SUPPORTED)
517517
add_dependencies(vulkan loader_asm_gen_files)
518518
endif()
519519

520+
if (BUILD_TESTS)
521+
target_compile_definitions(vulkan PRIVATE SHOULD_EXPORT_TEST_FUNCTIONS)
522+
endif()
523+
520524
if (APPLE_STATIC_LOADER)
521525
# TLDR: This feature only exists at the request of Google for Chromium. No other project should use this!
522526
message(NOTICE "Apple STATIC lib: it will be built but not installed, and vulkan.pc and VulkanLoaderConfig.cmake won't be generated!")

loader/cJSON.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
150150
}
151151

152152
/* Delete a cJSON structure. */
153-
CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
153+
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
154154
cJSON *next = NULL;
155155
while (item != NULL) {
156156
next = item->next;
@@ -949,7 +949,9 @@ static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *ou
949949
}
950950

951951
/* Render a cJSON item/entity/structure to text. */
952-
CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) { return (char *)print(item, true, out_of_memory); }
952+
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
953+
return (char *)print(item, true, out_of_memory);
954+
}
953955

954956
CJSON_PUBLIC(char *) loader_cJSON_PrintUnformatted(const cJSON *item, bool *out_of_memory) {
955957
return (char *)print(item, false, out_of_memory);

loader/cJSON.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
8888
#include <stddef.h>
8989
#include <stdbool.h>
9090

91+
#include "vk_loader_platform.h"
92+
9193
/* cJSON Types: */
9294
#define cJSON_Invalid (0)
9395
#define cJSON_False (1 << 0)
@@ -163,7 +165,7 @@ loader_cJSON_ParseWithLengthOpts(const VkAllocationCallbacks *pAllocator, const
163165
const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory);
164166

165167
/* Render a cJSON entity to text for transfer/storage. */
166-
CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory);
168+
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory);
167169
/* Render a cJSON entity to text for transfer/storage without any formatting. */
168170
CJSON_PUBLIC(char *) loader_cJSON_PrintUnformatted(const cJSON *item, bool *out_of_memory);
169171
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces
@@ -177,7 +179,7 @@ loader_cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt, boo
177179
CJSON_PUBLIC(cJSON_bool)
178180
loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
179181
/* Delete a cJSON entity and all subentities. */
180-
CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item);
182+
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item);
181183

182184
/* Returns the number of items in an array (or object). */
183185
CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array);

loader/loader.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,8 @@ bool loader_find_layer_name_in_blacklist(const char *layer_name, struct loader_l
508508
}
509509

510510
// Remove all layer properties entries from the list
511-
void loader_delete_layer_list_and_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
511+
TEST_FUNCTION_EXPORT void loader_delete_layer_list_and_properties(const struct loader_instance *inst,
512+
struct loader_layer_list *layer_list) {
512513
uint32_t i;
513514
if (!layer_list) return;
514515

loader/loader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ VkResult loader_add_device_extensions(const struct loader_instance *inst,
154154
VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size);
155155
void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list);
156156
void loader_destroy_pointer_layer_list(const struct loader_instance *inst, struct loader_pointer_layer_list *layer_list);
157-
void loader_delete_layer_list_and_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list);
157+
TEST_FUNCTION_EXPORT void loader_delete_layer_list_and_properties(const struct loader_instance *inst,
158+
struct loader_layer_list *layer_list);
158159
void loader_remove_layer_in_list(const struct loader_instance *inst, struct loader_layer_list *layer_list,
159160
uint32_t layer_to_remove);
160161
VkResult loader_init_scanned_icd_list(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);

loader/loader_json.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ VkResult loader_read_entire_file(const struct loader_instance *inst, const char
136136
}
137137
#endif
138138

139-
VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
139+
TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
140140
char *json_buf = NULL;
141141
VkResult res = VK_SUCCESS;
142142

loader/loader_json.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct loader_string_list;
3838
//
3939
// @return - A pointer to a cJSON object representing the JSON parse tree.
4040
// This returned buffer should be freed by caller.
41-
VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json);
41+
TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json);
4242

4343
// Given a cJSON object, find the string associated with the key and puts an pre-allocated string into out_string.
4444
// Length is given by out_str_len, and this function truncates the string with a null terminator if it the provided space isn't

loader/settings.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ VkResult get_loader_settings(const struct loader_instance* inst, loader_settings
484484
return res;
485485
}
486486

487-
VkResult update_global_loader_settings(void) {
487+
TEST_FUNCTION_EXPORT VkResult update_global_loader_settings(void) {
488488
loader_settings settings = {0};
489489
VkResult res = get_loader_settings(NULL, &settings);
490490
loader_platform_thread_lock_mutex(&global_loader_settings_lock);
@@ -538,8 +538,8 @@ void release_current_settings_lock(const struct loader_instance* inst) {
538538
}
539539
}
540540

541-
VkResult get_settings_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
542-
bool* should_search_for_other_layers) {
541+
TEST_FUNCTION_EXPORT VkResult get_settings_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
542+
bool* should_search_for_other_layers) {
543543
VkResult res = VK_SUCCESS;
544544
*should_search_for_other_layers = true; // default to true
545545

loader/settings.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "vulkan/vulkan_core.h"
3131

3232
#include "log.h"
33+
#include "vk_loader_platform.h"
3334

3435
struct loader_instance;
3536
struct loader_layer_list;
@@ -83,7 +84,7 @@ void free_loader_settings(const struct loader_instance* inst, loader_settings* l
8384
void log_settings(const struct loader_instance* inst, loader_settings* settings);
8485

8586
// Every global function needs to call this at startup to insure that
86-
VkResult update_global_loader_settings(void);
87+
TEST_FUNCTION_EXPORT VkResult update_global_loader_settings(void);
8788

8889
// Needs to be called during startup -
8990
void init_global_loader_settings(void);
@@ -94,8 +95,8 @@ bool should_skip_logging_global_messages(VkFlags msg_type);
9495

9596
// Query the current settings (either global or per-instance) and return the list of layers contained within.
9697
// should_search_for_other_layers tells the caller if the settings file should be used exclusively for layer searching or not
97-
VkResult get_settings_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
98-
bool* should_search_for_other_layers);
98+
TEST_FUNCTION_EXPORT VkResult get_settings_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
99+
bool* should_search_for_other_layers);
99100

100101
// Take the provided list of settings_layers and add in the layers from regular search paths
101102
// Only adds layers that aren't already present in the settings_layers and in the location of the

loader/vk_loader_platform.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@
8989
#define LOADER_EXPORT
9090
#endif
9191

92+
// For testing purposes, we want to expose some functions not normally callable on the library
93+
#if defined(SHOULD_EXPORT_TEST_FUNCTIONS)
94+
#if defined(_WIN32)
95+
#define TEST_FUNCTION_EXPORT __declspec(dllexport)
96+
#else
97+
#define TEST_FUNCTION_EXPORT LOADER_EXPORT
98+
#endif
99+
#else
100+
#define TEST_FUNCTION_EXPORT
101+
#endif
102+
92103
#define MAX_STRING_SIZE 1024
93104

94105
// This is defined in vk_layer.h, but if there's problems we need to create the define

0 commit comments

Comments
 (0)