diff --git a/configure.ac b/configure.ac index 275bca26..88d58e40 100644 --- a/configure.ac +++ b/configure.ac @@ -127,6 +127,7 @@ AS_IF([test "x$with_xcb" != "xno"], dnl Check for functions VKD3D_CHECK_FUNC([HAVE_BUILTIN_CLZ], [__builtin_clz], [__builtin_clz(0)]) VKD3D_CHECK_FUNC([HAVE_BUILTIN_POPCOUNT], [__builtin_popcount], [__builtin_popcount(0)]) +VKD3D_CHECK_FUNC([HAVE_BUILTIN_ADD_OVERFLOW], [__builtin_add_overflow], [__builtin_add_overflow(0, 0, (int *)0)]) VKD3D_CHECK_FUNC([HAVE_SYNC_ADD_AND_FETCH], [__sync_add_and_fetch], [__sync_add_and_fetch((int *)0, 0)]) VKD3D_CHECK_FUNC([HAVE_SYNC_SUB_AND_FETCH], [__sync_sub_and_fetch], [__sync_sub_and_fetch((int *)0, 0)]) diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 23495fc2..e25ee909 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -134,6 +134,17 @@ static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, con return NULL; } +static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit) +{ +#ifdef HAVE_BUILTIN_ADD_OVERFLOW + size_t sum; + + return !__builtin_add_overflow(start, count, &sum) && sum <= limit; +#else + return start <= limit && count <= limit - start; +#endif +} + static inline int ascii_isupper(int c) { return 'A' <= c && c <= 'Z'; diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 614d19e7..93c519af 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4422,7 +4422,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetVertexBuffers(ID3D12Graphi null_resources = &list->device->null_resources; gpu_va_allocator = &list->device->gpu_va_allocator; - if (start_slot >= ARRAY_SIZE(list->strides) || view_count > ARRAY_SIZE(list->strides) - start_slot) + if (!vkd3d_bound_range(start_slot, view_count, ARRAY_SIZE(list->strides))) { WARN("Invalid start slot %u / view count %u.\n", start_slot, view_count); return; @@ -4477,7 +4477,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_SOSetTargets(ID3D12GraphicsComm return; } - if (start_slot >= ARRAY_SIZE(buffers) || view_count > ARRAY_SIZE(buffers) - start_slot) + if (!vkd3d_bound_range(start_slot, view_count, ARRAY_SIZE(buffers))) { WARN("Invalid start slot %u / view count %u.\n", start_slot, view_count); return; diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 159bc470..be0bf2fb 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -3515,8 +3515,7 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *i array_size = d3d12_resource_desc_get_layer_count(desc); - if (first_sub_resource >= desc->MipLevels * array_size - || sub_resource_count > desc->MipLevels * array_size - first_sub_resource) + if (!vkd3d_bound_range(first_sub_resource, sub_resource_count, desc->MipLevels * array_size)) { WARN("Invalid sub-resource range %u-%u for resource.\n", first_sub_resource, sub_resource_count); return;