aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Lobodzinski <mark@lunarg.com>2016-03-21 16:32:53 -0600
committerMark Lobodzinski <mark@lunarg.com>2016-03-23 16:50:54 -0600
commita2d5d61d3c324e027f78bfd1d8c4c49c66898520 (patch)
treefc8a05567d25616d7f4ef19b8605dffbee494d34
parentc7bd67f06427b08ba65cdf2dd529c8234beebdd5 (diff)
downloadvulkan-validation-layers-a2d5d61d3c324e027f78bfd1d8c4c49c66898520.tar.gz
layers: LX448, Prevent descriptorSetCount overflow in core_validation
Tracking descriptor and descriptorSet counts was incorrect, sometimes causing integer overflow and application crashes for large createInfo values. Change-Id: I92196659d6a7476582aa069e42c9a0d7228ba087
-rw-r--r--layers/core_validation.cpp26
-rw-r--r--layers/core_validation.h19
2 files changed, 30 insertions, 15 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index e4946c40c..4e44b3135 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -4109,11 +4109,25 @@ static VkBool32 dsUpdate(layer_data *my_data, VkDevice device, uint32_t descript
return skipCall;
}
-// Verify that given pool has descriptors that are being requested for allocation
+// Verify that given pool has descriptors that are being requested for allocation.
+// NOTE : Calls to this function should be wrapped in mutex
static VkBool32 validate_descriptor_availability_in_pool(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count,
const VkDescriptorSetLayout *pSetLayouts) {
VkBool32 skipCall = VK_FALSE;
- uint32_t i = 0, j = 0;
+ uint32_t i = 0;
+ uint32_t j = 0;
+
+ // Track number of descriptorSets allowable in this pool
+ if (pPoolNode->availableSets < count) {
+ skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+ reinterpret_cast<uint64_t &>(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
+ "Unable to allocate %u descriptorSets from pool %#" PRIxLEAST64
+ ". This pool only has %d descriptorSets remaining.",
+ count, reinterpret_cast<uint64_t &>(pPoolNode->pool), pPoolNode->availableSets);
+ } else {
+ pPoolNode->availableSets -= count;
+ }
+
for (i = 0; i < count; ++i) {
LAYOUT_NODE *pLayout = getLayoutNode(dev_data, pSetLayouts[i]);
if (NULL == pLayout) {
@@ -4132,7 +4146,7 @@ static VkBool32 validate_descriptor_availability_in_pool(layer_data *dev_data, D
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t)pLayout->layout, __LINE__,
DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
"Unable to allocate %u descriptors of type %s from pool %#" PRIxLEAST64
- ". This pool only has %u descriptors of this type remaining.",
+ ". This pool only has %d descriptors of this type remaining.",
poolSizeCount, string_VkDescriptorType(pLayout->createInfo.pBindings[j].descriptorType),
(uint64_t)pPoolNode->pool, pPoolNode->availableDescriptorTypeCount[typeIndex]);
} else { // Decrement available descriptors of this type
@@ -6842,8 +6856,12 @@ vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t
return VK_ERROR_VALIDATION_FAILED_EXT;
VkResult result = dev_data->device_dispatch_table->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
if (VK_SUCCESS == result) {
- // For each freed descriptor add it back into the pool as available
loader_platform_thread_lock_mutex(&globalLock);
+
+ // Update available descriptor sets in pool
+ pPoolNode->availableSets += count;
+
+ // For each freed descriptor add it back into the pool as available
for (uint32_t i = 0; i < count; ++i) {
SET_NODE *pSet = dev_data->setMap[pDescriptorSets[i]]; // getSetNode() without locking
invalidateBoundCmdBuffers(dev_data, pSet);
diff --git a/layers/core_validation.h b/layers/core_validation.h
index c6266afe3..17913ba57 100644
--- a/layers/core_validation.h
+++ b/layers/core_validation.h
@@ -627,14 +627,16 @@ class SET_NODE : public BASE_NODE {
typedef struct _DESCRIPTOR_POOL_NODE {
VkDescriptorPool pool;
- uint32_t maxSets;
+ uint32_t maxSets; // Max descriptor sets allowed in this pool
+ uint32_t availableSets; // Available descriptr sets in this pool
+
VkDescriptorPoolCreateInfo createInfo;
SET_NODE *pSets; // Head of LL of sets for this Pool
- vector<uint32_t> maxDescriptorTypeCount; // max # of descriptors of each type in this pool
- vector<uint32_t> availableDescriptorTypeCount; // available # of descriptors of each type in this pool
+ vector<uint32_t> maxDescriptorTypeCount; // Max # of descriptors of each type in this pool
+ vector<uint32_t> availableDescriptorTypeCount; // Available # of descriptors of each type in this pool
_DESCRIPTOR_POOL_NODE(const VkDescriptorPool pool, const VkDescriptorPoolCreateInfo *pCreateInfo)
- : pool(pool), maxSets(pCreateInfo->maxSets), createInfo(*pCreateInfo), pSets(NULL),
+ : pool(pool), maxSets(pCreateInfo->maxSets), availableSets(pCreateInfo->maxSets), createInfo(*pCreateInfo), pSets(NULL),
maxDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE), availableDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE) {
if (createInfo.poolSizeCount) { // Shadow type struct from ptr into local struct
size_t poolSizeCountSize = createInfo.poolSizeCount * sizeof(VkDescriptorPoolSize);
@@ -644,13 +646,8 @@ typedef struct _DESCRIPTOR_POOL_NODE {
uint32_t i = 0;
for (i = 0; i < createInfo.poolSizeCount; ++i) {
uint32_t typeIndex = static_cast<uint32_t>(createInfo.pPoolSizes[i].type);
- uint32_t poolSizeCount = createInfo.pPoolSizes[i].descriptorCount;
- maxDescriptorTypeCount[typeIndex] += poolSizeCount;
- }
- for (i = 0; i < maxDescriptorTypeCount.size(); ++i) {
- maxDescriptorTypeCount[i] *= createInfo.maxSets;
- // Initially the available counts are equal to the max counts
- availableDescriptorTypeCount[i] = maxDescriptorTypeCount[i];
+ maxDescriptorTypeCount[typeIndex] = createInfo.pPoolSizes[i].descriptorCount;
+ availableDescriptorTypeCount[typeIndex] = maxDescriptorTypeCount[typeIndex];
}
} else {
createInfo.pPoolSizes = NULL; // Make sure this is NULL so we don't try to clean it up