Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/libANGLE/renderer/vulkan/CLKernelVk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,22 @@ angle::Result CLKernelVk::init()
}
case NonSemanticClspvReflectionArgumentPodPushConstant:
case NonSemanticClspvReflectionArgumentPointerPushConstant:
// Get existing push constant range and see if we need to update
if (arg.pushConstOffset + arg.pushConstantSize > pcRange.offset + pcRange.size)
{
// Get existing push constant range and see if we need to update.
// Use uint64_t to prevent uint32_t wrap-around from producing a
// falsely small pcRange.size (integer overflow -> heap under-alloc).
const uint64_t argEnd =
static_cast<uint64_t>(arg.pushConstOffset) + arg.pushConstantSize;
const uint64_t pcEnd =
static_cast<uint64_t>(pcRange.offset) + pcRange.size;
if (argEnd > pcEnd)
{
pcRange.size = arg.pushConstOffset + arg.pushConstantSize - pcRange.offset;
ASSERT(argEnd - pcRange.offset <=
std::numeric_limits<uint32_t>::max());
pcRange.size = static_cast<uint32_t>(argEnd - pcRange.offset);
}
continue;
}
case NonSemanticClspvReflectionArgumentSampledImage:
descType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
break;
Expand Down Expand Up @@ -251,8 +261,10 @@ angle::Result CLKernelVk::setArg(cl_uint argIndex, size_t argSize, const void *a
switch (arg.type)
{
case NonSemanticClspvReflectionArgumentPodPushConstant:
// Use uint64_t to prevent uint32_t wrap-around from defeating this
// bounds check (same overflow that under-allocates the vector).
ASSERT(mPodArgumentPushConstants.size() >=
arg.pushConstantSize + arg.pushConstOffset);
static_cast<uint64_t>(arg.pushConstantSize) + arg.pushConstOffset);
arg.handle = &mPodArgumentPushConstants[arg.pushConstOffset];
arg.handleSize = std::min(argSize, static_cast<size_t>(arg.pushConstantSize));
if (argSize > 0 && argValue != nullptr)
Expand Down
20 changes: 20 additions & 0 deletions src/libANGLE/renderer/vulkan/CLProgramVk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,26 @@ spv_result_t ParseReflection(CLProgramVk::SpvReflectionData &reflectionData,
kernelArg.op3 = reflectionData.spvIntLookup[spvInstr.words[7]];
kernelArg.op4 = reflectionData.spvIntLookup[spvInstr.words[8]];

// Validate push constant offset+size against Vulkan's guaranteed minimum
// maxPushConstantsSize (128 bytes). Reject malformed SPIR-V binaries whose
// values would cause a uint32_t overflow in CLKernelVk::init/setArg.
if (kernelArg.type == NonSemanticClspvReflectionArgumentPodPushConstant ||
kernelArg.type == NonSemanticClspvReflectionArgumentPointerPushConstant)
{
constexpr uint32_t kMaxPushConstantBytes = 128u;
const uint64_t endOffset =
static_cast<uint64_t>(kernelArg.op3) + kernelArg.op4;
if (kernelArg.op4 == 0 || kernelArg.op3 >= kMaxPushConstantBytes ||
kernelArg.op4 > kMaxPushConstantBytes ||
endOffset > kMaxPushConstantBytes)
{
ERR() << "CLProgramVk: rejecting SPIR-V binary: push constant "
"offset/size out of range (offset="
<< kernelArg.op3 << " size=" << kernelArg.op4 << ")";
return angle::Result::Stop;
}
}

if (reflectionData.kernelIDs.contains(spvInstr.words[5]))
{
CLKernelArguments &kernelArgs =
Expand Down