diff options
author | Charles Giessen <charles@lunarg.com> | 2022-05-25 19:47:55 +0300 |
---|---|---|
committer | Charles Giessen <46324611+charles-lunarg@users.noreply.github.com> | 2022-05-25 22:14:04 +0300 |
commit | c2897084d25489454bb1ee6b7bedc5b96e6dadd5 (patch) | |
tree | ed37633b712dff386a322011ea4cfff89b240dac | |
parent | 2d1565377360833be414d49fc39c4d23f71a9f89 (diff) |
Fix a NULL inst crashing during loader_icd_scan
When checking for the portability driver field of driver manifests,
the loader did not check if inst was NULL first. Since this function
is called in pre-instance functions, this crashes the loader.
-rw-r--r-- | loader/loader.c | 2 | ||||
-rw-r--r-- | tests/loader_regression_tests.cpp | 65 |
2 files changed, 66 insertions, 1 deletions
diff --git a/loader/loader.c b/loader/loader.c index 3d95c0ac6..820e2e33f 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -3538,7 +3538,7 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t // Skip over ICD's which contain a true "is_portability_driver" value whenever the application doesn't enable // portability enumeration. item = cJSON_GetObjectItem(itemICD, "is_portability_driver"); - if (item != NULL && item->type == cJSON_True && !inst->portability_enumeration_enabled) { + if (item != NULL && item->type == cJSON_True && inst && !inst->portability_enumeration_enabled) { if (skipped_portability_drivers) *skipped_portability_drivers = true; cJSON_Delete(json); json = NULL; diff --git a/tests/loader_regression_tests.cpp b/tests/loader_regression_tests.cpp index 5a4b4e682..5ed718425 100644 --- a/tests/loader_regression_tests.cpp +++ b/tests/loader_regression_tests.cpp @@ -3254,3 +3254,68 @@ TEST(PortabilityICDConfiguration, PortabilityAndRegularICD) { dev_info_0.CheckCreate(phys_dev); } } + +TEST(PortabilityICDConfiguration, PortabilityAndRegularICDPreInstanceFunctions) { + FrameworkEnvironment env{}; + env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA))); + env.add_icd( + TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true))); + + Extension first_ext{"VK_EXT_validation_features"}; // known instance extensions + Extension second_ext{"VK_EXT_headless_surface"}; + env.get_test_icd().add_instance_extensions({first_ext, second_ext}); + + auto& driver0 = env.get_test_icd(0); + auto& driver1 = env.get_test_icd(1); + + driver0.physical_devices.emplace_back("physical_device_0"); + driver0.max_icd_interface_version = 1; + + driver1.physical_devices.emplace_back("portability_physical_device_1"); + driver1.max_icd_interface_version = 1; + { + // check that enumerating instance extensions work with a portability driver present + uint32_t extension_count = 0; + std::array<VkExtensionProperties, 5> extensions; + ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr)); + ASSERT_EQ(extension_count, 5U); // return debug report & debug utils + our two extensions + + ASSERT_EQ(VK_SUCCESS, + env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data())); + ASSERT_EQ(extension_count, 5U); + // loader always adds the debug report & debug utils extensions + ASSERT_TRUE(first_ext.extensionName == extensions[0].extensionName); + ASSERT_TRUE(second_ext.extensionName == extensions[1].extensionName); + ASSERT_TRUE(string_eq("VK_EXT_debug_report", extensions[2].extensionName)); + ASSERT_TRUE(string_eq("VK_EXT_debug_utils", extensions[3].extensionName)); + ASSERT_TRUE(string_eq("VK_KHR_portability_enumeration", extensions[4].extensionName)); + } + + const char* layer_name = "TestLayer"; + env.add_explicit_layer( + ManifestLayer{}.add_layer( + ManifestLayer::LayerDescription{}.set_name(layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)), + "test_layer.json"); + + InstWrapper inst{env.vulkan_functions}; + inst.create_info.add_layer(layer_name); + inst.CheckCreate(); + + VkPhysicalDevice phys_dev = inst.GetPhysDev(); + { // LayersMatch + + uint32_t layer_count = 0; + ASSERT_EQ(env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &layer_count, nullptr), VK_SUCCESS); + ASSERT_EQ(layer_count, 1U); + VkLayerProperties layer_props; + ASSERT_EQ(env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &layer_count, &layer_props), VK_SUCCESS); + ASSERT_EQ(layer_count, 1U); + ASSERT_TRUE(string_eq(layer_props.layerName, layer_name)); + } + { // Property count less than available + VkLayerProperties layer_props; + uint32_t layer_count = 0; + ASSERT_EQ(VK_INCOMPLETE, env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &layer_count, &layer_props)); + ASSERT_EQ(layer_count, 0U); + } +} |