Skip to content

Commit dde4b21

Browse files
committed
GPU: Validate shader bytecode
1 parent e236a48 commit dde4b21

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

src/gpu/d3d12/SDL_gpu_d3d12.c

+24
Original file line numberDiff line numberDiff line change
@@ -2473,12 +2473,31 @@ static D3D12GraphicsRootSignature *D3D12_INTERNAL_CreateGraphicsRootSignature(
24732473
return d3d12GraphicsRootSignature;
24742474
}
24752475

2476+
static bool D3D12_INTERNAL_IsValidShaderBytecode(
2477+
const Uint8 *code,
2478+
size_t codeSize)
2479+
{
2480+
// Both DXIL and DXBC bytecode have a 4 byte header containing `DXBC`.
2481+
if (codeSize < 4)
2482+
return false;
2483+
return code[0] == 'D' && code[1] == 'X' && code[2] == 'B' && code[3] == 'C';
2484+
}
2485+
24762486
static bool D3D12_INTERNAL_CreateShaderBytecode(
2487+
D3D12Renderer *renderer,
24772488
const Uint8 *code,
24782489
size_t codeSize,
2490+
SDL_GPUShaderFormat format,
24792491
void **pBytecode,
24802492
size_t *pBytecodeSize)
24812493
{
2494+
if (!D3D12_INTERNAL_IsValidShaderBytecode(code, codeSize)) {
2495+
if (format == SDL_GPU_SHADERFORMAT_DXBC) {
2496+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid DXBC!", false);
2497+
}
2498+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid DXIL!", false);
2499+
}
2500+
24822501
if (pBytecode != NULL) {
24832502
*pBytecode = SDL_malloc(codeSize);
24842503
if (!*pBytecode) {
@@ -2696,8 +2715,10 @@ static SDL_GPUComputePipeline *D3D12_CreateComputePipeline(
26962715
ID3D12PipelineState *pipelineState;
26972716

26982717
if (!D3D12_INTERNAL_CreateShaderBytecode(
2718+
renderer,
26992719
createinfo->code,
27002720
createinfo->code_size,
2721+
createinfo->format,
27012722
&bytecode,
27022723
&bytecodeSize)) {
27032724
return NULL;
@@ -3104,13 +3125,16 @@ static SDL_GPUShader *D3D12_CreateShader(
31043125
SDL_GPURenderer *driverData,
31053126
const SDL_GPUShaderCreateInfo *createinfo)
31063127
{
3128+
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
31073129
void *bytecode;
31083130
size_t bytecodeSize;
31093131
D3D12Shader *shader;
31103132

31113133
if (!D3D12_INTERNAL_CreateShaderBytecode(
3134+
renderer,
31123135
createinfo->code,
31133136
createinfo->code_size,
3137+
createinfo->format,
31143138
&bytecode,
31153139
&bytecodeSize)) {
31163140
return NULL;

src/gpu/metal/SDL_gpu_metal.m

+15
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,16 @@ static void METAL_INTERNAL_TrackUniformBuffer(
826826
id<MTLFunction> function;
827827
} MetalLibraryFunction;
828828

829+
static bool METAL_INTERNAL_IsValidMetalLibrary(
830+
const Uint8 *code,
831+
size_t codeSize)
832+
{
833+
// Metal libraries have a 4 byte header containing `MTLB`.
834+
if (codeSize < 4)
835+
return false;
836+
return code[0] == 'M' && code[1] == 'T' && code[2] == 'L' && code[3] == 'B';
837+
}
838+
829839
// This function assumes that it's called from within an autorelease pool
830840
static MetalLibraryFunction METAL_INTERNAL_CompileShader(
831841
MetalRenderer *renderer,
@@ -854,6 +864,11 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
854864
options:nil
855865
error:&error];
856866
} else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {
867+
if (!METAL_INTERNAL_IsValidMetalLibrary(code, codeSize)) {
868+
SET_STRING_ERROR_AND_RETURN(
869+
"The provided shader code is not a valid Metal library!",
870+
libraryFunction);
871+
}
857872
data = dispatch_data_create(
858873
code,
859874
codeSize,

src/gpu/vulkan/SDL_gpu_vulkan.c

+20
Original file line numberDiff line numberDiff line change
@@ -6488,6 +6488,18 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
64886488
return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
64896489
}
64906490

6491+
static bool VULKAN_INTERNAL_IsValidShaderBytecode(
6492+
const Uint8 *code,
6493+
size_t codeSize)
6494+
{
6495+
// SPIR-V bytecode has a 4 byte header containing 0x07230203 in the current
6496+
// platform's endianness.
6497+
if (codeSize < 4)
6498+
return false;
6499+
uint32_t magic = *(uint32_t*)code;
6500+
return magic == 0x07230203;
6501+
}
6502+
64916503
static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
64926504
SDL_GPURenderer *driverData,
64936505
const SDL_GPUComputePipelineCreateInfo *createinfo)
@@ -6503,6 +6515,10 @@ static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
65036515
SET_STRING_ERROR_AND_RETURN("Incompatible shader format for Vulkan!", NULL);
65046516
}
65056517

6518+
if (!VULKAN_INTERNAL_IsValidShaderBytecode(createinfo->code, createinfo->code_size)) {
6519+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid SPIR-V!", NULL);
6520+
}
6521+
65066522
vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
65076523
shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
65086524
shaderModuleCreateInfo.pNext = NULL;
@@ -6648,6 +6664,10 @@ static SDL_GPUShader *VULKAN_CreateShader(
66486664
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
66496665
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
66506666

6667+
if (!VULKAN_INTERNAL_IsValidShaderBytecode(createinfo->code, createinfo->code_size)) {
6668+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid SPIR-V!", NULL);
6669+
}
6670+
66516671
vulkanShader = SDL_malloc(sizeof(VulkanShader));
66526672
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
66536673
vkShaderModuleCreateInfo.pNext = NULL;

0 commit comments

Comments
 (0)