Skip to content

Commit

Permalink
Test parts of API with libFuzzer.
Browse files Browse the repository at this point in the history
  • Loading branch information
PatKamin committed Jul 19, 2023
1 parent 9b5b8b9 commit 8f53448
Show file tree
Hide file tree
Showing 5 changed files with 417 additions and 0 deletions.
63 changes: 63 additions & 0 deletions source/adapters/null/ur_null.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,68 @@ context_t::context_t() {
}
return UR_RESULT_SUCCESS;
};

//////////////////////////////////////////////////////////////////////////
urDdiTable.USM.pfnHostAlloc =
[](ur_context_handle_t hContext, const ur_usm_desc_t *pUSMDesc,
ur_usm_pool_handle_t pool, size_t size, void **ppMem) {
if (size == 0) {
*ppMem = nullptr;
return UR_RESULT_ERROR_UNSUPPORTED_SIZE;
}
*ppMem = malloc(size);
if (ppMem == nullptr) {
return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}
return UR_RESULT_SUCCESS;
};

//////////////////////////////////////////////////////////////////////////
urDdiTable.USM.pfnDeviceAlloc =
[](ur_context_handle_t hContext, ur_device_handle_t hDevice,
const ur_usm_desc_t *pUSMDesc, ur_usm_pool_handle_t pool,
size_t size, void **ppMem) {
if (size == 0) {
*ppMem = nullptr;
return UR_RESULT_ERROR_UNSUPPORTED_SIZE;
}
*ppMem = malloc(size);
if (ppMem == nullptr) {
return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}
return UR_RESULT_SUCCESS;
};

//////////////////////////////////////////////////////////////////////////
urDdiTable.USM.pfnFree = [](ur_context_handle_t hContext, void *pMem) {
free(pMem);
return UR_RESULT_SUCCESS;
};

//////////////////////////////////////////////////////////////////////////
urDdiTable.USM.pfnGetMemAllocInfo =
[](ur_context_handle_t hContext, const void *pMem,
ur_usm_alloc_info_t propName, size_t propSize, void *pPropValue,
size_t *pPropSizeRet) {
switch (propName) {
case UR_USM_ALLOC_INFO_TYPE:
*reinterpret_cast<ur_usm_type_t *>(pPropValue) =
pMem ? UR_USM_TYPE_DEVICE : UR_USM_TYPE_UNKNOWN;
if (pPropSizeRet != nullptr) {
*pPropSizeRet = sizeof(ur_usm_type_t);
}
break;
case UR_USM_ALLOC_INFO_SIZE:
*reinterpret_cast<size_t *>(pPropValue) = pMem ? SIZE_MAX : 0;
if (pPropSizeRet != nullptr) {
*pPropSizeRet = sizeof(size_t);
}
break;
default:
pPropValue = nullptr;
break;
}
return UR_RESULT_SUCCESS;
};
}
} // namespace driver
21 changes: 21 additions & 0 deletions test/conformance/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,23 @@ function(add_conformance_test_with_platform_environment name)
target_compile_definitions("test-${name}" PRIVATE PLATFORM_ENVIRONMENT)
endfunction()

