loader: Null-terminated string checks
diff --git a/loader/loader.c b/loader/loader.c
index 1e213e1..df1c219 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -3234,29 +3234,45 @@
     return res;
 }
 
-VkResult loader_validate_layers(const uint32_t layer_count,
+VkResult loader_validate_layers(const struct loader_instance *inst,
+                                const uint32_t layer_count,
                                 const char *const *ppEnabledLayerNames,
                                 const struct loader_layer_list *list) {
     struct loader_layer_properties *prop;
 
     for (uint32_t i = 0; i < layer_count; i++) {
+        VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
+        if (result != VK_STRING_ERROR_NONE) {
+            loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+                "Loader: Device ppEnabledLayerNames contains string that is too long or is badly formed");
+            return VK_ERROR_LAYER_NOT_PRESENT;
+        }
+
         prop = loader_get_layer_property(ppEnabledLayerNames[i], list);
         if (!prop) {
             return VK_ERROR_LAYER_NOT_PRESENT;
         }
     }
-
     return VK_SUCCESS;
 }
 
 VkResult loader_validate_instance_extensions(
+    const struct loader_instance *inst,
     const struct loader_extension_list *icd_exts,
     const struct loader_layer_list *instance_layer,
     const VkInstanceCreateInfo *pCreateInfo) {
+
     VkExtensionProperties *extension_prop;
     struct loader_layer_properties *layer_prop;
 
     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+        VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
+        if (result != VK_STRING_ERROR_NONE) {
+            loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+                "Loader: Instance ppEnabledExtensionNames contains string that is too long or is badly formed");
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+
         extension_prop = get_extension_property(
             pCreateInfo->ppEnabledExtensionNames[i], icd_exts);
 
@@ -3304,6 +3320,14 @@
     struct loader_layer_properties *layer_prop;
 
     for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+
+        VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
+        if (result != VK_STRING_ERROR_NONE) {
+            loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+                "Loader: Device ppEnabledExtensionNames contains string that is too long or is badly formed");
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+
         const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
         extension_prop = get_extension_property(
             extension_name, &phys_dev->device_extension_cache);
@@ -3720,7 +3744,8 @@
 
     /* validate any app enabled layers are available */
     if (pCreateInfo->enabledLayerCount > 0) {
-        res = loader_validate_layers(pCreateInfo->enabledLayerCount,
+        res = loader_validate_layers(inst,
+                                     pCreateInfo->enabledLayerCount,
                                      pCreateInfo->ppEnabledLayerNames,
                                      &inst->device_layer_list);
         if (res != VK_SUCCESS) {
@@ -3902,12 +3927,17 @@
 
     /* get layer libraries if needed */
     if (pLayerName && strlen(pLayerName) != 0) {
-        loader_layer_scan(NULL, &instance_layers, NULL);
-        for (uint32_t i = 0; i < instance_layers.count; i++) {
-            struct loader_layer_properties *props = &instance_layers.list[i];
-            if (strcmp(props->info.layerName, pLayerName) == 0) {
-                global_ext_list = &props->instance_extension_list;
+        if (vk_string_validate(MaxLoaderStringLength, pLayerName) == VK_STRING_ERROR_NONE) {
+            loader_layer_scan(NULL, &instance_layers, NULL);
+            for (uint32_t i = 0; i < instance_layers.count; i++) {
+                struct loader_layer_properties *props = &instance_layers.list[i];
+                if (strcmp(props->info.layerName, pLayerName) == 0) {
+                   global_ext_list = &props->instance_extension_list;
+                }
             }
+        } else {
+            assert(VK_FALSE && "vkEnumerateInstanceExtensionProperties:  pLayerName is too long or is badly formed");
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
         }
     } else {
         /* Scan/discover all ICD libraries */
@@ -3981,6 +4011,7 @@
         memcpy(&pProperties[i], &instance_layer_list.list[i].info,
                sizeof(VkLayerProperties));
     }
+
     *pPropertyCount = copy_size;
     loader_destroy_layer_list(NULL, &instance_layer_list);
 
@@ -4008,31 +4039,36 @@
 
     /* get layer libraries if needed */
     if (pLayerName && strlen(pLayerName) != 0) {
-        for (uint32_t i = 0;
-             i < phys_dev->this_instance->device_layer_list.count; i++) {
-            struct loader_layer_properties *props =
-                &phys_dev->this_instance->device_layer_list.list[i];
-            if (strcmp(props->info.layerName, pLayerName) == 0) {
-                dev_ext_list = &props->device_extension_list;
+        if (vk_string_validate(MaxLoaderStringLength, pLayerName) == VK_STRING_ERROR_NONE) {
+            for (uint32_t i = 0;
+                i < phys_dev->this_instance->device_layer_list.count; i++) {
+                struct loader_layer_properties *props =
+                    &phys_dev->this_instance->device_layer_list.list[i];
+                if (strcmp(props->info.layerName, pLayerName) == 0) {
+                   dev_ext_list = &props->device_extension_list;
+                }
             }
-        }
-        count = (dev_ext_list == NULL) ? 0 : dev_ext_list->count;
-        if (pProperties == NULL) {
-            *pPropertyCount = count;
-            return VK_SUCCESS;
-        }
+            count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
+            if (pProperties == NULL) {
+                *pPropertyCount = count;
+                return VK_SUCCESS;
+            }
 
-        copy_size = *pPropertyCount < count ? *pPropertyCount : count;
-        for (uint32_t i = 0; i < copy_size; i++) {
-            memcpy(&pProperties[i], &dev_ext_list->list[i].props,
-                   sizeof(VkExtensionProperties));
-        }
-        *pPropertyCount = copy_size;
+            copy_size = *pPropertyCount < count ? *pPropertyCount : count;
+            for (uint32_t i = 0; i < copy_size; i++) {
+                memcpy(&pProperties[i], &dev_ext_list->list[i].props,
+                       sizeof(VkExtensionProperties));
+            }
+            *pPropertyCount = copy_size;
 
-        if (copy_size < count) {
-            return VK_INCOMPLETE;
+            if (copy_size < count) {
+                return VK_INCOMPLETE;
+            }
+        } else {
+            loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+                "vkEnumerateDeviceExtensionProperties:  pLayerName is too long or is badly formed");
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
         }
-
         return VK_SUCCESS;
     } else {
         /* this case is during the call down the instance chain with pLayerName
@@ -4040,6 +4076,7 @@
         struct loader_icd *icd = phys_dev->this_icd;
         uint32_t icd_ext_count = *pPropertyCount;
         VkResult res;
+
         /* get device extensions */
         res = icd->EnumerateDeviceExtensionProperties(
             phys_dev->phys_dev, NULL, &icd_ext_count, pProperties);
@@ -4159,3 +4196,40 @@
 
     return VK_SUCCESS;
 }
+
+VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8)
+{
+    VkStringErrorFlags result = VK_STRING_ERROR_NONE;
+    int                num_char_bytes;
+    int                i,j;
+
+    for (i = 0; i < max_length; i++)
+    {
+        if (utf8[i] == 0) {
+            break;
+        } else if ((utf8[i] > 0x20) && (utf8[i] < 0x7f)) {
+            num_char_bytes = 0;
+        } else if ((utf8[i] & UTF8_ONE_BYTE_MASK)   == UTF8_ONE_BYTE_CODE) {
+            num_char_bytes = 1;
+        } else if ((utf8[i] & UTF8_TWO_BYTE_MASK)   == UTF8_TWO_BYTE_CODE)   {
+            num_char_bytes = 2;
+        } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
+            num_char_bytes = 3;
+        } else {
+            result = VK_STRING_ERROR_BAD_DATA;
+        }
+
+        // Validate the following num_char_bytes of data
+        for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
+            if (++i == max_length) {
+                result |= VK_STRING_ERROR_LENGTH;
+                break;
+            }
+            if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
+                result |= VK_STRING_ERROR_BAD_DATA;
+            }
+        }
+    }
+    return result;
+}
+
diff --git a/loader/loader.h b/loader/loader.h
index ac20d74..2c89460 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -72,6 +72,24 @@
         0xc, // both instance and device layer, bitwise
 };
 
+
+typedef enum VkStringErrorFlagBits {
+    VK_STRING_ERROR_NONE      = 0x00000000,
+    VK_STRING_ERROR_LENGTH    = 0x00000001,
+    VK_STRING_ERROR_BAD_DATA  = 0x00000002,
+} VkStringErrorFlagBits;
+typedef VkFlags VkStringErrorFlags;
+
+static const int  MaxLoaderStringLength = 256;
+static const char UTF8_ONE_BYTE_CODE    = 0xC0;
+static const char UTF8_ONE_BYTE_MASK    = 0xE0;
+static const char UTF8_TWO_BYTE_CODE    = 0xE0;
+static const char UTF8_TWO_BYTE_MASK    = 0xF0;
+static const char UTF8_THREE_BYTE_CODE  = 0xF0;
+static const char UTF8_THREE_BYTE_MASK  = 0xF8;
+static const char UTF8_DATA_BYTE_CODE   = 0x80;
+static const char UTF8_DATA_BYTE_MASK   = 0xC0;
+
 // form of all dynamic lists/arrays
 // only the list element should be changed
 struct loader_generic_list {
@@ -370,11 +388,13 @@
 bool compare_vk_extension_properties(const VkExtensionProperties *op1,
                                      const VkExtensionProperties *op2);
 
-VkResult loader_validate_layers(const uint32_t layer_count,
+VkResult loader_validate_layers(const struct loader_instance *inst,
+                                const uint32_t layer_count,
                                 const char *const *ppEnabledLayerNames,
                                 const struct loader_layer_list *list);
 
 VkResult loader_validate_instance_extensions(
+    const struct loader_instance *inst,
     const struct loader_extension_list *icd_exts,
     const struct loader_layer_list *instance_layer,
     const VkInstanceCreateInfo *pCreateInfo);
@@ -507,4 +527,7 @@
 void *loader_tls_heap_alloc(size_t size);
 
 void loader_tls_heap_free(void *pMemory);
+
+VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
+
 #endif /* LOADER_H */
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 7cf6f55..98205b9 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -110,7 +110,8 @@
 
     /* validate the app requested layers to be enabled */
     if (pCreateInfo->enabledLayerCount > 0) {
-        res = loader_validate_layers(pCreateInfo->enabledLayerCount,
+        res = loader_validate_layers(ptr_instance,
+                                     pCreateInfo->enabledLayerCount,
                                      pCreateInfo->ppEnabledLayerNames,
                                      &ptr_instance->instance_layer_list);
         if (res != VK_SUCCESS) {
@@ -130,7 +131,7 @@
     loader_get_icd_loader_instance_extensions(
         ptr_instance, &ptr_instance->icd_libs, &ptr_instance->ext_list);
     res = loader_validate_instance_extensions(
-        &ptr_instance->ext_list, &ptr_instance->instance_layer_list,
+        ptr_instance, &ptr_instance->ext_list, &ptr_instance->instance_layer_list,
         pCreateInfo);
     if (res != VK_SUCCESS) {
         loader_delete_layer_properties(ptr_instance,