loader: Fix CTS failures in simulate_oom tests.
authorMark Young <marky@lunarg.com>
Fri, 19 Aug 2016 21:25:08 +0000 (15:25 -0600)
committerMark Young <marky@lunarg.com>
Fri, 19 Aug 2016 21:35:41 +0000 (15:35 -0600)
The simulate_oom tests continue the trend of testing what happens
when the user-provided allocators fail.  It validates two things:
1) That the loader returns the proper error message when this
occurs.
2) That the loader cleans up any allocated items prior to
returning.

Change-Id: Ic80ff4345e1f3524d5e11ce787b10c391a37d760

loader/loader.c
loader/loader.h
loader/trampoline.c

index 6b22893..485e387 100644 (file)
@@ -716,29 +716,29 @@ void loader_delete_layer_properties(const struct loader_instance *inst,
     }
 }
 
-static void loader_add_instance_extensions(
+static VkResult loader_add_instance_extensions(
     const struct loader_instance *inst,
     const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
     const char *lib_name, struct loader_extension_list *ext_list) {
     uint32_t i, count = 0;
     VkExtensionProperties *ext_props;
-    VkResult res;
+    VkResult res = VK_SUCCESS;
 
     if (!fp_get_props) {
         /* No EnumerateInstanceExtensionProperties defined */
-        return;
+        goto out;
     }
 
     res = fp_get_props(NULL, &count, NULL);
     if (res != VK_SUCCESS) {
         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                    "Error getting Instance extension count from %s", lib_name);
-        return;
+        goto out;
     }
 
     if (count == 0) {
         /* No ExtensionProperties to report */
-        return;
+        goto out;
     }
 
     ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
@@ -747,7 +747,7 @@ static void loader_add_instance_extensions(
     if (res != VK_SUCCESS) {
         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                    "Error getting Instance extensions from %s", lib_name);
-        return;
+        goto out;
     }
 
     for (i = 0; i < count; i++) {
@@ -763,11 +763,17 @@ static void loader_add_instance_extensions(
             loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
                        "Instance Extension: %s (%s) version %s",
                        ext_props[i].extensionName, lib_name, spec_version);
-            loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+            res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
+            if (res != VK_SUCCESS) {
+                loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+                           "Failed to add %s to Instance extension list",
+                           lib_name);
+                goto out;
+            }
         }
     }
-
-    return;
+out:
+    return res;
 }
 
 /*
@@ -782,9 +788,10 @@ loader_init_device_extensions(const struct loader_instance *inst,
     VkResult res;
     uint32_t i;
 
-    if (!loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
-                                  sizeof(VkExtensionProperties))) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
+                                   sizeof(VkExtensionProperties));
+    if (VK_SUCCESS != res) {
+        return res;
     }
 
     for (i = 0; i < count; i++) {
@@ -851,18 +858,18 @@ VkResult loader_add_device_extensions(const struct loader_instance *inst,
     return VK_SUCCESS;
 }
 
-bool loader_init_generic_list(const struct loader_instance *inst,
+VkResult loader_init_generic_list(const struct loader_instance *inst,
                               struct loader_generic_list *list_info,
                               size_t element_size) {
     list_info->capacity = 32 * element_size;
     list_info->list = loader_instance_heap_alloc(
         inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
     if (list_info->list == NULL) {
-        return false;
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
     }
     memset(list_info->list, 0, list_info->capacity);
     list_info->count = 0;
-    return true;
+    return VK_SUCCESS;
 }
 
 void loader_destroy_generic_list(const struct loader_instance *inst,
@@ -886,13 +893,13 @@ VkResult loader_add_to_ext_list(const struct loader_instance *inst,
     const VkExtensionProperties *cur_ext;
 
     if (ext_list->list == NULL || ext_list->capacity == 0) {
-        loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
+        VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
                                  sizeof(VkExtensionProperties));
+        if (VK_SUCCESS != res) {
+            return res;
+        }
     }
 
-    if (ext_list->list == NULL)
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-
     for (i = 0; i < prop_list_count; i++) {
         cur_ext = &props[i];
 
@@ -937,13 +944,14 @@ loader_add_to_dev_ext_list(const struct loader_instance *inst,
                            uint32_t entry_count, char **entrys) {
     uint32_t idx;
     if (ext_list->list == NULL || ext_list->capacity == 0) {
-        loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
-                                 sizeof(struct loader_dev_ext_props));
+        VkResult res = loader_init_generic_list(
+            inst, (struct loader_generic_list *)ext_list,
+            sizeof(struct loader_dev_ext_props));
+        if (VK_SUCCESS != res) {
+            return res;
+        }
     }
 
-    if (ext_list->list == NULL)
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
-
     // look for duplicates
     if (has_vk_dev_ext_property(props, ext_list)) {
         return VK_SUCCESS;
@@ -1177,7 +1185,6 @@ get_dev_extension_property(const char *name,
     return NULL;
 }
 
-
 /*
  * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
  * the extension must provide two entry points for the loader to use:
@@ -1198,26 +1205,42 @@ get_dev_extension_property(const char *name,
  * linked directly with the loader.
  */
 
