Refactor loader_icd_scan()
authorCharles Giessen <charles@lunarg.com>
Wed, 24 Aug 2022 23:04:38 +0000 (17:04 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Thu, 1 Sep 2022 19:13:14 +0000 (13:13 -0600)
Put all of the parsing for ICD Manifest data into a separate function.
This cleans it up by not requiring manual tracking of allocated resources
while parsing, and allow much saner 'skipping' of incorrect ICD's.

This commit also addresses an issue where OOM during ICD parsing wasn't
immediately ending parsing and returning.

loader/loader.c
tests/loader_alloc_callback_tests.cpp
tests/loader_regression_tests.cpp
tests/loader_version_tests.cpp

index 6e48e4466b50bd521cd38fc05f6d7469a47631c6..ed0607de587d175fa1f8f1f6521a344225aa0f9e 100644 (file)
@@ -3314,9 +3314,177 @@ out:
     return res;
 }
 
-void loader_init_icd_lib_list() {}
+struct ICDManifestInfo {
+    char full_library_path[MAX_STRING_SIZE];
+    uint32_t version;
+};
+
+VkResult loader_parse_icd_manifest(const struct loader_instance *inst, char *file_str, struct ICDManifestInfo *icd,
+                                   bool *skipped_portability_drivers) {
+    VkResult res = VK_SUCCESS;
+    cJSON *json = NULL;
+    cJSON *item = NULL, *itemICD = NULL;
+
+    char *file_vers_str = NULL;
+    char *library_path = NULL;
+    char *library_arch_str = NULL;
+    char *version_str = NULL;
+
+    if (file_str == NULL) {
+        goto out;
+    }
+
+    res = loader_get_json(inst, file_str, &json);
+    if (res != VK_SUCCESS || NULL == json) {
+        goto out;
+    }
+
+    item = cJSON_GetObjectItem(json, "file_format_version");
+    if (item == NULL) {
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: ICD JSON %s does not have a \'file_format_version\' field. Skipping ICD JSON.",
+                   file_str);
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+
+    file_vers_str = cJSON_Print(item);
+    if (NULL == file_vers_str) {
+        // Only reason the print can fail is if there was an allocation issue
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'file_format_version\' field. Skipping ICD JSON",
+                   file_str);
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers_str);
+
+    // Get the version of the driver manifest
+    loader_api_version json_file_version = loader_make_full_version(loader_parse_version_string(file_vers_str));
+
+    // Loader only knows versions 1.0.0 and 1.0.1, anything above it is unknown
+    if (loader_check_version_meets_required(loader_combine_version(1, 0, 2), json_file_version)) {
+        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: %s has unknown icd manifest file version %d.%d.%d. May cause errors.", file_str,
+                   json_file_version.major, json_file_version.minor, json_file_version.patch);
+    }
+
+    itemICD = cJSON_GetObjectItem(json, "ICD");
+    if (itemICD == NULL) {
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: Can not find \'ICD\' object in ICD JSON file %s. Skipping ICD JSON", file_str);
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+
+    item = cJSON_GetObjectItem(itemICD, "library_path");
+    if (item == NULL) {
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: Failed to find \'library_path\' object in ICD JSON file %s. Skipping ICD JSON.",
+                   file_str);
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+    library_path = cJSON_Print(item);
+    if (!library_path || strlen(library_path) == 0) {
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'library_path\' field. Skipping ICD JSON.", file_str);
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    size_t library_path_len = strlen(library_path);
+    // cJSON prints everything with quotes so they need to be removed.
+    // move every char forward one, so the leading quote is replaced.
+    memmove(library_path, &library_path[1], library_path_len - 2);
+    // replace end quote with null terminator
+    library_path[library_path_len - 2] = '\0';
+
+    if (strlen(library_path) == 0) {
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: ICD JSON %s \'library_path\' field is empty. Skipping ICD JSON.", file_str);
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+
+    // Print out the paths being searched if debugging is enabled
+    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Searching for ICD drivers named %s", library_path);
+    if (loader_platform_is_path(library_path)) {
+        // a relative or absolute path
+        char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
+        char *rel_base;
+        strcpy(name_copy, file_str);
+        rel_base = loader_platform_dirname(name_copy);
+        loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, &icd->full_library_path[0]);
+    } else {
+// a filename which is assumed in a system directory
+#if defined(DEFAULT_VK_DRIVERS_PATH)
+        loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, MAX_STRING_SIZE, &icd->full_library_path[0]);
+#else
+        loader_get_fullpath(library_path, "", MAX_STRING_SIZE, &icd->full_library_path[0]);
+#endif
+    }
+
+    item = cJSON_GetObjectItem(itemICD, "api_version");
+    if (item == NULL) {
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: ICD JSON %s does not have an \'api_version\' field. Skipping ICD JSON.", file_str);
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+    version_str = cJSON_Print(item);
+    if (NULL == version_str) {
+        // Only reason the print can fail is if there was an allocation issue
+        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'api_version\' field. Skipping ICD JSON.", file_str);
 
-void loader_destroy_icd_lib_list() {}
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
+    icd->version = loader_parse_version_string(version_str);
+
+    if (VK_API_VERSION_VARIANT(icd->version) != 0) {
+        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                   "loader_parse_icd_manifest: Driver's ICD JSON %s \'api_version\' field contains a non-zero variant value of %d. "
+                   " Skipping ICD JSON.",
+                   file_str, VK_API_VERSION_VARIANT(icd->version));
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+
+    // 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 && !inst->portability_enumeration_enabled) {
+        if (skipped_portability_drivers) {
+            *skipped_portability_drivers = true;
+        }
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+        goto out;
+    }
+
+    item = cJSON_GetObjectItem(itemICD, "library_arch");
+    if (item != NULL) {
+        library_arch_str = cJSON_Print(item);
+        if (NULL != library_arch_str) {
+            // cJSON includes the quotes by default, so we need to look for those here
+            if ((strncmp(library_arch_str, "\"32\"", 4) == 0 && sizeof(void *) != 4) ||
+                (strncmp(library_arch_str, "\"64\"", 4) == 0 && sizeof(void *) != 8)) {
+                loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
+                           "loader_parse_icd_manifest: Driver library architecture doesn't match the current running "
+                           "architecture, skipping this driver");
+                res = VK_ERROR_INCOMPATIBLE_DRIVER;
+                goto out;
+            }
+        }
+    }
+out:
+    cJSON_Delete(json);
+    loader_instance_heap_free(inst, file_vers_str);
+    loader_instance_heap_free(inst, library_path);
+    loader_instance_heap_free(inst, version_str);
+    loader_instance_heap_free(inst, library_arch_str);
+    return res;
+}
 
 // Try to find the Vulkan ICD driver(s).
 //
