Pre-submission Checklist
Hexa.NET.ImGui Version
2.2.9
Bug Description
Text/TextColored/TextDisabled overloads that take a plain string (no format args — e.g. ImGui.TextColored(Vector4 col, string fmt)) still forward that string into native cimgui's variadic Text(fmt, ...) / TextColoredV, which calls libc's vsnprintf(buf, size, fmt, args) treating it as a printf format string.
From C#, calling ImGui.TextColored(color, someString) looks completely safe — there's no vararg syntax at the call site, nothing signals the string is still parsed as a format string underneath. But if someString contains a recognized conversion specifier with no matching argument (most plausibly %s, e.g. from an unsubstituted i18n/translation placeholder, a log message, or any user/dynamic content), vsnprintf tries to read a vararg that was never supplied and dereferences whatever garbage it finds on the exhausted va_list. On glibc (Linux) this segfaults the whole process — no exception, no managed stack trace, just a native SIGSEGV.
This is a binding-level footgun: the C# API surface implies safety that the native contract doesn't provide. Confirmed the crash is specific to the format-parsing path — ImGui.TextUnformatted (Dear ImGui's actual non-format-string API) with the exact same string does not crash.
Steps to Reproduce
Minimal standalone repro (no other dependencies, exact package versions below): https://github.com/tomast1337/betasharp-imgui-percent-crash-repro
- Clone the repo,
dotnet run --configuration Release -- unsafe
- Process crashes with SIGSEGV (exit code 139)
dotnet run --configuration Release -- safe runs the identical string through ImGui.TextUnformatted instead — survives cleanly
Expected Behavior
Passing a plain, non-format C# string to Text/TextColored/TextDisabled should never crash, regardless of its content — same guarantee ImGui.NET's equivalent string-only overloads provide (worth checking how they avoid this, e.g. forwarding as "%s", text or calling TextUnformatted internally).
Code Sample
// Crashes (SIGSEGV) — string-only overload, no format args at the call site,
// but the native side still parses it as a printf format string.
ImGui.TextColored(new Vector4(1f, 1f, 1f, 1f), "Player: %s just joined the game");
// Same string, survives — the actual non-format-string API.
ImGui.TextUnformatted("Player: %s just joined the game");
Platform
Linux
.NET Version
net10.0
Additional Context
Confirmed via a real coredump (coredumpctl gdb) that the crashing thread's native stack is:
$ coredumpctl gdb 848542
PID: 848542 (repro)
UID: 1000 (tomast1337)
GID: 1000 (tomast1337)
Signal: 11 (SEGV)
Timestamp: Sun 2026-07-19 15:58:15 -03 (1min 16s ago)
Command Line: ./repro unsafe
Executable: /home/tomast1337/Projects/betasharp-imgui-percent-crash-repro/bin/Release/net10.0/repro
Control Group: /user.slice/user-1000.slice/user@1000.service/kitty-847878-0.scope
Unit: user@1000.service
User Unit: kitty-847878-0.scope
Slice: user-1000.slice
Owner UID: 1000 (tomast1337)
Boot ID: 47834779441c4d3bb85beaf6ff6f9e31
Machine ID: 9de1746df06040c8b98032f6f872a3a5
Hostname: archlinux
Storage: /var/lib/systemd/coredump/core.repro.1000.47834779441c4d3bb85beaf6ff6f9e31.848542.1784487495000000.zst (present)
Size on Disk: 7.5M
Message: Process 848542 (repro) of user 1000 dumped core.
Stack trace of thread 848542:
#0 0x00007f8c11174d5d n/a (libc.so.6 + 0x174d5d)
#1 0x00007f8c11067108 n/a (libc.so.6 + 0x67108)
#2 0x00007f8c1108c39a __vsnprintf (libc.so.6 + 0x8c39a)
-- this is ImFormatStringV
#3 0x00007f73254a4330 _Z15ImFormatStringVPcmPKcP13__va_list_tag (cimgui.so + 0xa4330)
--- ImFormatStringToTempBufferV
#4 0x00007f73254a4691 _Z27ImFormatStringToTempBufferVPPKcS1_S0_P13__va_list_tag (cimgui.so + 0xa4691)
-- ImGui::TextV
#5 0x00007f73255788ad _ZN5ImGui5TextVEPKcP13__va_list_tag (cimgui.so + 0x1788ad)
-- ImGui::TextColoredV
#6 0x00007f73255789f0 _ZN5ImGui12TextColoredVERK6ImVec4PKcP13__va_list_tag (cimgui.so + 0x1789f0)
#7 0x00007f7325486908 igTextColored (cimgui.so + 0x86908)
#8 0x00007f7325486967 igTextColored0 (cimgui.so + 0x86967)
#9 0x00007f8b927c25b0 n/a (n/a + 0x0)
#10 0x00007f8b927c24bf n/a (n/a + 0x0)
#11 0x00007f8b927c1228 n/a (n/a + 0x0)
#12 0x00007f8b927c06bb n/a (n/a + 0x0)
#13 0x00007f8b927c00ff n/a (n/a + 0x0)
#14 0x00007f8b927bfdaa n/a (n/a + 0x0)
#15 0x00007f8b927bfd04 n/a (n/a + 0x0)
#16 0x00007f8b927a33a9 n/a (n/a + 0x0)
#17 0x00007f8b92781c6b n/a (n/a + 0x0)
#18 0x00007f8c10cd40cc n/a (libcoreclr.so + 0x4d40cc)
#19 0x00007f8c10b1d533 n/a (libcoreclr.so + 0x31d533)
#20 0x00007f8c109f79d2 n/a (libcoreclr.so + 0x1f79d2)
#21 0x00007f8c109f7e89 n/a (libcoreclr.so + 0x1f7e89)
#22 0x00007f8c10a22811 n/a (libcoreclr.so + 0x222811)
#23 0x00007f8c10875f4f coreclr_execute_assembly (libcoreclr.so + 0x75f4f)
#24 0x00007f8c1129bba7 n/a (libhostpolicy.so + 0x24ba7)
#25 0x00007f8c1129bf84 n/a (libhostpolicy.so + 0x24f84)
#26 0x00007f8c1129d0c0 corehost_main (libhostpolicy.so + 0x260c0)
#27 0x00007f8c116ee3be n/a (libhostfxr.so + 0x113be)
#28 0x00007f8c116ecd89 n/a (libhostfxr.so + 0xfd89)
#29 0x00007f8c116e72a3 hostfxr_main_startupinfo (libhostfxr.so + 0xa2a3)
#30 0x0000563adf84470a n/a (repro + 0x370a)
#31 0x0000563adf844ab2 n/a (repro + 0x3ab2)
#32 0x00007f8c11027741 n/a (libc.so.6 + 0x27741)
#33 0x00007f8c11027879 __libc_start_main (libc.so.6 + 0x27879)
#34 0x0000563adf8431f5 n/a (repro + 0x21f5)
Isolated minimal repro (this issue's exact scenario, in isolation): https://github.com/tomast1337/betasharp-imgui-percent-crash-repro
Real-world occurrence this was found from: https://git.gay/betasharp-official/betasharp/issues/37
Pre-submission Checklist
Hexa.NET.ImGui Version
2.2.9
Bug Description
Text/TextColored/TextDisabled overloads that take a plain
string(no format args — e.g.ImGui.TextColored(Vector4 col, string fmt)) still forward that string into native cimgui's variadicText(fmt, ...)/TextColoredV, which calls libc'svsnprintf(buf, size, fmt, args)treating it as a printf format string.From C#, calling
ImGui.TextColored(color, someString)looks completely safe — there's no vararg syntax at the call site, nothing signals the string is still parsed as a format string underneath. But ifsomeStringcontains a recognized conversion specifier with no matching argument (most plausibly%s, e.g. from an unsubstituted i18n/translation placeholder, a log message, or any user/dynamic content),vsnprintftries to read a vararg that was never supplied and dereferences whatever garbage it finds on the exhaustedva_list. On glibc (Linux) this segfaults the whole process — no exception, no managed stack trace, just a native SIGSEGV.This is a binding-level footgun: the C# API surface implies safety that the native contract doesn't provide. Confirmed the crash is specific to the format-parsing path —
ImGui.TextUnformatted(Dear ImGui's actual non-format-string API) with the exact same string does not crash.Steps to Reproduce
Minimal standalone repro (no other dependencies, exact package versions below): https://github.com/tomast1337/betasharp-imgui-percent-crash-repro
dotnet run --configuration Release -- unsafedotnet run --configuration Release -- saferuns the identical string throughImGui.TextUnformattedinstead — survives cleanlyExpected Behavior
Passing a plain, non-format C# string to Text/TextColored/TextDisabled should never crash, regardless of its content — same guarantee ImGui.NET's equivalent string-only overloads provide (worth checking how they avoid this, e.g. forwarding as
"%s", textor calling TextUnformatted internally).Code Sample
Platform
Linux
.NET Version
net10.0
Additional Context
Confirmed via a real coredump (coredumpctl gdb) that the crashing thread's native stack is:
$ coredumpctl gdb 848542 PID: 848542 (repro) UID: 1000 (tomast1337) GID: 1000 (tomast1337) Signal: 11 (SEGV) Timestamp: Sun 2026-07-19 15:58:15 -03 (1min 16s ago) Command Line: ./repro unsafe Executable: /home/tomast1337/Projects/betasharp-imgui-percent-crash-repro/bin/Release/net10.0/repro Control Group: /user.slice/user-1000.slice/user@1000.service/kitty-847878-0.scope Unit: user@1000.service User Unit: kitty-847878-0.scope Slice: user-1000.slice Owner UID: 1000 (tomast1337) Boot ID: 47834779441c4d3bb85beaf6ff6f9e31 Machine ID: 9de1746df06040c8b98032f6f872a3a5 Hostname: archlinux Storage: /var/lib/systemd/coredump/core.repro.1000.47834779441c4d3bb85beaf6ff6f9e31.848542.1784487495000000.zst (present) Size on Disk: 7.5M Message: Process 848542 (repro) of user 1000 dumped core. Stack trace of thread 848542: #0 0x00007f8c11174d5d n/a (libc.so.6 + 0x174d5d) #1 0x00007f8c11067108 n/a (libc.so.6 + 0x67108) #2 0x00007f8c1108c39a __vsnprintf (libc.so.6 + 0x8c39a) -- this is ImFormatStringV #3 0x00007f73254a4330 _Z15ImFormatStringVPcmPKcP13__va_list_tag (cimgui.so + 0xa4330) --- ImFormatStringToTempBufferV #4 0x00007f73254a4691 _Z27ImFormatStringToTempBufferVPPKcS1_S0_P13__va_list_tag (cimgui.so + 0xa4691) -- ImGui::TextV #5 0x00007f73255788ad _ZN5ImGui5TextVEPKcP13__va_list_tag (cimgui.so + 0x1788ad) -- ImGui::TextColoredV #6 0x00007f73255789f0 _ZN5ImGui12TextColoredVERK6ImVec4PKcP13__va_list_tag (cimgui.so + 0x1789f0) #7 0x00007f7325486908 igTextColored (cimgui.so + 0x86908) #8 0x00007f7325486967 igTextColored0 (cimgui.so + 0x86967) #9 0x00007f8b927c25b0 n/a (n/a + 0x0) #10 0x00007f8b927c24bf n/a (n/a + 0x0) #11 0x00007f8b927c1228 n/a (n/a + 0x0) #12 0x00007f8b927c06bb n/a (n/a + 0x0) #13 0x00007f8b927c00ff n/a (n/a + 0x0) #14 0x00007f8b927bfdaa n/a (n/a + 0x0) #15 0x00007f8b927bfd04 n/a (n/a + 0x0) #16 0x00007f8b927a33a9 n/a (n/a + 0x0) #17 0x00007f8b92781c6b n/a (n/a + 0x0) #18 0x00007f8c10cd40cc n/a (libcoreclr.so + 0x4d40cc) #19 0x00007f8c10b1d533 n/a (libcoreclr.so + 0x31d533) #20 0x00007f8c109f79d2 n/a (libcoreclr.so + 0x1f79d2) #21 0x00007f8c109f7e89 n/a (libcoreclr.so + 0x1f7e89) #22 0x00007f8c10a22811 n/a (libcoreclr.so + 0x222811) #23 0x00007f8c10875f4f coreclr_execute_assembly (libcoreclr.so + 0x75f4f) #24 0x00007f8c1129bba7 n/a (libhostpolicy.so + 0x24ba7) #25 0x00007f8c1129bf84 n/a (libhostpolicy.so + 0x24f84) #26 0x00007f8c1129d0c0 corehost_main (libhostpolicy.so + 0x260c0) #27 0x00007f8c116ee3be n/a (libhostfxr.so + 0x113be) #28 0x00007f8c116ecd89 n/a (libhostfxr.so + 0xfd89) #29 0x00007f8c116e72a3 hostfxr_main_startupinfo (libhostfxr.so + 0xa2a3) #30 0x0000563adf84470a n/a (repro + 0x370a) #31 0x0000563adf844ab2 n/a (repro + 0x3ab2) #32 0x00007f8c11027741 n/a (libc.so.6 + 0x27741) #33 0x00007f8c11027879 __libc_start_main (libc.so.6 + 0x27879) #34 0x0000563adf8431f5 n/a (repro + 0x21f5)Isolated minimal repro (this issue's exact scenario, in isolation): https://github.com/tomast1337/betasharp-imgui-percent-crash-repro
Real-world occurrence this was found from: https://git.gay/betasharp-official/betasharp/issues/37