-void loader_get_icd_loader_instance_extensions(
+VkResult loader_get_icd_loader_instance_extensions(
     const struct loader_instance *inst, struct loader_icd_libs *icd_libs,
     struct loader_extension_list *inst_exts) {
     struct loader_extension_list icd_exts;
+    VkResult res = VK_SUCCESS;
+
     loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
                "Build ICD instance extension list");
+
     // traverse scanned icd list adding non-duplicate extensions to the list
     for (uint32_t i = 0; i < icd_libs->count; i++) {
-        loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts,
-                                 sizeof(VkExtensionProperties));
-        loader_add_instance_extensions(
+        res = loader_init_generic_list(inst,
+                                       (struct loader_generic_list *)&icd_exts,
+                                       sizeof(VkExtensionProperties));
+        if (VK_SUCCESS != res) {
+            goto out;
+        }
+        res = loader_add_instance_extensions(
             inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
             icd_libs->list[i].lib_name, &icd_exts);
-        loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list);
+        if (VK_SUCCESS == res) {
+            res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count,
+                                         icd_exts.list);
+        }
         loader_destroy_generic_list(inst,
                                     (struct loader_generic_list *)&icd_exts);
+        if (VK_SUCCESS != res) {
+            goto out;
+        }
     };
 
     // Traverse loader's extensions, adding non-duplicate extensions to the list
     debug_report_add_instance_extensions(inst, inst_exts);
+
+out:
+    return res;
 }
 
 struct loader_icd *loader_get_icd_and_device(const VkDevice device,
@@ -1433,9 +1456,10 @@ static VkResult loader_scanned_icd_init(const struct loader_instance *inst,
     return err;
 }
 
-static void loader_scanned_icd_add(const struct loader_instance *inst,
-                                   struct loader_icd_libs *icd_libs,
-                                   const char *filename, uint32_t api_version) {
+static VkResult loader_scanned_icd_add(const struct loader_instance *inst,
+                                       struct loader_icd_libs *icd_libs,
+                                       const char *filename,
+                                       uint32_t api_version) {
     loader_platform_dl_handle handle;
     PFN_vkCreateInstance fp_create_inst;
     PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
@@ -1443,6 +1467,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
     PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version;
     struct loader_scanned_icds *new_node;
     uint32_t interface_vers;
+    VkResult res = VK_SUCCESS;
 
     /* TODO implement smarter opening/closing of libraries. For now this
      * function leaves libraries open and the scanned_icd_clear closes them */
@@ -1450,7 +1475,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
     if (!handle) {
         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                    loader_platform_open_library_error(filename));
-        return;
+        goto out;
     }
 
     // Get and settle on an ICD interface version
@@ -1463,7 +1488,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
                    "ICD (%s) doesn't support interface version compatible"
                    "with loader, skip this ICD %s",
                    filename);
-        return;
+        goto out;
     }
 
     fp_get_proc_addr =
