layers: Add string validation to param_checker
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index 905cc13..7f08594 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -28,6 +28,7 @@
  *
  * Author: Jeremy Hayes <jeremy@lunarg.com>
  * Author: Tony Barbour <tony@LunarG.com>
+ * Author: Mark Lobodzinski <mark@LunarG.com>
  */
 
 #include <stdio.h>
@@ -51,6 +52,7 @@
 #include "vk_layer_data.h"
 #include "vk_layer_logging.h"
 #include "vk_layer_extension_utils.h"
+#include "vk_layer_utils.h"
 
 struct layer_data {
     debug_report_data *report_data;
@@ -231,13 +233,12 @@
         uint32_t*                                   pCount,
         VkLayerProperties*                          pProperties)
 {
+
     /* ParamChecker's physical device layers are the same as global */
     return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers,
                                    pCount, pProperties);
 }
 
-// Version: 0.138.2
-
 static
 std::string EnumeratorString(VkResult const& enumerator)
 {
@@ -1771,38 +1772,70 @@
     return enumeratorString;
 }
 
+static const int MaxParamCheckerStringLength = 256;
+
+VkBool32 validate_string(layer_data *my_data, const char *apiName, const char *stringName, const char *validateString)
+{
+    VkBool32 skipCall = VK_FALSE;
+
+    VkStringErrorFlags result = vk_string_validate(MaxParamCheckerStringLength, validateString);
+
+    if (result == VK_STRING_ERROR_NONE) {
+        return skipCall;
+    } else if (result & VK_STRING_ERROR_LENGTH) {
+        skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
+        "%s: string %s exceeds max length %d", apiName, stringName, MaxParamCheckerStringLength);
+    } else if (result & VK_STRING_ERROR_BAD_DATA) {
+        skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
+        "%s: string %s contains invalid characters or is badly formed", apiName, stringName);
+    }
+    return skipCall;
+}
+
+
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
     const VkInstanceCreateInfo* pCreateInfo,
     const VkAllocationCallbacks* pAllocator,
     VkInstance* pInstance)
 {
-    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+    VkResult    result         = VK_ERROR_VALIDATION_FAILED_EXT;
+    VkBool32    skipCall       = VK_FALSE;
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
 
-    assert(chain_info->u.pLayerInfo);
-    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
-    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
-    if (fpCreateInstance == NULL) {
-        return VK_ERROR_INITIALIZATION_FAILED;
+    skipCall |= validate_string(my_device_data, "vkCreateInstance()", "VkInstanceCreateInfo->VkApplicationInfo->pApplicationName",
+                                pCreateInfo->pApplicationInfo->pApplicationName);
+
+    skipCall |= validate_string(my_device_data, "vkCreateInstance()", "VkInstanceCreateInfo->VkApplicationInfo->pEngineName",
+                                pCreateInfo->pApplicationInfo->pEngineName);
+
+    if (skipCall == VK_FALSE) {
+        VkLayerInstanceCreateInfo *chain_info     = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+        assert(chain_info->u.pLayerInfo);
+        PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+        PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+        if (fpCreateInstance == NULL) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+
+        // Advance the link info for the next element on the chain
+        chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+        result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+        if (result != VK_SUCCESS)
+            return result;
+
+        layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+        VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, pc_instance_table_map);
+
+        my_data->report_data = debug_report_create_instance(
+                                   pTable,
+                                   *pInstance,
+                                   pCreateInfo->enabledExtensionCount,
+                                   pCreateInfo->ppEnabledExtensionNames);
+
+        InitParamChecker(my_data, pAllocator);
     }
 
-    // Advance the link info for the next element on the chain
-    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
-
-    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
-    if (result != VK_SUCCESS)
-        return result;
-
-    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
-    VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, pc_instance_table_map);
-
-    my_data->report_data = debug_report_create_instance(
-                               pTable,
-                               *pInstance,
-                               pCreateInfo->enabledExtensionCount,
-                               pCreateInfo->ppEnabledExtensionNames);
-
-    InitParamChecker(my_data, pAllocator);
-
     return result;
 }
 
@@ -1998,6 +2031,7 @@
         "vkGetPhysicalDeviceProperties parameter, VkPhysicalDeviceType pProperties->deviceType, is an unrecognized enumerator");
         return false;
     }
+
     }
 
     return true;
@@ -2107,36 +2141,51 @@
      * NOTE: We do not validate physicalDevice or any dispatchable
      * object as the first parameter. We couldn't get here if it was wrong!
      */
-    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
-    assert(chain_info->u.pLayerInfo);
-    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
-    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
-    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
-    if (fpCreateDevice == NULL) {
-        return VK_ERROR_INITIALIZATION_FAILED;
-    }
-
-    // Advance the link info for the next element on the chain
-    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
-
-    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
-    if (result != VK_SUCCESS) {
-        return result;
-    }
-
+    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+    VkBool32 skipCall = VK_FALSE;
     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
-    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
-    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
-    initDeviceTable(*pDevice, fpGetDeviceProcAddr, pc_device_table_map);
 
