diff --git a/opencl/source/kernel/kernel.cpp b/opencl/source/kernel/kernel.cpp index 973c9f27d0..4aaa90124b 100644 --- a/opencl/source/kernel/kernel.cpp +++ b/opencl/source/kernel/kernel.cpp @@ -1714,17 +1714,16 @@ cl_int Kernel::setArgImmediate(uint32_t argIndex, const auto &argAsVal = kernelInfo.kernelDescriptor.payloadMappings.explicitArgs[argIndex].as(); for (const auto &element : argAsVal.elements) { DEBUG_BREAK_IF(element.size <= 0); + if (static_cast(element.sourceOffset + element.size) > argSize) { + return CL_INVALID_ARG_SIZE; + } auto pDst = ptrOffset(crossThreadData, element.offset); auto pSrc = ptrOffset(argVal, element.sourceOffset); - DEBUG_BREAK_IF(!(ptrOffset(pDst, element.size) <= crossThreadDataEnd)); + auto dstAvailableSpace = crossThreadDataEnd - pDst; - if (element.sourceOffset < argSize) { - size_t maxBytesToCopy = argSize - element.sourceOffset; - size_t bytesToCopy = std::min(static_cast(element.size), maxBytesToCopy); - memcpy_s(pDst, element.size, pSrc, bytesToCopy); - } + memcpy_s(pDst, dstAvailableSpace, pSrc, element.size); } retVal = CL_SUCCESS; diff --git a/opencl/test/unit_test/api/api_tests_wrapper3.cpp b/opencl/test/unit_test/api/api_tests_wrapper3.cpp index 49fcfe90f1..7a2737ace9 100644 --- a/opencl/test/unit_test/api/api_tests_wrapper3.cpp +++ b/opencl/test/unit_test/api/api_tests_wrapper3.cpp @@ -33,6 +33,7 @@ #include "opencl/test/unit_test/api/cl_set_context_destructor_callback.inl" #include "opencl/test/unit_test/api/cl_set_event_callback_tests.inl" #include "opencl/test/unit_test/api/cl_set_kernel_arg_svm_pointer_tests.inl" +#include "opencl/test/unit_test/api/cl_set_kernel_arg_tests.inl" #include "opencl/test/unit_test/api/cl_set_kernel_exec_info_tests.inl" #include "opencl/test/unit_test/api/cl_set_mem_object_destructor_callback_tests.inl" #include "opencl/test/unit_test/api/cl_set_performance_configuration_tests.inl" diff --git a/opencl/test/unit_test/api/cl_set_kernel_arg_tests.inl b/opencl/test/unit_test/api/cl_set_kernel_arg_tests.inl new file mode 100644 index 0000000000..6947d6483b --- /dev/null +++ b/opencl/test/unit_test/api/cl_set_kernel_arg_tests.inl @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024-2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/compiler_interface/compiler_interface.h" +#include "shared/source/compiler_interface/compiler_options.h" +#include "shared/source/device/device.h" +#include "shared/source/helpers/file_io.h" +#include "shared/test/common/helpers/kernel_binary_helper.h" +#include "shared/test/common/helpers/test_files.h" + +#include "opencl/source/context/context.h" + +#include "cl_api_tests.h" + +using namespace NEO; + +using ClSetKernelArgTests = ApiTests; + +namespace ULT { + +TEST_F(ClSetKernelArgTests, WhenSettingKernelArgThenArgSizeIsRespected) { + cl_program pProgram = nullptr; + size_t sourceSize = 0; + std::string testFile; + + KernelBinaryHelper kbHelper("simple_kernels", false); + + testFile.append(clFiles); + testFile.append("simple_kernels.cl"); + + auto pSource = loadDataFromFile( + testFile.c_str(), + sourceSize); + + ASSERT_NE(0u, sourceSize); + ASSERT_NE(nullptr, pSource); + + const char *sources[1] = {pSource.get()}; + pProgram = clCreateProgramWithSource( + pContext, + 1, + sources, + &sourceSize, + &retVal); + + EXPECT_NE(nullptr, pProgram); + ASSERT_EQ(CL_SUCCESS, retVal); + + retVal = clBuildProgram( + pProgram, + 1, + &testedClDevice, + CompilerOptions::argInfo.data(), + nullptr, + nullptr); + + ASSERT_EQ(CL_SUCCESS, retVal); + + cl_kernel kernel = clCreateKernel(pProgram, "simple_kernel_1", &retVal); + ASSERT_EQ(CL_SUCCESS, retVal); + + uint32_t data = 1; + retVal = clSetKernelArg(kernel, 1, 1, &data); + EXPECT_EQ(CL_INVALID_ARG_SIZE, retVal); + + retVal = clSetKernelArg(kernel, 1, sizeof(data), &data); + EXPECT_EQ(CL_SUCCESS, retVal); + + retVal = clReleaseKernel(kernel); + EXPECT_EQ(CL_SUCCESS, retVal); + + retVal = clReleaseProgram(pProgram); + EXPECT_EQ(CL_SUCCESS, retVal); +} +} // namespace ULT diff --git a/opencl/test/unit_test/kernel/clone_kernel_tests.cpp b/opencl/test/unit_test/kernel/clone_kernel_tests.cpp index 96e42418e6..600e1242a7 100644 --- a/opencl/test/unit_test/kernel/clone_kernel_tests.cpp +++ b/opencl/test/unit_test/kernel/clone_kernel_tests.cpp @@ -485,9 +485,9 @@ TEST_F(CloneKernelTest, givenArgSvmAllocWhenCloningKernelThenKernelInfoIsCorrect } TEST_F(CloneKernelTest, givenArgImmediateWhenCloningKernelThenKernelInfoIsCorrect) { - pKernelInfo->addArgImmediate(0, sizeof(void *), 0x20); - using TypeParam = unsigned long; + pKernelInfo->addArgImmediate(0, sizeof(TypeParam), 0x20); + auto value = (TypeParam)0xAA55AA55UL; retVal = pSourceMultiDeviceKernel->setArg(0, sizeof(TypeParam), &value); diff --git a/opencl/test/unit_test/kernel/kernel_immediate_arg_tests.cpp b/opencl/test/unit_test/kernel/kernel_immediate_arg_tests.cpp index 7f7610b562..e63bcd2dd7 100644 --- a/opencl/test/unit_test/kernel/kernel_immediate_arg_tests.cpp +++ b/opencl/test/unit_test/kernel/kernel_immediate_arg_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -221,8 +221,7 @@ TYPED_TEST(KernelArgImmediateTest, givenTooLargePatchSizeWhenSettingArgThenDontR const auto memoryBeyondLimitBefore = *reinterpret_cast(memoryBeyondLimitAddress); - this->pKernelInfo->argAsVal(0).elements[0].size = sizeof(TypeParam) + 1; - auto retVal = pKernel->setArg(0, sizeof(TypeParam), &memory[0]); + auto retVal = pKernel->setArg(0, sizeof(memory), memory); const auto memoryBeyondLimitAfter = *reinterpret_cast(memoryBeyondLimitAddress); EXPECT_EQ(memoryBeyondLimitBefore, memoryBeyondLimitAfter); @@ -257,43 +256,6 @@ TYPED_TEST(KernelArgImmediateTest, givenNotTooLargePatchSizeWhenSettingArgThenDo } } -TYPED_TEST(KernelArgImmediateTest, givenMulitplePatchesAndFirstPatchSizeTooLargeWhenSettingArgThenDontReadMemoryBeyondLimit) { - if (sizeof(TypeParam) == 1) - return; // multiple patch chars don't make sense - - for (auto &rootDeviceIndex : this->context->getRootDeviceIndices()) { - auto pKernel = this->pMultiDeviceKernel->getKernel(rootDeviceIndex); - TypeParam memory[2]; - std::memset(&memory[0], 0xaa, sizeof(TypeParam)); - std::memset(&memory[1], 0xbb, sizeof(TypeParam)); - - auto &elements = this->pKernelInfo->argAsVal(3).elements; - const auto destinationMemoryAddress1 = pKernel->getCrossThreadData() + - elements[2].offset; - const auto destinationMemoryAddress2 = pKernel->getCrossThreadData() + - elements[1].offset; - const auto memoryBeyondLimitAddress1 = destinationMemoryAddress1 + sizeof(TypeParam); - const auto memoryBeyondLimitAddress2 = destinationMemoryAddress2 + sizeof(TypeParam) / 2; - - const std::vector memoryBeyondLimitBefore1(memoryBeyondLimitAddress1, memoryBeyondLimitAddress1 + sizeof(TypeParam)); - const std::vector memoryBeyondLimitBefore2(memoryBeyondLimitAddress2, memoryBeyondLimitAddress2 + sizeof(TypeParam) / 2); - - elements[2].sourceOffset = 0; - elements[1].sourceOffset = sizeof(TypeParam) / 2; - elements[2].size = sizeof(TypeParam); - elements[1].size = sizeof(TypeParam) / 2; - auto retVal = pKernel->setArg(3, sizeof(TypeParam), &memory[0]); - - EXPECT_EQ(0, std::memcmp(memoryBeyondLimitBefore1.data(), memoryBeyondLimitAddress1, sizeof(TypeParam))); - EXPECT_EQ(0, std::memcmp(memoryBeyondLimitBefore2.data(), memoryBeyondLimitAddress2, sizeof(TypeParam) / 2)); - - EXPECT_EQ(0, std::memcmp(&memory[0], destinationMemoryAddress1, sizeof(TypeParam))); - EXPECT_EQ(0, std::memcmp(&memory[0], destinationMemoryAddress2, sizeof(TypeParam) / 2)); - - EXPECT_EQ(CL_SUCCESS, retVal); - } -} - TYPED_TEST(KernelArgImmediateTest, givenMulitplePatchesAndSecondPatchSizeTooLargeWhenSettingArgThenDontReadMemoryBeyondLimit) { if (sizeof(TypeParam) == 1) return; // multiple patch chars don't make sense @@ -310,17 +272,17 @@ TYPED_TEST(KernelArgImmediateTest, givenMulitplePatchesAndSecondPatchSizeTooLarg const auto destinationMemoryAddress2 = pKernel->getCrossThreadData() + elements[1].offset; const auto memoryBeyondLimitAddress1 = destinationMemoryAddress1 + sizeof(TypeParam) / 2; - const auto memoryBeyondLimitAddress2 = destinationMemoryAddress2 + sizeof(TypeParam) / 2; + const auto memoryBeyondLimitAddress2 = destinationMemoryAddress2 + sizeof(TypeParam); const std::vector memoryBeyondLimitBefore1(memoryBeyondLimitAddress1, memoryBeyondLimitAddress1 + sizeof(TypeParam) / 2); - const std::vector memoryBeyondLimitBefore2(memoryBeyondLimitAddress2, memoryBeyondLimitAddress2 + sizeof(TypeParam) / 2); + const std::vector memoryBeyondLimitBefore2(memoryBeyondLimitAddress2, memoryBeyondLimitAddress2 + sizeof(TypeParam)); elements[0].size = 0; elements[2].sourceOffset = 0; elements[1].sourceOffset = sizeof(TypeParam) / 2; elements[2].size = sizeof(TypeParam) / 2; elements[1].size = sizeof(TypeParam); - auto retVal = pKernel->setArg(3, sizeof(TypeParam), &memory[0]); + auto retVal = pKernel->setArg(3, sizeof(memory), memory); EXPECT_EQ(0, std::memcmp(memoryBeyondLimitBefore1.data(), memoryBeyondLimitAddress1, sizeof(TypeParam) / 2)); EXPECT_EQ(0, std::memcmp(memoryBeyondLimitBefore2.data(), memoryBeyondLimitAddress2, sizeof(TypeParam) / 2)); @@ -333,6 +295,9 @@ TYPED_TEST(KernelArgImmediateTest, givenMulitplePatchesAndSecondPatchSizeTooLarg } TYPED_TEST(KernelArgImmediateTest, givenMultiplePatchesAndOneSourceOffsetBeyondArgumentWhenSettingArgThenDontCopyThisPatch) { + if (sizeof(TypeParam) == 1u) { + GTEST_SKIP(); + } for (auto &rootDeviceIndex : this->context->getRootDeviceIndices()) { auto pKernel = this->pMultiDeviceKernel->getKernel(rootDeviceIndex); TypeParam memory[2]; @@ -345,22 +310,23 @@ TYPED_TEST(KernelArgImmediateTest, givenMultiplePatchesAndOneSourceOffsetBeyondA const auto destinationMemoryAddress2 = pKernel->getCrossThreadData() + elements[2].offset; const auto memoryBeyondLimitAddress1 = destinationMemoryAddress1 + sizeof(TypeParam); - const auto memoryBeyondLimitAddress2 = destinationMemoryAddress2; + const auto memoryBeyondLimitAddress2 = destinationMemoryAddress2 + 1; const std::vector memoryBeyondLimitBefore1(memoryBeyondLimitAddress1, memoryBeyondLimitAddress1 + sizeof(TypeParam)); - const std::vector memoryBeyondLimitBefore2(memoryBeyondLimitAddress2, memoryBeyondLimitAddress2 + sizeof(TypeParam)); + const std::vector memoryBeyondLimitBefore2(memoryBeyondLimitAddress2, memoryBeyondLimitAddress2 + sizeof(TypeParam) - 1); elements[0].size = 0; elements[1].sourceOffset = 0; elements[1].size = sizeof(TypeParam); elements[2].sourceOffset = sizeof(TypeParam); elements[2].size = 1; - auto retVal = pKernel->setArg(3, sizeof(TypeParam), &memory[0]); + auto retVal = pKernel->setArg(3, sizeof(memory), memory); EXPECT_EQ(0, std::memcmp(memoryBeyondLimitBefore1.data(), memoryBeyondLimitAddress1, memoryBeyondLimitBefore1.size())); EXPECT_EQ(0, std::memcmp(memoryBeyondLimitBefore2.data(), memoryBeyondLimitAddress2, memoryBeyondLimitBefore2.size())); EXPECT_EQ(0, std::memcmp(&memory[0], destinationMemoryAddress1, sizeof(TypeParam))); + EXPECT_EQ(0, std::memcmp(&memory[1], destinationMemoryAddress2, 1)); EXPECT_EQ(CL_SUCCESS, retVal); }