From 3bfbcad8c6d94673b46c7925a3c3959c409a3f65 Mon Sep 17 00:00:00 2001 From: Maciej Dziuban Date: Tue, 5 Jun 2018 11:03:13 +0200 Subject: [PATCH] Fix validation of size when creating image from buffer Change-Id: Iaf9b8aae8bd3a2f2ea2b4a3d7f751dbcf4df7c0e --- runtime/mem_obj/image.cpp | 7 +- .../mem_obj/image2d_from_buffer_tests.cpp | 82 ++++++++++++++++++- 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/runtime/mem_obj/image.cpp b/runtime/mem_obj/image.cpp index 0f5ab20988..2fdcb481ac 100644 --- a/runtime/mem_obj/image.cpp +++ b/runtime/mem_obj/image.cpp @@ -444,9 +444,12 @@ cl_int Image::validate(Context *context, pDevice->getCap(reinterpret_cast(pitchAlignment), srcSize, retSize); pDevice->getCap(reinterpret_cast(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(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 diff --git a/unit_tests/mem_obj/image2d_from_buffer_tests.cpp b/unit_tests/mem_obj/image2d_from_buffer_tests.cpp index 8b4f2e4dce..b86a39ae9a 100644 --- a/unit_tests/mem_obj/image2d_from_buffer_tests.cpp +++ b/unit_tests/mem_obj/image2d_from_buffer_tests.cpp @@ -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(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(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(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(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(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(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(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(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(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(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::getValue(context.getDevice(0u)->getDeviceInfo()); + imageDesc.image_height = castToObject(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(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(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(Image::getSurfaceFormatFromTable(flags, &imageFormat)); retVal = Image::validate(&context, flags, surfaceFormat, &imageDesc, NULL); EXPECT_EQ(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, retVal); }