layers: Correct 32bit handling of ValidationCache

Updated handle casting for Validation object to size-safe/portable
calls.  Corrected incorrect loop increment for 64bit handles cast to
32bit pointers.

Change-Id: I459a0f37426ec5656e228e91b4b116e7dacc0e3d
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index fea1485..d2b7c66 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -13202,24 +13202,24 @@
 
 void CoreChecks::CoreLayerDestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache,
                                                     const VkAllocationCallbacks *pAllocator) {
-    delete (ValidationCache *)validationCache;
+    delete CastFromHandle<VkValidationCacheEXT, ValidationCache *>(validationCache);
 }
 
 VkResult CoreChecks::CoreLayerGetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t *pDataSize,
                                                         void *pData) {
     size_t inSize = *pDataSize;
-    ((ValidationCache *)validationCache)->Write(pDataSize, pData);
+    CastFromHandle<VkValidationCacheEXT, ValidationCache *>(validationCache)->Write(pDataSize, pData);
     return (pData && *pDataSize != inSize) ? VK_INCOMPLETE : VK_SUCCESS;
 }
 
 VkResult CoreChecks::CoreLayerMergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount,
                                                        const VkValidationCacheEXT *pSrcCaches) {
     bool skip = false;
-    auto dst = (ValidationCache *)dstCache;
-    auto src = (ValidationCache const *const *)pSrcCaches;
+    auto dst = CastFromHandle<VkValidationCacheEXT, ValidationCache *>(dstCache);
     VkResult result = VK_SUCCESS;
     for (uint32_t i = 0; i < srcCacheCount; i++) {
-        if (src[i] == dst) {
+        auto src = CastFromHandle<const VkValidationCacheEXT, const ValidationCache *>(pSrcCaches[i]);
+        if (src == dst) {
             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT, 0,
                             "VUID-vkMergeValidationCachesEXT-dstCache-01536",
                             "vkMergeValidationCachesEXT: dstCache (0x%" PRIx64 ") must not appear in pSrcCaches array.",
@@ -13227,7 +13227,7 @@
             result = VK_ERROR_VALIDATION_FAILED_EXT;
         }
         if (!skip) {
-            dst->Merge(src[i]);
+            dst->Merge(src);
         }
     }
 
diff --git a/layers/shader_validation.cpp b/layers/shader_validation.cpp
index 3cbe518..3482a18 100644
--- a/layers/shader_validation.cpp
+++ b/layers/shader_validation.cpp
@@ -2532,11 +2532,10 @@
 uint32_t ValidationCache::MakeShaderHash(VkShaderModuleCreateInfo const *smci) { return XXH32(smci->pCode, smci->codeSize, 0); }
 
 static ValidationCache *GetValidationCacheInfo(VkShaderModuleCreateInfo const *pCreateInfo) {
-    while ((pCreateInfo = (VkShaderModuleCreateInfo const *)pCreateInfo->pNext) != nullptr) {
-        if (pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT)
-            return (ValidationCache *)((VkShaderModuleValidationCacheCreateInfoEXT const *)pCreateInfo)->validationCache;
+    const auto validation_cache_ci = lvl_find_in_chain<VkShaderModuleValidationCacheCreateInfoEXT>(pCreateInfo->pNext);
+    if (validation_cache_ci) {
+        return CastFromHandle<VkValidationCacheEXT, ValidationCache *>(validation_cache_ci->validationCache);
     }
-
     return nullptr;
 }
 
diff --git a/layers/vk_layer_utils.h b/layers/vk_layer_utils.h
index 0ab161a..e59d7bc 100644
--- a/layers/vk_layer_utils.h
+++ b/layers/vk_layer_utils.h
@@ -159,6 +159,34 @@
     return static_cast<uint64_t>(CastToUint<HandleType, Uint>(handle));
 }
 
+// Convenience functions to case between handles and the types the handles abstract, reflecting the Vulkan handle scheme, where
+// Handles are either pointers (dispatchable) or sizeof(uint64_t) (non-dispatchable), s.t. full size-safe casts are used and
+// we ensure that handles are large enough to contain the underlying type.
+template <typename HandleType, typename ValueType>
+void CastToHandle(ValueType value, HandleType *handle) {
+    static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value");
+    *handle = CastFromUint64<HandleType>(CastToUint64<ValueType>(value));
+}
+// This form is conveniently "inline" but inconveniently requires both template arguments.
+template <typename HandleType, typename ValueType>
+HandleType CastToHandle(ValueType value) {
+    HandleType handle;
+    CastToHandle(value, &handle);
+    return handle;
+}
+
+template <typename HandleType, typename ValueType>
+void CastFromHandle(HandleType handle, ValueType *value) {
+    static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value");
+    *value = CastFromUint64<ValueType>(CastToUint64<HandleType>(handle));
+}
+template <typename HandleType, typename ValueType>
+ValueType CastFromHandle(HandleType handle) {
+    ValueType value;
+    CastFromHandle(handle, &value);
+    return value;
+}
+
 extern "C" {
 #endif