@@ -1477,7 +1502,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                        loader_platform_get_proc_address_error(
                            "vk_icdGetInstanceProcAddr"));
-            return;
+            goto out;
         } else {
             loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                        "Using deprecated ICD interface of "
@@ -1492,7 +1517,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
                        "Couldn't get vkCreateInstance via dlsym/loadlibrary "
                        "for ICD %s",
                        filename);
-            return;
+            goto out;
         }
         fp_get_inst_ext_props = loader_platform_get_proc_address(
             handle, "vkEnumerateInstanceExtensionProperties");
@@ -1501,7 +1526,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
                        "Couldn't get vkEnumerateInstanceExtensionProperties "
                        "via dlsym/loadlibrary for ICD %s",
                        filename);
-            return;
+            goto out;
         }
     } else {
         // Use newer interface version 1 or later
@@ -1515,7 +1540,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
                        "Couldn't get vkCreateInstance via "
                        "vk_icdGetInstanceProcAddr for ICD %s",
                        filename);
-            return;
+            goto out;
         }
         fp_get_inst_ext_props =
             (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(
@@ -1525,7 +1550,7 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
                        "Couldn't get vkEnumerateInstanceExtensionProperties "
                        "via vk_icdGetInstanceProcAddr for ICD %s",
                        filename);
-            return;
+            goto out;
         }
     }
 
@@ -1537,9 +1562,10 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
             inst, icd_libs->list, icd_libs->capacity, icd_libs->capacity * 2,
             VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
         if (NULL == icd_libs->list) {
+            res = VK_ERROR_OUT_OF_HOST_MEMORY;
             loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                        "realloc failed on icd library list");
-            return;
+            goto out;
         }
         // double capacity
         icd_libs->capacity *= 2;
@@ -1556,12 +1582,17 @@ static void loader_scanned_icd_add(const struct loader_instance *inst,
     new_node->lib_name = (char *)loader_instance_heap_alloc(
         inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
     if (NULL == new_node->lib_name) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
         loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                    "Out of memory can't add icd");
-        return;
+        goto out;
     }
     strcpy(new_node->lib_name, filename);
     icd_libs->count++;
+
+out:
+
+    return res;
 }
 
 static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst,
@@ -1776,43 +1807,60 @@ static void loader_get_fullpath(const char *file, const char *dirs,
  * A pointer to a cJSON object representing the JSON parse tree.
  * This returned buffer should be freed by caller.
  */
-static cJSON *loader_get_json(const struct loader_instance *inst,
-                              const char *filename) {
-    FILE *file;
+static VkResult loader_get_json(const struct loader_instance *inst,
+                                const char *filename, cJSON **json) {
+    FILE *file = NULL;
     char *json_buf;
-    cJSON *json;
     size_t len;
+    VkResult res = VK_SUCCESS;
+
+    if (NULL == json) {
+        res = VK_ERROR_INITIALIZATION_FAILED;
+        goto out;
+    }
+
+    *json = NULL;
+
     file = fopen(filename, "rb");
     if (!file) {
+        res = VK_ERROR_INITIALIZATION_FAILED;
         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "Couldn't open JSON file %s", filename);
-        return NULL;
+        goto out;
     }
     fseek(file, 0, SEEK_END);
     len = ftell(file);
     fseek(file, 0, SEEK_SET);
     json_buf = (char *)loader_stack_alloc(len + 1);
     if (json_buf == NULL) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "Out of memory can't get JSON file");
-        fclose(file);
-        return NULL;
+        goto out;
     }
     if (fread(json_buf, sizeof(char), len, file) != len) {
+        res = VK_ERROR_INITIALIZATION_FAILED;
         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "fread failed can't get JSON file");
-        fclose(file);
-        return NULL;
+        goto out;
     }