@@ -3334,13 +3502,9 @@ void loader_destroy_icd_lib_list() {}
 // (on result == VK_SUCCESS) a list of icds that were discovered
 VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
                          bool *skipped_portability_drivers) {
-    char *file_str;
-    loader_api_version json_file_version = {0, 0, 0};
     struct loader_data_files manifest_files;
     VkResult res = VK_SUCCESS;
     bool lockedMutex = false;
-    cJSON *json = NULL;
-    uint32_t num_good_icds = 0;
 
     memset(&manifest_files, 0, sizeof(struct loader_data_files));
 
@@ -3348,254 +3512,57 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
     if (VK_SUCCESS != res) {
         goto out;
     }
+
     // Get a list of manifest files for ICDs
     res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
     if (VK_SUCCESS != res || manifest_files.count == 0) {
         goto out;
     }
+
     loader_platform_thread_lock_mutex(&loader_json_lock);
     lockedMutex = true;
     for (uint32_t i = 0; i < manifest_files.count; i++) {
-        file_str = manifest_files.filename_list[i];
-        if (file_str == NULL) {
-            continue;
-        }
-
-        VkResult temp_res = loader_get_json(inst, file_str, &json);
-        if (NULL == json || temp_res != VK_SUCCESS) {
-            if (NULL != json) {
-                cJSON_Delete(json);
-                json = NULL;
-            }
-            // If we haven't already found an ICD, copy this result to
-            // the returned result.
-            if (num_good_icds == 0) {
-                res = temp_res;
-            }
-            if (temp_res == VK_ERROR_OUT_OF_HOST_MEMORY) {
-                res = VK_ERROR_OUT_OF_HOST_MEMORY;
-                break;
-            } else {
-                continue;
-            }
-        }
-        res = temp_res;
-
-        cJSON *item, *itemICD;
-        item = cJSON_GetObjectItem(json, "file_format_version");
-        if (item == NULL) {
-            if (num_good_icds == 0) {
-                res = VK_ERROR_INITIALIZATION_FAILED;
-            }
-            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                       "loader_icd_scan: ICD JSON %s does not have a \'file_format_version\' field. Skipping ICD JSON.", file_str);
-            cJSON_Delete(json);
-            json = NULL;
-            continue;
-        }
-
-        char *file_vers = cJSON_Print(item);
-        if (NULL == file_vers) {
-            // Only reason the print can fail is if there was an allocation issue
-            if (num_good_icds == 0) {
-                res = VK_ERROR_OUT_OF_HOST_MEMORY;
-            }
-            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                       "loader_icd_scan: Failed retrieving ICD JSON %s \'file_format_version\' field.  Skipping ICD JSON",
-                       file_str);
-            cJSON_Delete(json);
-            json = NULL;
+        VkResult icd_res = VK_SUCCESS;
+        struct ICDManifestInfo icd;
+        memset(&icd, 0, sizeof(struct ICDManifestInfo));
+        icd_res = loader_parse_icd_manifest(inst, manifest_files.filename_list[i], &icd, skipped_portability_drivers);
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
+            res = icd_res;
+            goto out;
+        } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) {
             continue;
         }