-    uint32_t count;
-    get_dispatch_table(pc_instance_table_map, physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
-    std::vector<VkQueueFamilyProperties> properties(count);
-    get_dispatch_table(pc_instance_table_map, physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, &properties[0]);
+    for (auto i = 0; i < pCreateInfo->enabledLayerCount; i++) {
+        skipCall |= validate_string(my_instance_data, "vkCreateDevice()", "VkDeviceCreateInfo->ppEnabledLayerNames",
+                                    pCreateInfo->ppEnabledLayerNames[i]);
+    }
 
-    validateDeviceCreateInfo(physicalDevice, pCreateInfo, properties);
-    storeCreateDeviceData(*pDevice, pCreateInfo);
+    for (auto i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+        skipCall |= validate_string(my_instance_data, "vkCreateDevice()", "VkDeviceCreateInfo->ppEnabledExtensionNames",
+                                    pCreateInfo->ppEnabledExtensionNames[i]);
+    }
+
+    if (skipCall == VK_FALSE) {
+        VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+        assert(chain_info->u.pLayerInfo);
+        PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+        PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+        PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+        if (fpCreateDevice == NULL) {
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+
+        // Advance the link info for the next element on the chain
+        chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+        result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+        if (result != VK_SUCCESS) {
+            return result;
+        }
+
+        layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+        my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+        initDeviceTable(*pDevice, fpGetDeviceProcAddr, pc_device_table_map);
+
+        uint32_t count;
+        get_dispatch_table(pc_instance_table_map, physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
+        std::vector<VkQueueFamilyProperties> properties(count);
+        get_dispatch_table(pc_instance_table_map, physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, &properties[0]);
+
+        validateDeviceCreateInfo(physicalDevice, pCreateInfo, properties);
+        storeCreateDeviceData(*pDevice, pCreateInfo);
+    }
 
     return result;
 }
@@ -3794,6 +3843,9 @@
     VkDevice device,
     const VkGraphicsPipelineCreateInfo* pCreateInfos)
 {
+    layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+    // TODO: Handle count
     if(pCreateInfos != nullptr)
     {
     if(pCreateInfos->sType != VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO)
@@ -4060,6 +4112,12 @@
         log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
         "vkCreateGraphicsPipelines parameter, VkRenderPass pCreateInfos->renderPass, is null pointer");
     }
+
+    int i = 0;
+    for (auto j = 0; j < pCreateInfos[i].stageCount; j++) {
+        validate_string(data, "vkCreateGraphicsPipelines()", "pCreateInfos[i].pStages[j].pName", pCreateInfos[i].pStages[j].pName);
+    }
+
     }
 
     return true;
@@ -4110,8 +4168,11 @@
     VkDevice device,
     const VkComputePipelineCreateInfo* pCreateInfos)
 {
+    layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
     if(pCreateInfos != nullptr)
     {
+    // TODO: Handle count!
     if(pCreateInfos->sType != VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO)
     {
         log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
@@ -4133,6 +4194,9 @@
     {
     }
     }
+
+    int i = 0;
+    validate_string(data, "vkCreateComputePipelines()", "pCreateInfos[i].stage.pName", pCreateInfos[i].stage.pName);
     }
 
     return true;
@@ -6547,6 +6611,12 @@
 
 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
 {
+    layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+    if (validate_string(data, "vkGetDeviceProcAddr()", "funcName", funcName) == VK_TRUE) {
+        return NULL;
+    }
+
     if (!strcmp(funcName, "vkGetDeviceProcAddr"))
         return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
     if (!strcmp(funcName, "vkDestroyDevice"))
@@ -6749,6 +6819,7 @@
     }
 
     layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+
     PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
     if(fptr)
         return fptr;
diff --git a/layers/vk_layer_utils.cpp b/layers/vk_layer_utils.cpp
index 2452b0e..59c4222 100644
--- a/layers/vk_layer_utils.cpp
+++ b/layers/vk_layer_utils.cpp
@@ -610,12 +610,12 @@
 static const char UTF8_DATA_BYTE_CODE  = 0x80;
 static const char UTF8_DATA_BYTE_MASK  = 0xC0;
 
-VkStringErrorFlags vk_string_validate(const int max_length, char *utf8)
+VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8)
 {
-    VkStringErrorFlags result     = VK_STRING_ERROR_NONE;
-    int code;
-    int num_char_bytes;
-    int i,j;
+    VkStringErrorFlags result = VK_STRING_ERROR_NONE;
+    int                code;
+    int                num_char_bytes;
+    int                i,j;
 
     for (i = 0; i < max_length; i++)
     {
diff --git a/layers/vk_layer_utils.h b/layers/vk_layer_utils.h
index 41b7875..359029d 100644
--- a/layers/vk_layer_utils.h
+++ b/layers/vk_layer_utils.h
@@ -123,7 +123,7 @@
 unsigned int               vk_format_get_channel_count(VkFormat format);
 VkFormatCompatibilityClass vk_format_get_compatibility_class(VkFormat format);
 VkDeviceSize               vk_safe_modulo(VkDeviceSize dividend, VkDeviceSize divisor);
-VkStringErrorFlags         vk_string_validate(const int max_length, char *char_array);
+VkStringErrorFlags         vk_string_validate(const int max_length, const char *char_array);
 
 static inline int u_ffs(int val)
 {