-    fclose(file);
     json_buf[len] = '\0';
 
     // parse text from file
-    json = cJSON_Parse(json_buf);
-    if (json == NULL)
+    *json = cJSON_Parse(json_buf);
+    if (*json == NULL) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
         loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
                    "Can't parse JSON file %s", filename);
-    return json;
+        goto out;
+    }
+
+out:
+    if (NULL != file) {
+        fclose(file);
+    }
+
+    return res;
 }
 
 /**
@@ -2828,6 +2876,7 @@ VkResult loader_icd_scan(const struct loader_instance *inst,
     VkResult res = VK_SUCCESS;
     bool lockedMutex = false;
     cJSON *json = NULL;
+    uint32_t num_good_icds = 0;
 
     memset(&manifest_files, 0, sizeof(struct loader_manifest_files));
 
@@ -2851,22 +2900,29 @@ VkResult loader_icd_scan(const struct loader_instance *inst,
             continue;
         }
 
-        json = loader_get_json(inst, file_str);
-        if (!json) {
+        res = loader_get_json(inst, file_str, &json);
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+            break;
+        } else if (VK_SUCCESS != res || NULL == json) {
             continue;
         }
+
         cJSON *item, *itemICD;
         item = cJSON_GetObjectItem(json, "file_format_version");
         if (item == NULL) {
-            res = VK_ERROR_INITIALIZATION_FAILED;
-            goto out;
+            if (num_good_icds == 0) {
+                res = VK_ERROR_INITIALIZATION_FAILED;
+            }
+            continue;
         }
         char *file_vers = cJSON_Print(item);
         if (NULL == file_vers) {
             // Only reason the print can fail is if there was an allocation
             // issue
-            res = VK_ERROR_OUT_OF_HOST_MEMORY;
-            goto out;
+            if (num_good_icds == 0) {
+                res = VK_ERROR_OUT_OF_HOST_MEMORY;
+            }
+            continue;
         }
         loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
                    "Found manifest file %s, version %s", file_str, file_vers);
@@ -2899,6 +2955,9 @@ VkResult loader_icd_scan(const struct loader_instance *inst,
                                "Can't find \"library_path\" in ICD JSON file "
                                "%s, skipping",
                                file_str);
+                    if (num_good_icds == 0) {
+                        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+                    }
                     cJSON_Free(temp);
                     cJSON_Delete(json);
                     json = NULL;
@@ -2907,9 +2966,21 @@ VkResult loader_icd_scan(const struct loader_instance *inst,
                 // 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, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+                        "Can't allocate space for \"library_path\" in ICD "
+                        "JSON file %s, skipping",
+                        file_str);
+                    res = VK_ERROR_OUT_OF_HOST_MEMORY;
+                    cJSON_Free(temp);
+                    cJSON_Delete(json);
+                    json = NULL;
+                    goto out;
+                }
                 strcpy(library_path, &temp[1]);
                 cJSON_Free(temp);
-                if (!library_path || strlen(library_path) == 0) {
+                if (strlen(library_path) == 0) {
                     loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                                "Can't find \"library_path\" in ICD JSON file "
                                "%s, skipping",
@@ -2951,7 +3022,11 @@ VkResult loader_icd_scan(const struct loader_instance *inst,
                     vers = loader_make_version(temp);
                     cJSON_Free(temp);
                 }
-                loader_scanned_icd_add(inst, icds, fullpath, vers);
+                res = loader_scanned_icd_add(inst, icds, fullpath, vers);
+                if (VK_SUCCESS != res) {
+                    goto out;
+                }
+                num_good_icds++;
             } else {
                 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                            "Can't find \"library_path\" object in ICD JSON "
@@ -3033,8 +3108,10 @@ void loader_layer_scan(const struct loader_instance *inst,
                 continue;
 
             // parse file into JSON struct
-            json = loader_get_json(inst, file_str);
-            if (!json) {
+            VkResult res = loader_get_json(inst, file_str, &json);
+            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+                break;
+            } else if (VK_SUCCESS != res || NULL == json) {
                 continue;
             }
 
@@ -3096,8 +3173,10 @@ void loader_implicit_layer_scan(const struct loader_instance *inst,
         }
 
         // parse file into JSON struct
-        json = loader_get_json(inst, file_str);
-        if (!json) {
+        res = loader_get_json(inst, file_str, &json);
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+            break;
+        } else if (VK_SUCCESS != res || NULL == json) {
             continue;
         }
 
@@ -4017,7 +4096,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
     filtered_extension_names =
         loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
     if (!filtered_extension_names) {
-        return VK_ERROR_OUT_OF_HOST_MEMORY;
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
     }
     icd_create_info.ppEnabledExtensionNames =
         (const char *const *)filtered_extension_names;
@@ -4025,13 +4105,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
     for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
         icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
         if (NULL == icd) {
-            while (NULL != ptr_instance->icds) {
-                icd = ptr_instance->icds;
-                ptr_instance->icds = icd->next;
-                icd->DestroyInstance(icd->instance, pAllocator);
-                loader_icd_destroy(ptr_instance, icd, pAllocator);
-            }
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
+            res = VK_ERROR_OUT_OF_HOST_MEMORY;
+            goto out;
         }
         icd_create_info.enabledExtensionCount = 0;
         struct loader_extension_list icd_exts;
@@ -4040,13 +4115,28 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
                    "Build ICD instance extension list");
         // traverse scanned icd list adding non-duplicate extensions to the
         // list
-        loader_init_generic_list(ptr_instance,
+        res = loader_init_generic_list(ptr_instance,
                                  (struct loader_generic_list *)&icd_exts,
                                  sizeof(VkExtensionProperties));
-        loader_add_instance_extensions(
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+            // If out of memory, bail immediately.
+            goto out;
+        } else if (VK_SUCCESS != res) {
+            // Keep trying if there was some other error.
+            continue;
+        }
+
+        res = loader_add_instance_extensions(
             ptr_instance,
             icd->this_icd_lib->EnumerateInstanceExtensionProperties,
             icd->this_icd_lib->lib_name, &icd_exts);
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+            // If out of memory, bail immediately.
+            goto out;
+        } else if (VK_SUCCESS != res) {
+            // Keep trying if there was some other error.
+            continue;
+        }
 
         for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) {
             prop = get_extension_property(
@@ -4064,17 +4154,23 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
 
         res = ptr_instance->icd_libs.list[i].CreateInstance(
             &icd_create_info, pAllocator, &(icd->instance));
-        if (res == VK_SUCCESS)
-            success = loader_icd_init_entrys(
-                icd, icd->instance,
-                ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
+        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+            // If out of memory, bail immediately.
+            goto out;
+        } else if (VK_SUCCESS != res) {
+            // Keep trying if there was some other error.
+            loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+                       "ICD ignored: failed to CreateInstance in ICD %d", i);
+            continue;
+        }
 
-        if (res != VK_SUCCESS || !success) {
-            ptr_instance->icds = ptr_instance->icds->next;
-            loader_icd_destroy(ptr_instance, icd, pAllocator);
-            loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+        if (!loader_icd_init_entrys(
+                icd, icd->instance,
+                ptr_instance->icd_libs.list[i].GetInstanceProcAddr)) {
+            loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
                        "ICD ignored: failed to CreateInstance and find "
                        "entrypoints with ICD");
+            continue;
         }
     }
 
@@ -4083,15 +4179,24 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(
      * from it's initial value, the loader was unable to find
      * a suitable ICD.
      */