-        loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers);
-
-        // Get the version of the driver manifest
-        json_file_version = loader_make_full_version(loader_parse_version_string(file_vers));
 
-        // Loader only knows versions 1.0.0 and 1.0.1, anything above it is unknown
-        if (loader_check_version_meets_required(loader_combine_version(1, 0, 2), json_file_version)) {
-            loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                       "loader_icd_scan: %s has unknown icd manifest file version %d.%d.%d. May cause errors.", file_str,
-                       json_file_version.major, json_file_version.minor, json_file_version.patch);
-        }
-        loader_instance_heap_free(inst, file_vers);
-
-        itemICD = cJSON_GetObjectItem(json, "ICD");
-        if (itemICD != NULL) {
-            item = cJSON_GetObjectItem(itemICD, "library_path");
-            if (item != NULL) {
-                char *temp = cJSON_Print(item);
-                if (!temp || strlen(temp) == 0) {
-                    if (num_good_icds == 0) {
-                        res = VK_ERROR_OUT_OF_HOST_MEMORY;
-                    }
-                    loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                               "loader_icd_scan: Failed retrieving ICD JSON %s \'library_path\' field.  Skipping ICD JSON.",
-                               file_str);
-                    loader_instance_heap_free(inst, temp);
-                    cJSON_Delete(json);
-                    json = NULL;
-                    continue;
-                }
-                // strip out extra quotes
-                temp[strlen(temp) - 1] = '\0';
-                char *library_path = loader_stack_alloc(strlen(temp) + 1);
-                if (NULL == library_path) {
-                    loader_log(
-                        inst, VULKAN_LOADER_ERROR_BIT, 0,
-                        "loader_icd_scan: Failed to allocate space for ICD JSON %s \'library_path\' value.  Skipping ICD JSON.",
-                        file_str);
-                    res = VK_ERROR_OUT_OF_HOST_MEMORY;
-                    loader_instance_heap_free(inst, temp);
-                    cJSON_Delete(json);
-                    json = NULL;
-                    goto out;
-                }
-                strcpy(library_path, &temp[1]);
-                loader_instance_heap_free(inst, temp);
-                if (strlen(library_path) == 0) {
-                    loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                               "loader_icd_scan: ICD JSON %s \'library_path\' field is empty.  Skipping ICD JSON.", file_str);
-                    cJSON_Delete(json);
-                    json = NULL;
-                    continue;
-                }
-                char fullpath[MAX_STRING_SIZE];
-                // Print out the paths being searched if debugging is enabled
-                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Searching for ICD drivers named %s", library_path);
-                if (loader_platform_is_path(library_path)) {
-                    // a relative or absolute path
-                    char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
-                    char *rel_base;
-                    strcpy(name_copy, file_str);
-                    rel_base = loader_platform_dirname(name_copy);
-                    loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
-                } else {
-// a filename which is assumed in a system directory
-#if defined(DEFAULT_VK_DRIVERS_PATH)
-                    loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
-#else
-                    loader_get_fullpath(library_path, "", sizeof(fullpath), fullpath);
-#endif
+        enum loader_layer_library_status lib_status;
+        icd_res = loader_scanned_icd_add(inst, icd_tramp_list, icd.full_library_path, icd.version, &lib_status);
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
+            res = icd_res;
+            goto out;
+        } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) {
+            switch (lib_status) {
+                case LOADER_LAYER_LIB_NOT_LOADED:
+                case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD:
+                    loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+                               "loader_icd_scan: Failed loading library associated with ICD JSON %s. Ignoring this JSON",
+                               icd.full_library_path);
+                    break;
+                case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE: {
+                    loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Requested layer %s was wrong bit-type. Ignoring this JSON",
+                               icd.full_library_path);
+                    break;
                 }
