From deb313dd99ecf4aa4cdbb236bc1f7eae9e7f4087 Mon Sep 17 00:00:00 2001 From: Davis Gallinghouse 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 fdce2e3f4c..58b48af2c4 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 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) {