-    if (ptr_instance->icds == NULL) {
-        if (res == VK_SUCCESS) {
-            return VK_ERROR_INCOMPATIBLE_DRIVER;
-        } else {
-            return res;
+    if (VK_SUCCESS == res && ptr_instance->icds == NULL) {
+        res = VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
+out:
+
+    if (VK_SUCCESS != res) {
+        while (NULL != ptr_instance->icds) {
+            icd = ptr_instance->icds;
+            ptr_instance->icds = icd->next;
+            if (NULL != icd->instance) {
+                icd->DestroyInstance(icd->instance, pAllocator);
+            }
+            loader_icd_destroy(ptr_instance, icd, pAllocator);
         }
     }
 
-    return VK_SUCCESS;
+    return res;
 }
 
 VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(
@@ -4180,10 +4285,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(
         (const char *const *)filtered_extension_names;
 
     /* Get the physical device (ICD) extensions  */
-    if (!loader_init_generic_list(phys_dev->this_icd->this_instance,
+    res = loader_init_generic_list(phys_dev->this_icd->this_instance,
                                   (struct loader_generic_list *)&icd_exts,
-                                  sizeof(VkExtensionProperties))) {
-        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+                                  sizeof(VkExtensionProperties));
+    if (VK_SUCCESS != res) {
         goto out;
     }
 
@@ -4420,7 +4525,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
     uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
     struct loader_physical_device *phys_dev;
 
-    struct loader_layer_list implicit_layer_list;
+    struct loader_layer_list implicit_layer_list = {0};
+    struct loader_extension_list all_exts = {0};
+    struct loader_extension_list icd_exts = {0};
 
     assert(pLayerName == NULL || strlen(pLayerName) == 0);
 
@@ -4437,10 +4544,14 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
     /* get device extensions */
     res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL,
                                                   &icd_ext_count, pProperties);
-    if (res != VK_SUCCESS)
-        return res;
+    if (res != VK_SUCCESS) {
+        goto out;
+    }
 
-    loader_init_layer_list(icd->this_instance, &implicit_layer_list);
+    if (!loader_init_layer_list(icd->this_instance, &implicit_layer_list)) {
+        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+        goto out;
+    }
 
     loader_add_layer_implicit(
         icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
@@ -4450,22 +4561,24 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
      * it depends on results of environment variables (which can change).
      */
     if (pProperties != NULL) {
-        struct loader_extension_list icd_exts;
         /* initialize dev_extension list within the physicalDevice object */
         res = loader_init_device_extensions(icd->this_instance, phys_dev,
                                             icd_ext_count, pProperties,
                                             &icd_exts);
-        if (res != VK_SUCCESS)
-            return res;
+        if (res != VK_SUCCESS) {
+            goto out;
+        }
 
         /* we need to determine which implicit layers are active,
          * and then add their extensions. This can't be cached as
          * it depends on results of environment variables (which can
          * change).
          */
-        struct loader_extension_list all_exts = {0};
-        loader_add_to_ext_list(icd->this_instance, &all_exts, icd_exts.count,
-                               icd_exts.list);
+        res = loader_add_to_ext_list(icd->this_instance, &all_exts,
+                                     icd_exts.count, icd_exts.list);
+        if (res != VK_SUCCESS) {
+            goto out;
+        }
 
         loader_add_layer_implicit(
             icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
@@ -4475,10 +4588,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
             for (uint32_t j = 0;
                  j < implicit_layer_list.list[i].device_extension_list.count;
                  j++) {
-                loader_add_to_ext_list(icd->this_instance, &all_exts, 1,
-                                       &implicit_layer_list.list[i]
-                                            .device_extension_list.list[j]
-                                            .props);
+                res = loader_add_to_ext_list(icd->this_instance, &all_exts, 1,
+                                             &implicit_layer_list.list[i]
+                                                  .device_extension_list.list[j]
+                                                  .props);
+                if (res != VK_SUCCESS) {
+                    goto out;
+                }
             }
         }
         uint32_t capacity = *pPropertyCount;
@@ -4494,10 +4610,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
         } else {
             *pPropertyCount = all_exts.count;
         }
-        loader_destroy_generic_list(icd->this_instance,
-                                    (struct loader_generic_list *)&all_exts);
-        loader_destroy_generic_list(icd->this_instance,
-                                    (struct loader_generic_list *)&icd_exts);
     } else {
         /* just return the count; need to add in the count of implicit layer
          * extensions
@@ -4511,8 +4623,22 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
         res = VK_SUCCESS;
     }
 
-    loader_destroy_generic_list(
-        icd->this_instance, (struct loader_generic_list *)&implicit_layer_list);
+out:
+
+    if (NULL != implicit_layer_list.list) {
+        loader_destroy_generic_list(
+            icd->this_instance,
+            (struct loader_generic_list *)&implicit_layer_list);
+    }
+    if (NULL != all_exts.list) {
+        loader_destroy_generic_list(icd->this_instance,
+                                    (struct loader_generic_list *)&all_exts);
+    }
+    if (NULL != icd_exts.list) {
+        loader_destroy_generic_list(icd->this_instance,
+                                    (struct loader_generic_list *)&icd_exts);
+    }
+
     return res;
 }
 
index cb5f206..5a1515e 100644 (file)
@@ -449,9 +449,9 @@ VkResult loader_add_device_extensions(const struct loader_instance *inst,
                                       VkPhysicalDevice physical_device,
                                       const char *lib_name,
                                       struct loader_extension_list *ext_list);
-bool loader_init_generic_list(const struct loader_instance *inst,
-                              struct loader_generic_list *list_info,
-                              size_t element_size);
+VkResult loader_init_generic_list(const struct loader_instance *inst,
+                                  struct loader_generic_list *list_info,
+                                  size_t element_size);
 void loader_destroy_generic_list(const struct loader_instance *inst,
                                  struct loader_generic_list *list);
 void loader_destroy_layer_list(const struct loader_instance *inst,
@@ -489,7 +489,7 @@ void loader_layer_scan(const struct loader_instance *inst,
                        struct loader_layer_list *instance_layers);
 void loader_implicit_layer_scan(const struct loader_instance *inst,
                                 struct loader_layer_list *instance_layers);
-void loader_get_icd_loader_instance_extensions(
+VkResult loader_get_icd_loader_instance_extensions(
     const struct loader_instance *inst, struct loader_icd_libs *icd_libs,
     struct loader_extension_list *inst_exts);
 struct loader_icd *loader_get_icd_and_device(const VkDevice device,
index e2c3205..b0f6138 100644 (file)
@@ -177,8 +177,11 @@ vkEnumerateInstanceExtensionProperties(const char *pLayerName,
             goto out;
         }
         /* get extensions from all ICD's, merge so no duplicates */
-        loader_get_icd_loader_instance_extensions(NULL, &icd_libs,
-                                                  &local_ext_list);
+        res = loader_get_icd_loader_instance_extensions(NULL, &icd_libs,
+                                                        &local_ext_list);
+        if (VK_SUCCESS != res) {
+            goto out;
+        }
         loader_scanned_icd_clear(NULL, &icd_libs);
 
         // Append implicit layers.
@@ -366,8 +369,11 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
     }
 
     /* get extensions from all ICD's, merge so no duplicates, then validate */
-    loader_get_icd_loader_instance_extensions(
+    res = loader_get_icd_loader_instance_extensions(
         ptr_instance, &ptr_instance->icd_libs, &ptr_instance->ext_list);
+    if (res != VK_SUCCESS) {
+        goto out;
+    }
     res = loader_validate_instance_extensions(
         ptr_instance, &ptr_instance->ext_list,
         &ptr_instance->instance_layer_list, &ici);
@@ -658,9 +664,10 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
     /* Get the physical device (ICD) extensions  */
     struct loader_extension_list icd_exts;
     icd_exts.list = NULL;
-    if (!loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts,
-                                  sizeof(VkExtensionProperties))) {
-        res = VK_ERROR_OUT_OF_HOST_MEMORY;
+    res =
+        loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts,
+                                 sizeof(VkExtensionProperties));
+    if (VK_SUCCESS != res) {
         goto out;
     }