-
-                uint32_t vers = 0;
-                item = cJSON_GetObjectItem(itemICD, "api_version");
-                if (item != NULL) {
-                    temp = cJSON_Print(item);
-                    if (NULL == temp) {
-                        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                                   "loader_icd_scan: Failed retrieving ICD JSON %s \'api_version\' field.  Skipping ICD JSON.",
-                                   file_str);
-
-                        // Only reason the print can fail is if there was an
-                        // allocation issue
-                        if (num_good_icds == 0) {
-                            res = VK_ERROR_OUT_OF_HOST_MEMORY;
-                        }
-
-                        loader_instance_heap_free(inst, temp);
-                        cJSON_Delete(json);
-                        json = NULL;
-                        continue;
-                    }
-                    vers = loader_parse_version_string(temp);
-                    loader_instance_heap_free(inst, temp);
-                } else {
+                case LOADER_LAYER_LIB_SUCCESS_LOADED:
+                    // Shouldn't be able to reach this but if it is, best to report a debug
                     loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                               "loader_icd_scan: ICD JSON %s does not have an \'api_version\' field.", file_str);
-                }
-                if (VK_API_VERSION_VARIANT(vers) != 0) {
-                    loader_log(
-                        inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                        "loader_icd_scan: Driver's ICD JSON %s \'api_version\' field contains a non-zero variant value of %d. "
-                        " Skipping ICD JSON.",
-                        file_str, VK_API_VERSION_VARIANT(vers));
-                    cJSON_Delete(json);
-                    json = NULL;
-                    continue;
-                }
-                // 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 && !inst->portability_enumeration_enabled) {
-                    if (skipped_portability_drivers) *skipped_portability_drivers = true;
-                    cJSON_Delete(json);
-                    json = NULL;
-                    continue;
-                }
-
-                item = cJSON_GetObjectItem(itemICD, "library_arch");
-                if (item != NULL) {
-                    temp = cJSON_Print(item);
-                    if (NULL != temp) {
-                        // cJSON includes the quotes by default, so we need to look for those here
-                        if ((strncmp(temp, "\"32\"", 4) == 0 && sizeof(void *) != 4) ||
-                            (strncmp(temp, "\"64\"", 4) == 0 && sizeof(void *) != 8)) {
-                            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
-                                       "loader_icd_scan: Driver library architecture doesn't match the current running "
-                                       "architecture, skipping this driver");
-                            loader_instance_heap_free(inst, temp);
-                            cJSON_Delete(json);
-                            json = NULL;
-                            continue;
-                        }
-                    }
-                    loader_instance_heap_free(inst, temp);
-                }
-
-                VkResult icd_add_res = VK_SUCCESS;
-                enum loader_layer_library_status lib_status;
-                icd_add_res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers, &lib_status);
-                if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_add_res) {
-                    res = icd_add_res;
-                    goto out;
-                } else if (VK_SUCCESS != icd_add_res) {
-                    switch (lib_status) {
-                        case LOADER_LAYER_LIB_NOT_LOADED:
-                        case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD:
-                            loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                                       "loader_icd_scan: Failed loading library associated with ICD JSON %s.Ignoring this JSON",
-                                       fullpath);
-                            break;
-                        case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE: {
-                            loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0,
-                                       "Requested layer %s was wrong bit-type. Ignoring this JSON", fullpath);
-                            break;
-                        }
-                        case LOADER_LAYER_LIB_SUCCESS_LOADED:
-                            // Shouldn't be able to reach this but if it is, best to report a debug
-                            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                                       "Shouldn't reach this. A valid version of requested ICD %s was loaded but something bad "
-                                       "happened afterwards.",
-                                       fullpath);
-                            break;
-                    }
-                    cJSON_Delete(json);
-                    json = NULL;
-                    continue;
-                }
-                num_good_icds++;
-            } else {
-                loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                           "loader_icd_scan: Failed to find \'library_path\' object in ICD JSON file %s.  Skipping ICD JSON.",
-                           file_str);
+                               "Shouldn't reach this. A valid version of requested ICD %s was loaded but something bad "
+                               "happened afterwards.",
+                               icd.full_library_path);
+                    break;
             }
