diff options
author | Charles Giessen <charles@lunarg.com> | 2022-05-25 19:47:55 +0300 |
---|---|---|
committer | Charles Giessen <charles@lunarg.com> | 2022-05-26 00:49:32 +0300 |
commit | 08e2cb6c4f5d28ae811608a84550a723f5255c8d (patch) | |
tree | ae4d29ea19e4a50ac271c82820ae23302667470c | |
parent | ad05e878ee8309cfaac62f869f9d4f6431471321 (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 4447fb52d..8469550d3 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -3556,7 +3556,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(inst, 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); + } +} |