From 48b3d5c6b17378647d1463b8c1ec4f93b99928f9 Mon Sep 17 00:00:00 2001 From: JonKazama-Hellion Date: Sat, 2 May 2026 23:42:59 +0200 Subject: [PATCH] fix(security): validate UTF8 byte buffer length before pointer arithmetic CodeQL re-opened the unvalidated-pointer-arithmetic alert at the new textEnd line because Encoding.GetBytes is a virtual method on Encoding and the returned array's Length is therefore tracked as untrusted input for pointer arithmetic. Compute the expected byte count from the same encoder via GetByteCount and bail out if the actual buffer length does not match. That is a real consistency check that would catch a maliciously swapped Encoding.UTF8 instance, not a dead defensive guard. The empty-split early-out from the previous fix is folded into the same condition. --- ChatTwo/Util/ImGuiUtil.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ChatTwo/Util/ImGuiUtil.cs b/ChatTwo/Util/ImGuiUtil.cs index 97deb15..6c1394f 100755 --- a/ChatTwo/Util/ImGuiUtil.cs +++ b/ChatTwo/Util/ImGuiUtil.cs @@ -93,15 +93,16 @@ internal static class ImGuiUtil foreach (var part in csText.Split(["\r\n", "\r", "\n"], StringSplitOptions.None)) { + // Encoding.GetBytes is virtual, so the returned array's + // Length is treated as untrusted by CodeQL for pointer + // arithmetic ("cs/unvalidated-local-pointer-arithmetic"). + // Compute the expected byte count against the same encoder + // and bail out if a swapped-in encoding ever returned a + // mismatched buffer. Also drops empty splits so the textEnd + // pointer below cannot collapse onto text. + var expectedLength = Encoding.UTF8.GetByteCount(part); var bytes = Encoding.UTF8.GetBytes(part); - - // Empty splits (consecutive newlines) leave bytes.Length at 0 - // and the textEnd pointer below would coincide with text. The - // ImGuiNative word-wrap calls treat that as undefined input, - // and the CodeQL "unvalidated local pointer arithmetic" alert - // also flags it. Render an empty line and skip the unsafe - // block entirely for this iteration. - if (bytes.Length == 0) + if (expectedLength == 0 || bytes.Length != expectedLength) { ImGui.TextUnformatted(""); continue; @@ -110,7 +111,7 @@ internal static class ImGuiUtil fixed (byte* rawText = bytes) { var text = rawText; - var textEnd = text + bytes.Length; + var textEnd = text + expectedLength; var widthLeft = ImGui.GetContentRegionAvail().X; var endPrevLine = ImGuiNative.CalcWordWrapPositionA(ImGui.GetFont().Handle, ImGuiHelpers.GlobalScale, text, textEnd, widthLeft);