Skip to content

Commit 48baf4b

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

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

src/gpu/d3d12/SDL_gpu_d3d12.c

+25
Original file line numberDiff line numberDiff line change
@@ -2473,12 +2473,32 @@ 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 || code == NULL) {
2482+
return false;
2483+
}
2484+
return SDL_memcmp(code, "DXBC", 4) == 0;
2485+
}
2486+
24762487
static bool D3D12_INTERNAL_CreateShaderBytecode(
2488+
D3D12Renderer *renderer,
24772489
const Uint8 *code,
24782490
size_t codeSize,
2491+
SDL_GPUShaderFormat format,
24792492
void **pBytecode,
24802493
size_t *pBytecodeSize)
24812494
{
2495+
if (!D3D12_INTERNAL_IsValidShaderBytecode(code, codeSize)) {
2496+
if (format == SDL_GPU_SHADERFORMAT_DXBC) {
2497+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid DXBC!", false);
2498+
}
2499+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid DXIL!", false);
2500+
}
2501+
24822502
if (pBytecode != NULL) {
24832503
*pBytecode = SDL_malloc(codeSize);
24842504
if (!*pBytecode) {
@@ -2696,8 +2716,10 @@ static SDL_GPUComputePipeline *D3D12_CreateComputePipeline(
26962716
ID3D12PipelineState *pipelineState;
26972717

26982718
if (!D3D12_INTERNAL_CreateShaderBytecode(
2719+
renderer,
26992720
createinfo->code,
27002721
createinfo->code_size,
2722+
createinfo->format,
27012723
&bytecode,
27022724
&bytecodeSize)) {
27032725
return NULL;
@@ -3104,13 +3126,16 @@ static SDL_GPUShader *D3D12_CreateShader(
31043126
SDL_GPURenderer *driverData,
31053127
const SDL_GPUShaderCreateInfo *createinfo)
31063128
{
3129+
D3D12Renderer *renderer = (D3D12Renderer *)driverData;
31073130
void *bytecode;
31083131
size_t bytecodeSize;
31093132
D3D12Shader *shader;
31103133

31113134
if (!D3D12_INTERNAL_CreateShaderBytecode(
3135+
renderer,
31123136
createinfo->code,
31133137
createinfo->code_size,
3138+
createinfo->format,
31143139
&bytecode,
31153140
&bytecodeSize)) {
31163141
return NULL;

src/gpu/metal/SDL_gpu_metal.m

+16
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,17 @@ 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 || code == NULL) {
835+
return false;
836+
}
837+
return SDL_memcmp(code, "MTLB", 4) == 0;
838+
}
839+
829840
// This function assumes that it's called from within an autorelease pool
830841
static MetalLibraryFunction METAL_INTERNAL_CompileShader(
831842
MetalRenderer *renderer,
@@ -854,6 +865,11 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
854865
options:nil
855866
error:&error];
856867
} else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {
868+
if (!METAL_INTERNAL_IsValidMetalLibrary(code, codeSize)) {
869+
SET_STRING_ERROR_AND_RETURN(
870+
"The provided shader code is not a valid Metal library!",
871+
libraryFunction);
872+
}
857873
data = dispatch_data_create(
858874
code,
859875
codeSize,

src/gpu/vulkan/SDL_gpu_vulkan.c

+21
Original file line numberDiff line numberDiff line change
@@ -6488,6 +6488,19 @@ 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 || code == NULL) {
6498+
return false;
6499+
}
6500+
const Uint32 magic = 0x07230203;
6501+
return SDL_memcmp(code, &magic, 4) == 0;
6502+
}
6503+
64916504
static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
64926505
SDL_GPURenderer *driverData,
64936506
const SDL_GPUComputePipelineCreateInfo *createinfo)
@@ -6503,6 +6516,10 @@ static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
65036516
SET_STRING_ERROR_AND_RETURN("Incompatible shader format for Vulkan!", NULL);
65046517
}
65056518

6519+
if (!VULKAN_INTERNAL_IsValidShaderBytecode(createinfo->code, createinfo->code_size)) {
6520+
SET_STRING_ERROR_AND_RETURN("The provided shader code is not valid SPIR-V!", NULL);
6521+
}
6522+
65066523
vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
65076524
shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
65086525
shaderModuleCreateInfo.pNext = NULL;
@@ -6648,6 +6665,10 @@ static SDL_GPUShader *VULKAN_CreateShader(
66486665
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
66496666
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
66506667

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

0 commit comments

Comments
 (0)