function(add_fuzz_test name)
set(TEST_TARGET_NAME fuzztest-${name})
add_executable(${TEST_TARGET_NAME}
${ARGN})
target_link_libraries(${TEST_TARGET_NAME}
PRIVATE
${PROJECT_NAME}::loader
${PROJECT_NAME}::headers
${PROJECT_NAME}::common
-fsanitize=fuzzer)
add_test(NAME ${TEST_TARGET_NAME}
COMMAND ${TEST_TARGET_NAME} -max_total_time=10 -seed=1 -shrink=1
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_tests_properties(${TEST_TARGET_NAME} PROPERTIES LABELS "fuzz")
target_compile_options(${TEST_TARGET_NAME} PRIVATE -g -fsanitize=fuzzer)
endfunction()

add_subdirectory(testing)

add_subdirectory(platform)
Expand Down Expand Up @@ -74,3 +91,7 @@ if(DEFINED UR_DPCXX)
add_subdirectory(program)
add_subdirectory(enqueue)
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_subdirectory(fuzz)
endif()
7 changes: 7 additions & 0 deletions test/conformance/fuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (C) 2023 Intel Corporation
# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
# See LICENSE.TXT
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

add_fuzz_test(conformance
urConformanceFuzz.cpp)
200 changes: 200 additions & 0 deletions test/conformance/fuzz/urConformanceFuzz copy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// Copyright (C) 2023 Intel Corporation
// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE.TXT
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cassert>
#include <cstring>
#include <vector>

#include "ur_api.h"

struct FuzzData {
uint16_t platform_count;
uint16_t device_count;
uint8_t device_type;
uint32_t device_alloc_size;
uint32_t host_alloc_size;
uint8_t usm_alloc_info_prop_name;
uint16_t usm_alloc_info_prop_size;
void *usm_alloc_info_prop_value;
uint16_t num_subdevices;
ur_context_properties_t context_props;
};

int ParseData(uint8_t *data, size_t size, FuzzData *fuzz_data) {
// Make sure fuzzer data size is sufficient to store all variables
if (size < sizeof(*fuzz_data)) {
return -1;
}

uint8_t *data_ptr = data;
memcpy(&fuzz_data->platform_count, data_ptr,
sizeof(fuzz_data->platform_count));
// Limit the max number of platforms to avoid allocating too much memory for a vector
if (fuzz_data->platform_count > 1024) {
return -1;
}
data_ptr += sizeof(fuzz_data->platform_count);

memcpy(&fuzz_data->device_count, data_ptr, sizeof(fuzz_data->device_count));
data_ptr += sizeof(fuzz_data->device_count);

memcpy(&fuzz_data->device_type, data_ptr, sizeof(fuzz_data->device_type));
// Pass only integers which can be a valid device type
if (fuzz_data->device_type > 7) {
return -1;
}
data_ptr += sizeof(fuzz_data->device_type);

memcpy(&fuzz_data->device_alloc_size, data_ptr,
sizeof(fuzz_data->device_alloc_size));
// Limit the max size of allocations
if (fuzz_data->device_alloc_size > 1 * 1024 * 1024) {
return -1;
}
data_ptr += sizeof(fuzz_data->device_alloc_size);

memcpy(&fuzz_data->host_alloc_size, data_ptr,
sizeof(fuzz_data->host_alloc_size));
// Limit the max size of allocations
if (fuzz_data->host_alloc_size > 1 * 1024 * 1024) {
return -1;
}
data_ptr += sizeof(fuzz_data->host_alloc_size);

memcpy(&fuzz_data->usm_alloc_info_prop_name, data_ptr,
sizeof(fuzz_data->usm_alloc_info_prop_name));
// Pass only integers which can be a valid memory alloc info property name
if (fuzz_data->usm_alloc_info_prop_name > 4) {
return -1;
}
data_ptr += sizeof(fuzz_data->usm_alloc_info_prop_name);

memcpy(&fuzz_data->usm_alloc_info_prop_size, data_ptr,
sizeof(fuzz_data->usm_alloc_info_prop_size));
// Limit the max size of the allocation
if (fuzz_data->usm_alloc_info_prop_size > UINT16_MAX) {
return -1;
}
// Make sure fuzzer data size is sufficient to store property data
if (size < sizeof(*fuzz_data) + fuzz_data->usm_alloc_info_prop_size) {
return -1;
}
data_ptr += sizeof(fuzz_data->usm_alloc_info_prop_size);

fuzz_data->usm_alloc_info_prop_value = data_ptr;
data_ptr += fuzz_data->usm_alloc_info_prop_size;

memcpy(&fuzz_data->num_subdevices, data_ptr,
sizeof(fuzz_data->num_subdevices));
// Limit the max number of subdevices to avoid allocating too much memory for a vector
if (fuzz_data->num_subdevices > 1024) {
return -1;
}
data_ptr += sizeof(fuzz_data->num_subdevices);

memcpy(&fuzz_data->context_props.stype, data_ptr,
sizeof(fuzz_data->context_props.stype));
data_ptr += sizeof(fuzz_data->context_props.stype);
fuzz_data->context_props.pNext = nullptr;
data_ptr += sizeof(fuzz_data->context_props.pNext);
memcpy(&fuzz_data->context_props.flags, data_ptr,
sizeof(fuzz_data->context_props.flags));
data_ptr += sizeof(fuzz_data->context_props.flags);

return 0;
}

extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
FuzzData fuzz_data;
int ret = ParseData(data, size, &fuzz_data);
if (ret) {
return ret;
}

//// API calls
ur_result_t res = UR_RESULT_SUCCESS;

res = urInit(0);
if (res != UR_RESULT_SUCCESS) {
return 0;
}

// Get valid platforms
std::vector<ur_platform_handle_t> platforms;
uint32_t platformCount = 0;

res = urPlatformGet(fuzz_data.platform_count, nullptr, &platformCount);
if (res != UR_RESULT_SUCCESS) {
return 0;
}
platformCount =
platformCount ? fuzz_data.platform_count % platformCount : 0;
platforms.resize(platformCount);
res = urPlatformGet(platformCount, platforms.data(), nullptr);
if (res != UR_RESULT_SUCCESS || platformCount == 0) {
return 0;
}

// Get valid devices of a random platform
ur_platform_handle_t platform =
platforms[fuzz_data.platform_count % platforms.size()];
std::vector<ur_device_handle_t> devices;
uint32_t deviceCount = 0;
ur_device_type_t deviceType =
static_cast<ur_device_type_t>(fuzz_data.device_type);

res = urDeviceGet(platform, deviceType, fuzz_data.device_count, nullptr,
&deviceCount);
if (res != UR_RESULT_SUCCESS) {
return 0;
}
deviceCount = deviceCount ? fuzz_data.device_count % deviceCount : 0;
devices.resize(deviceCount);
res = urDeviceGet(platform, deviceType, devices.size(), devices.data(),
nullptr);
if (res != UR_RESULT_SUCCESS || deviceCount == 0) {
return 0;
}

// Test API
ur_context_handle_t context;
void *host_ptr = nullptr;
void *device_ptr = nullptr;
size_t usm_alloc_info_size = 0;
ur_device_handle_t device =
devices[fuzz_data.device_count % devices.size()];
ur_usm_type_t device_type = UR_USM_TYPE_UNKNOWN;
const char *msg = nullptr;
int32_t error_code = -1;
ur_usm_pool_handle_t pool;
std::vector<ur_device_handle_t> subdevices(fuzz_data.num_subdevices);

urContextCreate(devices.size(), devices.data(), &fuzz_data.context_props,
&context);
urUSMPoolCreate(context, nullptr, &pool);
urUSMHostAlloc(context, nullptr, pool, fuzz_data.host_alloc_size,
&host_ptr);
if (fuzz_data.host_alloc_size != 0) {
memset(host_ptr, 'H', fuzz_data.host_alloc_size);
} else {
assert(host_ptr == nullptr);
}
urUSMDeviceAlloc(context, device, nullptr, pool,
fuzz_data.device_alloc_size, &device_ptr);

urPlatformGetLastError(platform, &msg, &error_code);

urDevicePartition(device, nullptr, subdevices.size(), subdevices.data(),
nullptr);

urUSMFree(context, host_ptr);
urUSMFree(context, device_ptr);
urUSMPoolRelease(pool);
for (auto &device : devices) {
urDeviceRelease(device);
}
urContextRelease(context);
return 0;
}
Loading

0 comments on commit 8f53448

Please sign in to comment.