Version/Branch of Dear ImGui:
Branch: docking, commit: 417f5ed
Back-ends:
imgui_impl_vulkan.cpp + imgui_impl_sdl3.cpp
Compiler, OS:
Windows 10, zig cc (v0.16.0)
Full config/build information:
Utilising imgui+docking via https://github.com/tiawl/cimgui.zig.git#68c0ed133ed317061baad3a3ae56cd2940c61a62 (a thin zig-build system wrapper for imgui, with c-bindings generated using dear_bindings).
SDL3 + Vulkan
The working demo is tiny, git access can be provided if desired (private gitlab repo).
Details:
I believe there is a use-after-free of &wd->SurfaceFormat.format inside imgui_impl_vulkan.cpp with dynamic rendering on the docking branch.
Disclaimer: I did use Claude to help dig into the issue, but the report is 100% artisanal.
I have a 100% crash repro with a basic hello world setup with SDL3 + Vulkan, using dynamic rendering, when dragging a panel into its own window, returning it and docking it inside the main one, and then moving it into its own window again.
Further below there is a code example below recreates this inside the imgui SDL3 + Vulkan example (not a crash, but via logging).
My zig callstack is:
thread 7188 panic: load of value 2863311530, which is not valid for type 'const VkFormat'
D:\dev\playphyszig\zig-pkg\cimgui_zig-1.0.0-2XubksPPvwDUY1zt1EGL16m1Zr-a53ZGn13PsqjChWhk\dcimgui\docking\backends\imgui_impl_vulkan.cpp:1525: 0x7ff6654aa519 in ImGui_ImplVulkanH_SelectSurfaceFormat (cimgui.lib)
if (avail_format[avail_i].format == request_formats[request_i] && avail_format[avail_i].colorSpace == request_color_space)
D:\dev\playphyszig\zig-pkg\cimgui_zig-1.0.0-2XubksPPvwDUY1zt1EGL16m1Zr-a53ZGn13PsqjChWhk\dcimgui\docking\backends\imgui_impl_vulkan.cpp:2015: 0x7ff6654b2620 in ImGui_ImplVulkan_CreateWindow (cimgui.lib)
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(v->PhysicalDevice, wd->Surface, requestSurfaceImageFormats.Data, requestSurfaceImageFormats.Size, requestSurfaceColorSpace);
D:\dev\playphyszig\zig-pkg\cimgui_zig-1.0.0-2XubksPPvwDUY1zt1EGL16m1Zr-a53ZGn13PsqjChWhk\dcimgui\docking\imgui.cpp:17429: 0x7ff665173c27 in ImGui::UpdatePlatformWindows (cimgui.lib)
g.PlatformIO.Renderer_CreateWindow(viewport);
D:\dev\playphyszig\zig-pkg\cimgui_zig-1.0.0-2XubksPPvwDUY1zt1EGL16m1Zr-a53ZGn13PsqjChWhk\dcimgui\docking\dcimgui.cpp:2806: 0x7ff664cd583e in ImGui_UpdatePlatformWindows (cimgui.lib)
::ImGui::UpdatePlatformWindows();
D:\dev\playphyszig\src\engine\imgui\root.zig:146:34: 0x7ff664bdd17b in updatePlatformWindows (playphys_zcu.obj)
c.ImGui_UpdatePlatformWindows();
The value is "0xAAAAAAAA" - either uninitialised or freed memory by my zig allocator.
Editing the block ~line 2032 from:
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (wd->UseDynamicRendering)
{
pipeline_info->PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 1;
pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = &wd->SurfaceFormat.format;
}
else
{
pipeline_info->RenderPass = wd->RenderPass;
}
#endif
bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports);
}
to
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (wd->UseDynamicRendering)
{
pipeline_info->PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 1;
pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = &wd->SurfaceFormat.format;
bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports);
pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = nullptr;
pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 0;
}
else
{
pipeline_info->RenderPass = wd->RenderPass;
bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports);
}
#else
bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, &v->PipelineInfoForViewports);
#endif
}
Resolves the crash. I am not certain that this is the correct fix - again, I'm not a rendering engineer - but it does resolve my crash.
My goal for this issue report: confirm if what I'm seeing is correct, report it so you guys know about it, and get it fixed properly with time. I have a local workaround so I'm okay for now.
Minimal, Complete and Verifiable Example code:
First patch is to add dynamic rendering to the SDL3+Vulkan example.
Note: I am not a rendering engineer and this was LLM assisted.
From 7ba9481a3704d10a8c4fdb6e16cb456887aa0fa7 Mon Sep 17 00:00:00 2001
From: Vikram Saran <contact@vikram.codes>
Date: Mon, 4 May 2026 11:46:17 +0200
Subject: [PATCH] Enable dynamic rendering in the SDL3+Vulkan Example
---
examples/example_sdl3_vulkan/main.cpp | 81 ++++++++++++++++++++++++---
1 file changed, 72 insertions(+), 9 deletions(-)
diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp
index e961ca1c0..0935971db 100644
--- a/examples/example_sdl3_vulkan/main.cpp
+++ b/examples/example_sdl3_vulkan/main.cpp
@@ -51,6 +51,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static uint32_t g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
+static ImVector<VkSemaphore> g_AcquireSemaphores;
static void check_vk_result(VkResult err)
{
@@ -152,6 +153,13 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
{
ImVector<const char*> device_extensions;
device_extensions.push_back("VK_KHR_swapchain");
+#ifdef VK_KHR_dynamic_rendering
+ device_extensions.push_back("VK_KHR_dynamic_rendering");
+ device_extensions.push_back("VK_KHR_depth_stencil_resolve");
+ device_extensions.push_back("VK_KHR_create_renderpass2");
+ device_extensions.push_back("VK_KHR_multiview");
+ device_extensions.push_back("VK_KHR_maintenance2");
+#endif
// Enumerate physical device extension
uint32_t properties_count;
@@ -170,10 +178,14 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
queue_info[0].queueFamilyIndex = g_QueueFamily;
queue_info[0].queueCount = 1;
queue_info[0].pQueuePriorities = queue_priority;
+ VkPhysicalDeviceDynamicRenderingFeatures dynamic_rendering_features = {};
+ dynamic_rendering_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES;
+ dynamic_rendering_features.dynamicRendering = VK_TRUE;
VkDeviceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
create_info.pQueueCreateInfos = queue_info;
+ create_info.pNext = &dynamic_rendering_features;
create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
create_info.ppEnabledExtensionNames = device_extensions.Data;
err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
@@ -237,7 +249,10 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
static void CleanupVulkan()
{
+ vkDeviceWaitIdle(g_Device);
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
+ for (int i = 0; i < g_AcquireSemaphores.Size; i++)
+ vkDestroySemaphore(g_Device, g_AcquireSemaphores[i], g_Allocator);
#ifdef APP_USE_VULKAN_DEBUG_REPORT
// Remove the debug report callback
@@ -257,9 +272,11 @@ static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
{
- VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
- VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
- VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
+ VkResult err;
+
+ VkSemaphore acquire_semaphore = g_AcquireSemaphores[wd->SemaphoreIndex];
+ uint32_t image_index = 0;
+ err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, acquire_semaphore, VK_NULL_HANDLE, &image_index);
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
g_SwapChainRebuild = true;
if (err == VK_ERROR_OUT_OF_DATE_KHR)
@@ -267,6 +284,9 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);
+ wd->FrameIndex = image_index;
+ VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->FrameIndex].RenderCompleteSemaphore;
+
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
@@ -284,6 +304,27 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
check_vk_result(err);
}
+
+ if (wd->UseDynamicRendering)
+ {
+ static PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)vkGetDeviceProcAddr(g_Device, "vkCmdBeginRenderingKHR");
+ VkRenderingAttachmentInfoKHR color_attachment = {};
+ color_attachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;
+ color_attachment.imageView = fd->BackbufferView;
+ color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ color_attachment.clearValue = wd->ClearValue;
+ VkRenderingInfoKHR rendering_info = {};
+ rendering_info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR;
+ rendering_info.renderArea.extent.width = wd->Width;
+ rendering_info.renderArea.extent.height = wd->Height;
+ rendering_info.layerCount = 1;
+ rendering_info.colorAttachmentCount = 1;
+ rendering_info.pColorAttachments = &color_attachment;
+ vkCmdBeginRenderingKHR(fd->CommandBuffer, &rendering_info);
+ }
+ else
{
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -300,13 +341,19 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
// Submit command buffer
- vkCmdEndRenderPass(fd->CommandBuffer);
+ if (wd->UseDynamicRendering)
+ {
+ static PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)vkGetDeviceProcAddr(g_Device, "vkCmdEndRenderingKHR");
+ vkCmdEndRenderingKHR(fd->CommandBuffer);
+ }
+ else
+ vkCmdEndRenderPass(fd->CommandBuffer);
{
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.waitSemaphoreCount = 1;
- info.pWaitSemaphores = &image_acquired_semaphore;
+ info.pWaitSemaphores = &acquire_semaphore;
info.pWaitDstStageMask = &wait_stage;
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
@@ -324,7 +371,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
{
if (g_SwapChainRebuild)
return;
- VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+ VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->FrameIndex].RenderCompleteSemaphore;
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
@@ -339,7 +386,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
return;
if (err != VK_SUBOPTIMAL_KHR)
check_vk_result(err);
- wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
+ wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount;
}
// Main code
@@ -386,6 +433,16 @@ int main(int, char**)
SDL_GetWindowSize(window, &w, &h);
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
SetupVulkanWindow(wd, surface, w, h);
+ {
+ g_AcquireSemaphores.resize(wd->SemaphoreCount);
+ for (uint32_t i = 0; i < wd->SemaphoreCount; i++)
+ {
+ VkSemaphoreCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ err = vkCreateSemaphore(g_Device, &info, g_Allocator, &g_AcquireSemaphores[i]);
+ check_vk_result(err);
+ }
+ }
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
@@ -421,7 +478,7 @@ int main(int, char**)
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForVulkan(window);
ImGui_ImplVulkan_InitInfo init_info = {};
- //init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version.
+ init_info.ApiVersion = VK_API_VERSION_1_4; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version.
init_info.Instance = g_Instance;
init_info.PhysicalDevice = g_PhysicalDevice;
init_info.Device = g_Device;
@@ -432,11 +489,15 @@ int main(int, char**)
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.Allocator = g_Allocator;
- init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
+ init_info.UseDynamicRendering = true;
init_info.PipelineInfoMain.Subpass = 0;
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
+ init_info.PipelineInfoMain.PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR;
+ init_info.PipelineInfoMain.PipelineRenderingCreateInfo.colorAttachmentCount = 1;
+ init_info.PipelineInfoMain.PipelineRenderingCreateInfo.pColorAttachmentFormats = &wd->SurfaceFormat.format;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info);
+ wd->UseDynamicRendering = true;
// Load Fonts
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
@@ -503,6 +564,8 @@ int main(int, char**)
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
+ ImGui::DockSpaceOverViewport(
+ 0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode, nullptr);
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
--
2.50.1.windows.1
Second patch is to demonstrate the issue:
From ff4d8d33cd027271c2e2475d850f952f93ffd42c Mon Sep 17 00:00:00 2001
From: Vikram Saran <contact@vikram.codes>
Date: Mon, 4 May 2026 12:21:27 +0200
Subject: [PATCH] Add debug printing for window and pipeline creation
---
backends/imgui_impl_vulkan.cpp | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 8df12926f..c28825129 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -2088,8 +2088,13 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoForViewports;
ImVector<VkFormat> requestSurfaceImageFormats;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
+ fprintf(stderr, "[DEBUG] CreateWindow read: pColorAttachmentFormats=%p\n", (void*)pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats);
for (uint32_t n = 0; n < pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount; n++)
- requestSurfaceImageFormats.push_back(pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats[n]);
+ {
+ VkFormat fmt = pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats[n];
+ fprintf(stderr, "[DEBUG] CreateWindow read: format[%d]=%d (0x%x)\n", n, (int)fmt, (int)fmt);
+ requestSurfaceImageFormats.push_back(fmt);
+ }
#endif
const VkFormat defaultFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
for (VkFormat format : defaultFormats)
@@ -2111,6 +2116,7 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
vd->WindowOwned = true;
// Create pipeline (shared by all secondary viewports)
+ fprintf(stderr, "[DEBUG] CreateWindow: PipelineForViewports=%p\n", (void*)bd->PipelineForViewports);
if (bd->PipelineForViewports == VK_NULL_HANDLE)
{
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
@@ -2118,6 +2124,7 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
{
pipeline_info->PipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
pipeline_info->PipelineRenderingCreateInfo.colorAttachmentCount = 1;
+ fprintf(stderr, "[DEBUG] CreateWindow set: pColorAttachmentFormats=%p (wd->SurfaceFormat.format)\n", (void*)&wd->SurfaceFormat.format);
pipeline_info->PipelineRenderingCreateInfo.pColorAttachmentFormats = &wd->SurfaceFormat.format;
}
else
--
2.50.1.windows.1
With the above, the first window creation gives:
[DEBUG] CreateWindow read: pColorAttachmentFormats=0000000000000000
[DEBUG] CreateWindow: PipelineForViewports=0000000000000000
[DEBUG] CreateWindow set: pColorAttachmentFormats=00000191CF9C6A70 (wd->SurfaceFormat.format)
And the second gives
[DEBUG] CreateWindow read: pColorAttachmentFormats=00000191CF9C6A70
[DEBUG] CreateWindow read: format[0]=-572662307 (0xdddddddd)
[DEBUG] CreateWindow: PipelineForViewports=00004A000000004A
I believe this shows a use after free for format[0]
Version/Branch of Dear ImGui:
Branch: docking, commit: 417f5ed
Back-ends:
imgui_impl_vulkan.cpp + imgui_impl_sdl3.cpp
Compiler, OS:
Windows 10, zig cc (v0.16.0)
Full config/build information:
Utilising imgui+docking via https://github.com/tiawl/cimgui.zig.git#68c0ed133ed317061baad3a3ae56cd2940c61a62 (a thin zig-build system wrapper for imgui, with c-bindings generated using dear_bindings).
SDL3 + Vulkan
The working demo is tiny, git access can be provided if desired (private gitlab repo).
Details:
I believe there is a use-after-free of
&wd->SurfaceFormat.formatinside imgui_impl_vulkan.cpp with dynamic rendering on the docking branch.Disclaimer: I did use Claude to help dig into the issue, but the report is 100% artisanal.
I have a 100% crash repro with a basic hello world setup with SDL3 + Vulkan, using dynamic rendering, when dragging a panel into its own window, returning it and docking it inside the main one, and then moving it into its own window again.
Further below there is a code example below recreates this inside the imgui SDL3 + Vulkan example (not a crash, but via logging).
My zig callstack is:
The value is "0xAAAAAAAA" - either uninitialised or freed memory by my zig allocator.
Editing the block ~line 2032 from:
to
Resolves the crash. I am not certain that this is the correct fix - again, I'm not a rendering engineer - but it does resolve my crash.
My goal for this issue report: confirm if what I'm seeing is correct, report it so you guys know about it, and get it fixed properly with time. I have a local workaround so I'm okay for now.
Minimal, Complete and Verifiable Example code:
First patch is to add dynamic rendering to the SDL3+Vulkan example.
Note: I am not a rendering engineer and this was LLM assisted.
Second patch is to demonstrate the issue:
With the above, the first window creation gives:
And the second gives
I believe this shows a use after free for format[0]