Fix validation of size when creating image from buffer

Change-Id: Iaf9b8aae8bd3a2f2ea2b4a3d7f751dbcf4df7c0e
This commit is contained in:
Maciej Dziuban 2018-06-05 11:03:13 +02:00 committed by sys_ocldev
parent 836e0023c1
commit 3bfbcad8c6
2 changed files with 83 additions and 6 deletions

View File

@ -444,9 +444,12 @@ cl_int Image::validate(Context *context,
pDevice->getCap<CL_DEVICE_IMAGE_PITCH_ALIGNMENT>(reinterpret_cast<const void *&>(pitchAlignment), srcSize, retSize);
pDevice->getCap<CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT>(reinterpret_cast<const void *&>(baseAddressAlignment), srcSize, retSize);
const auto rowSize = imageDesc->image_row_pitch != 0 ? imageDesc->image_row_pitch : alignUp(imageDesc->image_width * surfaceFormat->NumChannels * surfaceFormat->PerChannelSizeInBytes, *pitchAlignment);
const auto minimumBufferSize = imageDesc->image_height * rowSize;
if ((imageDesc->image_row_pitch % (*pitchAlignment)) ||
((parentBuffer->getFlags() & CL_MEM_USE_HOST_PTR) && (reinterpret_cast<uint64_t>(parentBuffer->getHostPtr()) % (*baseAddressAlignment))) ||
(imageDesc->image_height * (imageDesc->image_row_pitch != 0 ? imageDesc->image_row_pitch : imageDesc->image_width) > parentBuffer->getSize())) {
(minimumBufferSize > parentBuffer->getSize())) {
return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
} else if (flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) {
return CL_INVALID_VALUE;
@ -1299,4 +1302,4 @@ bool Image::hasValidParentImageFormat(const cl_image_format &imageFormat) const
return false;
}
}
}
} // namespace OCLRT

View File

@ -107,7 +107,7 @@ TEST_F(Image2dFromBufferTest, CalculateRowPitch) {
}
TEST_F(Image2dFromBufferTest, givenInvalidRowPitchWhenCreateImage2dFromBufferThenReturnsError) {
char ptr[10];
imageDesc.image_row_pitch = 257;
imageDesc.image_row_pitch = 255;
cl_mem_flags flags = CL_MEM_READ_ONLY;
auto surfaceFormat = (SurfaceFormatInfo *)Image::getSurfaceFormatFromTable(flags, &imageFormat);
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, ptr);
@ -152,10 +152,84 @@ TEST_F(Image2dFromBufferTest, InvalidFlags) {
EXPECT_EQ(CL_INVALID_VALUE, retVal);
}
TEST_F(Image2dFromBufferTest, InvalidSize) {
imageDesc.image_height = 1024;
TEST_F(Image2dFromBufferTest, givenOneChannel8BitColorsNoRowPitchSpecifiedAndTooLargeImageWhenValidatingSurfaceFormatThenReturnError) {
imageDesc.image_height = 1 + castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width;
cl_mem_flags flags = CL_MEM_READ_ONLY;
auto surfaceFormat = (SurfaceFormatInfo *)Image::getSurfaceFormatFromTable(flags, &imageFormat);
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_R;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal);
}
TEST_F(Image2dFromBufferTest, givenOneChannel16BitColorsNoRowPitchSpecifiedAndTooLargeImageWhenValidatingSurfaceFormatThenReturnError) {
imageDesc.image_height = 1 + castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width / 2;
cl_mem_flags flags = CL_MEM_READ_ONLY;
imageFormat.image_channel_data_type = CL_UNORM_INT16;
imageFormat.image_channel_order = CL_R;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal);
}
TEST_F(Image2dFromBufferTest, givenFourChannel8BitColorsNoRowPitchSpecifiedAndTooLargeImageWhenValidatingSurfaceFormatThenReturnError) {
imageDesc.image_height = 1 + castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width / 4;
cl_mem_flags flags = CL_MEM_READ_ONLY;
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_RGBA;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal);
}
TEST_F(Image2dFromBufferTest, givenFourChannel16BitColorsNoRowPitchSpecifiedAndTooLargeImageWhenValidatingSurfaceFormatThenReturnError) {
imageDesc.image_height = 1 + castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width / 8;
cl_mem_flags flags = CL_MEM_READ_ONLY;
imageFormat.image_channel_data_type = CL_UNORM_INT16;
imageFormat.image_channel_order = CL_RGBA;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal);
}
TEST_F(Image2dFromBufferTest, givenFourChannel8BitColorsAndNotTooLargeRowPitchSpecifiedWhenValidatingSurfaceFormatThenDoNotReturnError) {
imageDesc.image_height = castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width;
imageDesc.image_row_pitch = imageDesc.image_width;
cl_mem_flags flags = CL_MEM_READ_ONLY;
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_RGBA;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_SUCCESS, retVal);
}
TEST_F(Image2dFromBufferTest, givenFourChannel8BitColorsAndTooLargeRowPitchSpecifiedWhenValidatingSurfaceFormatThenReturnError) {
const auto pitchAlignment = &DeviceInfoTable::Map<CL_DEVICE_IMAGE_PITCH_ALIGNMENT>::getValue(context.getDevice(0u)->getDeviceInfo());
imageDesc.image_height = castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width;
imageDesc.image_row_pitch = imageDesc.image_width + *pitchAlignment;
cl_mem_flags flags = CL_MEM_READ_ONLY;
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_RGBA;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal);
}
TEST_F(Image2dFromBufferTest, givenUnalignedImageWidthAndNoSpaceInBufferForAlignmentWhenValidatingSurfaceFormatThenReturnError) {
context.getDevice(0u)->getMutableDeviceInfo()->imagePitchAlignment = 128;
imageDesc.image_width = 64;
imageDesc.image_height = castToObject<Buffer>(imageDesc.mem_object)->getSize() / imageDesc.image_width;
cl_mem_flags flags = CL_MEM_READ_ONLY;
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_R;
const auto surfaceFormat = static_cast<const SurfaceFormatInfo *>(Image::getSurfaceFormatFromTable(flags, &imageFormat));
retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL);
EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal);
}