mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-24 03:58:28 +00:00
GPU: Validate shader bytecode
This commit is contained in:

committed by
Sam Lantinga

parent
89d7d406ab
commit
6e4ace310c
@@ -2482,12 +2482,32 @@ static D3D12GraphicsRootSignature *D3D12_INTERNAL_CreateGraphicsRootSignature(
|
|||||||
return d3d12GraphicsRootSignature;
|
return d3d12GraphicsRootSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool D3D12_INTERNAL_IsValidShaderBytecode(
|
||||||
|
const Uint8 *code,
|
||||||
|
size_t codeSize)
|
||||||
|
{
|
||||||
|
// Both DXIL and DXBC bytecode have a 4 byte header containing `DXBC`.
|
||||||
|
if (codeSize < 4 || code == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return SDL_memcmp(code, "DXBC", 4) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool D3D12_INTERNAL_CreateShaderBytecode(
|
static bool D3D12_INTERNAL_CreateShaderBytecode(
|
||||||
|
D3D12Renderer *renderer,
|
||||||
const Uint8 *code,
|
const Uint8 *code,
|
||||||
size_t codeSize,
|
size_t codeSize,
|
||||||
|
SDL_GPUShaderFormat format,
|
||||||
void **pBytecode,
|
void **pBytecode,
|
||||||
size_t *pBytecodeSize)
|
size_t *pBytecodeSize)
|
||||||
{
|
{
|
||||||
|
if (!D3D12_INTERNAL_IsValidShaderBytecode(code, codeSize)) {
|
||||||
|
if (format == SDL_GPU_SHADERFORMAT_DXBC) {
|
||||||
|
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid DXBC!", false);
|
||||||
|
}
|
||||||
|
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid DXIL!", false);
|
||||||
|
}
|
||||||
|
|
||||||
if (pBytecode != NULL) {
|
if (pBytecode != NULL) {
|
||||||
*pBytecode = SDL_malloc(codeSize);
|
*pBytecode = SDL_malloc(codeSize);
|
||||||
if (!*pBytecode) {
|
if (!*pBytecode) {
|
||||||
@@ -2705,8 +2725,10 @@ static SDL_GPUComputePipeline *D3D12_CreateComputePipeline(
|
|||||||
ID3D12PipelineState *pipelineState;
|
ID3D12PipelineState *pipelineState;
|
||||||
|
|
||||||
if (!D3D12_INTERNAL_CreateShaderBytecode(
|
if (!D3D12_INTERNAL_CreateShaderBytecode(
|
||||||
|
renderer,
|
||||||
createinfo->code,
|
createinfo->code,
|
||||||
createinfo->code_size,
|
createinfo->code_size,
|
||||||
|
createinfo->format,
|
||||||
&bytecode,
|
&bytecode,
|
||||||
&bytecodeSize)) {
|
&bytecodeSize)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -3113,13 +3135,16 @@ static SDL_GPUShader *D3D12_CreateShader(
|
|||||||
SDL_GPURenderer *driverData,
|
SDL_GPURenderer *driverData,
|
||||||
const SDL_GPUShaderCreateInfo *createinfo)
|
const SDL_GPUShaderCreateInfo *createinfo)
|
||||||
{
|
{
|
||||||
|
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
|
||||||
void *bytecode;
|
void *bytecode;
|
||||||
size_t bytecodeSize;
|
size_t bytecodeSize;
|
||||||
D3D12Shader *shader;
|
D3D12Shader *shader;
|
||||||
|
|
||||||
if (!D3D12_INTERNAL_CreateShaderBytecode(
|
if (!D3D12_INTERNAL_CreateShaderBytecode(
|
||||||
|
renderer,
|
||||||
createinfo->code,
|
createinfo->code,
|
||||||
createinfo->code_size,
|
createinfo->code_size,
|
||||||
|
createinfo->format,
|
||||||
&bytecode,
|
&bytecode,
|
||||||
&bytecodeSize)) {
|
&bytecodeSize)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -836,6 +836,17 @@ typedef struct MetalLibraryFunction
|
|||||||
id<MTLFunction> function;
|
id<MTLFunction> function;
|
||||||
} MetalLibraryFunction;
|
} MetalLibraryFunction;
|
||||||
|
|
||||||
|
static bool METAL_INTERNAL_IsValidMetalLibrary(
|
||||||
|
const Uint8 *code,
|
||||||
|
size_t codeSize)
|
||||||
|
{
|
||||||
|
// Metal libraries have a 4 byte header containing `MTLB`.
|
||||||
|
if (codeSize < 4 || code == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return SDL_memcmp(code, "MTLB", 4) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// This function assumes that it's called from within an autorelease pool
|
// This function assumes that it's called from within an autorelease pool
|
||||||
static MetalLibraryFunction METAL_INTERNAL_CompileShader(
|
static MetalLibraryFunction METAL_INTERNAL_CompileShader(
|
||||||
MetalRenderer *renderer,
|
MetalRenderer *renderer,
|
||||||
@@ -864,6 +875,11 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
|
|||||||
options:nil
|
options:nil
|
||||||
error:&error];
|
error:&error];
|
||||||
} else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {
|
} else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {
|
||||||
|
if (!METAL_INTERNAL_IsValidMetalLibrary(code, codeSize)) {
|
||||||
|
SET_STRING_ERROR_AND_RETURN(
|
||||||
|
"The provided shader code is not a valid Metal library!",
|
||||||
|
libraryFunction);
|
||||||
|
}
|
||||||
data = dispatch_data_create(
|
data = dispatch_data_create(
|
||||||
code,
|
code,
|
||||||
codeSize,
|
codeSize,
|
||||||
|
@@ -6511,6 +6511,25 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
|
|||||||
return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
|
return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool VULKAN_INTERNAL_IsValidShaderBytecode(
|
||||||
|
const Uint8 *code,
|
||||||
|
size_t codeSize)
|
||||||
|
{
|
||||||
|
// SPIR-V bytecode has a 4 byte header containing 0x07230203. SPIR-V is
|
||||||
|
// defined as a stream of words and not a stream of bytes so both byte
|
||||||
|
// orders need to be considered.
|
||||||
|
//
|
||||||
|
// FIXME: It is uncertain if drivers are able to load both byte orders. If
|
||||||
|
// needed we may need to do an optional swizzle internally so apps can
|
||||||
|
// continue to treat shader code as an opaque blob.
|
||||||
|
if (codeSize < 4 || code == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const Uint32 magic = 0x07230203;
|
||||||
|
const Uint32 magicInv = 0x03022307;
|
||||||
|
return SDL_memcmp(code, &magic, 4) == 0 || SDL_memcmp(code, &magicInv, 4) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
|
static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
|
||||||
SDL_GPURenderer *driverData,
|
SDL_GPURenderer *driverData,
|
||||||
const SDL_GPUComputePipelineCreateInfo *createinfo)
|
const SDL_GPUComputePipelineCreateInfo *createinfo)
|
||||||
@@ -6526,6 +6545,10 @@ static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
|
|||||||
SET_STRING_ERROR_AND_RETURN("Incompatible shader format for Vulkan!", NULL);
|
SET_STRING_ERROR_AND_RETURN("Incompatible shader format for Vulkan!", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!VULKAN_INTERNAL_IsValidShaderBytecode(createinfo->code, createinfo->code_size)) {
|
||||||
|
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid SPIR-V!", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
|
vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
|
||||||
shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
shaderModuleCreateInfo.pNext = NULL;
|
shaderModuleCreateInfo.pNext = NULL;
|
||||||
@@ -6671,6 +6694,10 @@ static SDL_GPUShader *VULKAN_CreateShader(
|
|||||||
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
|
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
|
||||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||||
|
|
||||||
|
if (!VULKAN_INTERNAL_IsValidShaderBytecode(createinfo->code, createinfo->code_size)) {
|
||||||
|
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid SPIR-V!", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
vulkanShader = SDL_malloc(sizeof(VulkanShader));
|
vulkanShader = SDL_malloc(sizeof(VulkanShader));
|
||||||
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
vkShaderModuleCreateInfo.pNext = NULL;
|
vkShaderModuleCreateInfo.pNext = NULL;
|
||||||
|
Reference in New Issue
Block a user