From deb313dd99ecf4aa4cdbb236bc1f7eae9e7f4087 Mon Sep 17 00:00:00 2001
From: Davis Gallinghouse <[EMAIL REDACTED]>
Date: Mon, 2 Sep 2024 08:05:43 -0500
Subject: [PATCH] GPU: Compile Metal shader source from NSString
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Using the @() syntax to construct an NSString assumes the parenthesized
pointer is null-terminated, but the Metal shader source included in
render/sdlgpu/shaders/metal.h is not null-terminated.
Quoting the clang documentation on Objective-C literals:
When the type of the parenthesized expression is (char *) or (const
char *), the result of the boxed expression is a pointer to an
NSString object containing equivalent character data, which is
assumed to be ‘\0’-terminated and UTF-8 encoded.
Because the @() syntax assumes null-termination, it may read garbage
data after the shader source (up to the next null byte), which can then
cause the Metal shader compiler to fail. To prevent this, instead of
using the @() boxing syntax, we explicitly construct an NSString using
the string length passed by the caller.
---
src/gpu/metal/SDL_gpu_metal.m | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m
index fdce2e3f4c532..58b48af2c4829 100644
--- a/src/gpu/metal/SDL_gpu_metal.m
+++ b/src/gpu/metal/SDL_gpu_metal.m
@@ -740,8 +740,12 @@ static MetalLibraryFunction METAL_INTERNAL_CompileShader(
id<MTLFunction> function;
if (format == SDL_GPU_SHADERFORMAT_MSL) {
+ NSString *codeString = [[NSString alloc]
+ initWithBytes:code
+ length:codeSize
+ encoding:NSUTF8StringEncoding];
library = [renderer->device
- newLibraryWithSource:@((const char *)code)
+ newLibraryWithSource:codeString
options:nil
error:&error];
} else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {