From 02d8eb393ea5db20d73b35f57563beac6d76edbe Mon Sep 17 00:00:00 2001 From: joselope Date: Wed, 29 Apr 2026 15:42:52 +0100 Subject: [PATCH 1/2] Add coverage for memfill and fillbuffer with a corrupted pattern --- test_conformance/SVM/test_enqueue_api.cpp | 124 +++++++++++++++++ test_conformance/buffers/test_buffer_fill.cpp | 131 +++++++++++++++++- 2 files changed, 254 insertions(+), 1 deletion(-) diff --git a/test_conformance/SVM/test_enqueue_api.cpp b/test_conformance/SVM/test_enqueue_api.cpp index 83e0b9afd4..5f34a1a3b1 100644 --- a/test_conformance/SVM/test_enqueue_api.cpp +++ b/test_conformance/SVM/test_enqueue_api.cpp @@ -349,3 +349,127 @@ REGISTER_TEST(svm_enqueue_api) return 0; } + +// Tests corrupting the pattern before clEnqueueSVMMemFill is executed +REGISTER_TEST(svm_memfill_pattern_lifetime) +{ + constexpr cl_int FILL_PATTERN = 0x12345678; + + clContextWrapper contextWrapper = nullptr; + clCommandQueueWrapper queues[MAXQ]; + cl_uint num_devices = 0; + cl_int err = CL_SUCCESS; + + const size_t svm_size = num_elements * sizeof(cl_int); + + cl_int *svm_ptr = nullptr; + cl_int *pattern = nullptr; + cl_event user_event = nullptr; + cl_event fill_event = nullptr; + + int result = TEST_FAIL; + + err = create_cl_objects(device, nullptr, &contextWrapper, nullptr, + &queues[0], &num_devices, + CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + if (err) goto cleanup; + + context = contextWrapper; + queue = queues[0]; + + svm_ptr = static_cast(clSVMAlloc(context, CL_MEM_READ_WRITE, svm_size, 0)); + if (!svm_ptr) + { + log_error("clSVMAlloc failed\n"); + goto cleanup; + } + + user_event = clCreateUserEvent(context, &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateUserEvent failed"); + goto cleanup; + } + + pattern = static_cast(malloc(sizeof(cl_int))); + if (!pattern) + { + log_error("Failed to allocate pattern memory\n"); + goto cleanup; + } + *pattern = FILL_PATTERN; + + err = clEnqueueSVMMemFill(queue, + svm_ptr, + pattern, + sizeof(cl_int), + svm_size, + 1, + &user_event, + &fill_event); + if (err != CL_SUCCESS) + { + print_error(err, "clEnqueueSVMMemFill failed"); + goto cleanup; + } + + /* corrupt pattern while command is blocked */ + *pattern = static_cast(0xDEADBEEF); + + err = clSetUserEventStatus(user_event, CL_COMPLETE); + if (err != CL_SUCCESS) + { + print_error(err, "clSetUserEventStatus failed"); + goto cleanup; + } + + err = clWaitForEvents(1, &fill_event); + if (err != CL_SUCCESS) + { + print_error(err, "clWaitForEvents failed"); + goto cleanup; + } + + err = clEnqueueSVMMap(queue, CL_TRUE, CL_MAP_READ, + svm_ptr, svm_size, + 0, nullptr, nullptr); + if (err != CL_SUCCESS) + { + print_error(err, "clEnqueueSVMMap failed"); + goto cleanup; + } + + for (size_t i = 0; i < num_elements; i++) + { + if (svm_ptr[i] != FILL_PATTERN) + { + log_error("Verification failed at index %zu: expected 0x%08x, got 0x%08x\n", + i, FILL_PATTERN, svm_ptr[i]); + goto cleanup; + } + } + + err = clEnqueueSVMUnmap(queue, svm_ptr, 0, nullptr, nullptr); + if (err != CL_SUCCESS) + { + print_error(err, "clEnqueueSVMUnmap failed"); + goto cleanup; + } + + err = clFinish(queue); + if (err != CL_SUCCESS) + { + print_error(err, "clFinish failed"); + goto cleanup; + } + + result = TEST_PASS; + +cleanup: + if (fill_event) clReleaseEvent(fill_event); + if (user_event) clReleaseEvent(user_event); + if (pattern) free(pattern); + if (svm_ptr) clSVMFree(context, svm_ptr); + + return result; +} \ No newline at end of file diff --git a/test_conformance/buffers/test_buffer_fill.cpp b/test_conformance/buffers/test_buffer_fill.cpp index d8fa76549a..f133fbfa44 100644 --- a/test_conformance/buffers/test_buffer_fill.cpp +++ b/test_conformance/buffers/test_buffer_fill.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2017 The Khronos Group Inc. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -557,6 +557,18 @@ static int verify_fill_struct( void *ptr1, void *ptr2, int n ) } +static int verify_pattern_lifetime(cl_int *buffer, size_t num_elements, + cl_int expected_value) +{ + for (size_t i = 0; i < num_elements; i++) { + if (buffer[i] != expected_value) + return -1; + + } + return 0; +} + + static int test_buffer_fill(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements, size_t size, char *type, int loops, void *inptr[5], @@ -709,6 +721,109 @@ static int test_buffer_fill(cl_device_id deviceID, cl_context context, } // end test_buffer_fill() + +static int test_fill_reused_pattern(cl_device_id device_id, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + cl_int err; + const size_t buffer_bytes = num_elements * sizeof(cl_int); + + cl_mem buffer = nullptr; + cl_event user_event = nullptr; + cl_event fill_event = nullptr; + cl_int *pattern = nullptr; + cl_int *host_buffer = nullptr; + + int result = TEST_FAIL; + + buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, + buffer_bytes, nullptr, &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateBuffer failed"); + goto cleanup; + } + + user_event = clCreateUserEvent(context, &err); + if (err != CL_SUCCESS) + { + print_error(err, "clCreateUserEvent failed"); + goto cleanup; + } + + pattern = static_cast(malloc(sizeof(cl_int))); + if (!pattern) + { + log_error("Failed to allocate pattern memory\n"); + goto cleanup; + } + *pattern = TEST_PRIME_INT; + + err = clEnqueueFillBuffer(queue, buffer, + pattern, sizeof(cl_int), + 0, buffer_bytes, + 1, &user_event, &fill_event); + if (err != CL_SUCCESS) + { + print_error(err, "clEnqueueFillBuffer failed"); + goto cleanup; + } + + /* Modify pattern while command is blocked */ + *pattern = static_cast(0xDEADBEEF); + + err = clSetUserEventStatus(user_event, CL_COMPLETE); + if (err != CL_SUCCESS) + { + print_error(err, "clSetUserEventStatus failed"); + goto cleanup; + } + + err = clWaitForEvents(1, &fill_event); + if (err != CL_SUCCESS) + { + print_error(err, "clWaitForEvents failed"); + goto cleanup; + } + + host_buffer = static_cast(malloc(buffer_bytes)); + if (!host_buffer) + { + log_error("Failed to allocate host buffer\n"); + goto cleanup; + } + + err = clEnqueueReadBuffer(queue, buffer, CL_TRUE, + 0, buffer_bytes, + host_buffer, 0, nullptr, nullptr); + if (err != CL_SUCCESS) + { + print_error(err, "clEnqueueReadBuffer failed"); + goto cleanup; + } + + if (verify_pattern_lifetime(host_buffer, + num_elements, + TEST_PRIME_INT) != 0) + { + log_error("buffer_fill pattern lifetime test failed - driver used freed/corrupted pattern memory\n"); + goto cleanup; + } + + result = TEST_PASS; + +cleanup: + if (host_buffer) free(host_buffer); + if (pattern) free(pattern); + if (fill_event) clReleaseEvent(fill_event); + if (user_event) clReleaseEvent(user_event); + if (buffer) clReleaseMemObject(buffer); + + return result; +} // end test_fill_pattern_freed_and_corrupted() + REGISTER_TEST(buffer_fill_struct) { TestStruct pattern; @@ -1510,3 +1625,17 @@ REGISTER_TEST(buffer_fill_float) return err; } // end test_buffer_float_fill() + + +REGISTER_TEST(buffer_fill_pattern_lifetime) +{ + int err = 0; + if (test_fill_reused_pattern(device, context, queue, + num_elements) + != TEST_PASS) { + err++; + } + + return err; + +} // end test_buffer_fill_pattern_lifetime() From 2acad7eaffb7ff8119faece9d850b4b3c84200ae Mon Sep 17 00:00:00 2001 From: joselope Date: Wed, 29 Apr 2026 16:16:07 +0100 Subject: [PATCH 2/2] Apply clang-format --- test_conformance/SVM/test_enqueue_api.cpp | 27 +++++------- test_conformance/buffers/test_buffer_fill.cpp | 44 ++++++++----------- 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/test_conformance/SVM/test_enqueue_api.cpp b/test_conformance/SVM/test_enqueue_api.cpp index 5f34a1a3b1..e36bc2cd2e 100644 --- a/test_conformance/SVM/test_enqueue_api.cpp +++ b/test_conformance/SVM/test_enqueue_api.cpp @@ -369,15 +369,16 @@ REGISTER_TEST(svm_memfill_pattern_lifetime) int result = TEST_FAIL; - err = create_cl_objects(device, nullptr, &contextWrapper, nullptr, - &queues[0], &num_devices, - CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); + err = + create_cl_objects(device, nullptr, &contextWrapper, nullptr, &queues[0], + &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER); if (err) goto cleanup; context = contextWrapper; queue = queues[0]; - svm_ptr = static_cast(clSVMAlloc(context, CL_MEM_READ_WRITE, svm_size, 0)); + svm_ptr = static_cast( + clSVMAlloc(context, CL_MEM_READ_WRITE, svm_size, 0)); if (!svm_ptr) { log_error("clSVMAlloc failed\n"); @@ -399,14 +400,8 @@ REGISTER_TEST(svm_memfill_pattern_lifetime) } *pattern = FILL_PATTERN; - err = clEnqueueSVMMemFill(queue, - svm_ptr, - pattern, - sizeof(cl_int), - svm_size, - 1, - &user_event, - &fill_event); + err = clEnqueueSVMMemFill(queue, svm_ptr, pattern, sizeof(cl_int), svm_size, + 1, &user_event, &fill_event); if (err != CL_SUCCESS) { print_error(err, "clEnqueueSVMMemFill failed"); @@ -430,9 +425,8 @@ REGISTER_TEST(svm_memfill_pattern_lifetime) goto cleanup; } - err = clEnqueueSVMMap(queue, CL_TRUE, CL_MAP_READ, - svm_ptr, svm_size, - 0, nullptr, nullptr); + err = clEnqueueSVMMap(queue, CL_TRUE, CL_MAP_READ, svm_ptr, svm_size, 0, + nullptr, nullptr); if (err != CL_SUCCESS) { print_error(err, "clEnqueueSVMMap failed"); @@ -443,7 +437,8 @@ REGISTER_TEST(svm_memfill_pattern_lifetime) { if (svm_ptr[i] != FILL_PATTERN) { - log_error("Verification failed at index %zu: expected 0x%08x, got 0x%08x\n", + log_error("Verification failed at index %zu: expected 0x%08x, got " + "0x%08x\n", i, FILL_PATTERN, svm_ptr[i]); goto cleanup; } diff --git a/test_conformance/buffers/test_buffer_fill.cpp b/test_conformance/buffers/test_buffer_fill.cpp index f133fbfa44..7c3f37d12d 100644 --- a/test_conformance/buffers/test_buffer_fill.cpp +++ b/test_conformance/buffers/test_buffer_fill.cpp @@ -560,10 +560,9 @@ static int verify_fill_struct( void *ptr1, void *ptr2, int n ) static int verify_pattern_lifetime(cl_int *buffer, size_t num_elements, cl_int expected_value) { - for (size_t i = 0; i < num_elements; i++) { - if (buffer[i] != expected_value) - return -1; - + for (size_t i = 0; i < num_elements; i++) + { + if (buffer[i] != expected_value) return -1; } return 0; } @@ -721,11 +720,8 @@ static int test_buffer_fill(cl_device_id deviceID, cl_context context, } // end test_buffer_fill() - -static int test_fill_reused_pattern(cl_device_id device_id, - cl_context context, - cl_command_queue queue, - int num_elements) +static int test_fill_reused_pattern(cl_device_id device_id, cl_context context, + cl_command_queue queue, int num_elements) { cl_int err; const size_t buffer_bytes = num_elements * sizeof(cl_int); @@ -738,8 +734,8 @@ static int test_fill_reused_pattern(cl_device_id device_id, int result = TEST_FAIL; - buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, - buffer_bytes, nullptr, &err); + buffer = + clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_bytes, nullptr, &err); if (err != CL_SUCCESS) { print_error(err, "clCreateBuffer failed"); @@ -761,10 +757,8 @@ static int test_fill_reused_pattern(cl_device_id device_id, } *pattern = TEST_PRIME_INT; - err = clEnqueueFillBuffer(queue, buffer, - pattern, sizeof(cl_int), - 0, buffer_bytes, - 1, &user_event, &fill_event); + err = clEnqueueFillBuffer(queue, buffer, pattern, sizeof(cl_int), 0, + buffer_bytes, 1, &user_event, &fill_event); if (err != CL_SUCCESS) { print_error(err, "clEnqueueFillBuffer failed"); @@ -795,8 +789,7 @@ static int test_fill_reused_pattern(cl_device_id device_id, goto cleanup; } - err = clEnqueueReadBuffer(queue, buffer, CL_TRUE, - 0, buffer_bytes, + err = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, buffer_bytes, host_buffer, 0, nullptr, nullptr); if (err != CL_SUCCESS) { @@ -804,11 +797,10 @@ static int test_fill_reused_pattern(cl_device_id device_id, goto cleanup; } - if (verify_pattern_lifetime(host_buffer, - num_elements, - TEST_PRIME_INT) != 0) + if (verify_pattern_lifetime(host_buffer, num_elements, TEST_PRIME_INT) != 0) { - log_error("buffer_fill pattern lifetime test failed - driver used freed/corrupted pattern memory\n"); + log_error("buffer_fill pattern lifetime test failed - driver used " + "freed/corrupted pattern memory\n"); goto cleanup; } @@ -822,7 +814,7 @@ static int test_fill_reused_pattern(cl_device_id device_id, if (buffer) clReleaseMemObject(buffer); return result; -} // end test_fill_pattern_freed_and_corrupted() +} // end test_fill_pattern_freed_and_corrupted() REGISTER_TEST(buffer_fill_struct) { @@ -1630,12 +1622,12 @@ REGISTER_TEST(buffer_fill_float) REGISTER_TEST(buffer_fill_pattern_lifetime) { int err = 0; - if (test_fill_reused_pattern(device, context, queue, - num_elements) - != TEST_PASS) { + if (test_fill_reused_pattern(device, context, queue, num_elements) + != TEST_PASS) + { err++; } return err; -} // end test_buffer_fill_pattern_lifetime() +} // end test_buffer_fill_pattern_lifetime()