-        } else {
-            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
-                       "loader_icd_scan: Can not find \'ICD\' object in ICD JSON file %s.  Skipping ICD JSON", file_str);
         }
-
-        cJSON_Delete(json);
-        json = NULL;
     }
 
 out:
-
-    if (NULL != json) {
-        cJSON_Delete(json);
-    }
-
     if (NULL != manifest_files.filename_list) {
         for (uint32_t i = 0; i < manifest_files.count; i++) {
             loader_instance_heap_free(inst, manifest_files.filename_list[i]);
index 851b876a8d629e9a1d8a1019696e768cf5b25d89..56a20dd2c9a4fd1b844af7a3901f62b3c185d525 100644 (file)
@@ -435,6 +435,41 @@ TEST(Allocation, CreateInstanceIntentionalAllocFail) {
     }
 }
 
+// Test failure during vkCreateInstance to make sure we don't leak memory if
+// one of the out-of-memory conditions trigger.
+TEST(Allocation, DriverEnvVarIntentionalAllocFail) {
+    FrameworkEnvironment env{};
+    env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_discovery_type(ManifestDiscoveryType::env_var));
+
+    const char* layer_name = "VkLayerImplicit0";
+    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+                                                         .set_name(layer_name)
+                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+                                                         .set_disable_environment("DISABLE_ENV")),
+                           "test_layer.json");
+    env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
+
+    auto driver_files = get_env_var("VK_DRIVER_FILES");
+    driver_files += OS_ENV_VAR_LIST_SEPARATOR;
+    driver_files += (fs::path("totally_made_up") / "path_to_fake" / "jason_file.json").str();
+    set_env_var("VK_DRIVER_FILES", driver_files);
+
+    size_t fail_index = 66;  // 0
+    VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
+    while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) {
+        MemoryTracker tracker(MemoryTrackerSettings{false, 0, true, fail_index});
+
+        VkInstance instance;
+        InstanceCreateInfo inst_create_info{};
+        result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance);
+        if (result == VK_SUCCESS) {
+            env.vulkan_functions.vkDestroyInstance(instance, tracker.get());
+        }
+        ASSERT_TRUE(tracker.empty());
+        fail_index++;
+    }
+}
+
 // Test failure during vkCreateDevice to make sure we don't leak memory if
 // one of the out-of-memory conditions trigger.
 // Use 2 physical devices so that anything which copies a list of devices item by item
index 5e30ad132eff1fd4f8ef0d5580afe50574941dd6..32070e38a12a0e90df2b523f067b980fe88256bf 100644 (file)
@@ -1314,8 +1314,9 @@ TEST(TryLoadWrongBinaries, WrongArchDriver) {
     InstWrapper inst{env.vulkan_functions};
     FillDebugUtilsCreateDetails(inst.create_info, log);
     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
-    ASSERT_TRUE(log.find(
-        "loader_icd_scan: Driver library architecture doesn't match the current running architecture, skipping this driver"));
+    ASSERT_TRUE(
+        log.find("loader_parse_icd_manifest: Driver library architecture doesn't match the current running architecture, skipping "
+                 "this driver"));
 }
 
 TEST(TryLoadWrongBinaries, WrongArchLayer) {
index d621c24d6f6646d500cc8ae418864fcbf6b6a9fd..04c22acea7404effe041d9347d0b915553feedb0 100644 (file)
@@ -831,7 +831,7 @@ TEST(DriverManifest, NonVulkanVariant) {
     inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
     FillDebugUtilsCreateDetails(inst.create_info, log);
     inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
-    ASSERT_TRUE(log.find("loader_icd_scan: Driver's ICD JSON "));
+    ASSERT_TRUE(log.find("loader_parse_icd_manifest: Driver's ICD JSON "));
     // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
     ASSERT_TRUE(log.find("\'api_version\' field contains a non-zero variant value of 1.  Skipping ICD JSON."));
 }
@@ -890,7 +890,7 @@ TEST(DriverManifest, UnknownManifestVersion) {
     inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
     FillDebugUtilsCreateDetails(inst.create_info, log);
     inst.CheckCreate();
-    ASSERT_TRUE(log.find("loader_icd_scan: "));
+    ASSERT_TRUE(log.find("loader_parse_icd_manifest: "));
     // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
     ASSERT_TRUE(log.find("has unknown icd manifest file version 3.2.1. May cause errors."));
 }