fix: Avoid reading unmapped memory in FastTextRenderer - #3376
Conversation
Vulkan says unmapped memory is no longer readable
|
@dotnet-policy-service agree |
|
|
||
| graphicsContext.CommandList.UnmapSubResource(mappedIndices); | ||
|
|
||
| indexBufferBinding = new IndexBufferBinding(Buffer.Index.New(graphicsContext.CommandList.GraphicsDevice, new ReadOnlySpan<byte>((void*)indexPointer, indexBufferSize)), true, indexBufferLength); |
There was a problem hiding this comment.
I think the problem with this code is not using the now unmapped buffer to construct the index buffer, but constructing a new unnecessary index buffer using the pointer. Let me explain:
- The index buffer is created above in line 96 as a dynamic buffer. It is then mapped and populated, then unmapped.
- Then, when creating the
IndexBufferBindinginstead of using our already populatedindexBufferwe do anotherBuffer.Index.Newpassing the now invalid pointer to the data to populate it. But that is exactly what we already did above!
This seems like a mistake from when this was ported from C++ to C#, and not a problem per-se of persisting the pointer incorrectly.
There was a problem hiding this comment.
From my understanding, the way it was before two buffers were used because the final one should be immutable for read optimization, and so a dynamic one was created to fill in the actual data afterwards.
create mutable buffer > fill with data > copy to immutable buffer > cleanup mutable buffer.
My change would then change this to
build data in int[] > copy to immutable buffer
So I guess you could say the double buffering from before was unnecessary, but from as a consumer the fatal issue was what is effectively a "read-after-free".
What do you think if the solution?
I also considered using NativeMemory to avoid GC but that would also mean keeping the unsafe and doing a try/finally.
PR Details
FastTextRenderer.Initializeretained a pointer to mapped index-buffer memory and passed it toBuffer.Index.Newafter unmapping the buffer.On Linux/Vulkan the pointer was no longer valid, which caused an
AccessViolationExceptionwhenBuffer.Index.Newtried to copy the index data.This change builds the indices in a managed
int[]and passes that array directly toBuffer.Index.New.This also removes the temporary graphics buffer and the now-unnecessary
unsafemodifier.I rebuilt the local Stride packages and confirmed that a code-only game using Vulkan can render debug text without crashing.
Related Issue
Fixes #3375
Types of changes
Checklist
I tested the change in a code-only game on Linux/Vulkan.
I did not run Game Studio because it is not currently available on Linux.