Quellcode durchsuchen

InputTextWithHint(): Fixed buffer overflow when user callback modifies the buffer contents in a way that alters hint visibility. (#8368)

ocornut vor 7 Monaten
Ursprung
Commit
5dd84082ab
4 geänderte Dateien mit 18 neuen und 1 gelöschten Zeilen
  1. 1 0
      backends/imgui_impl_metal.mm
  2. 3 0
      docs/CHANGELOG.txt
  3. 1 0
      imgui.cpp
  4. 13 1
      imgui_widgets.cpp

+ 1 - 0
backends/imgui_impl_metal.mm

@@ -15,6 +15,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2025-02-03: Metal: Crash fix. (#8367)
 //  2024-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419).
 //  2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'.
 //  2022-07-05: Metal: Add dispatch synchronization.

+ 3 - 0
docs/CHANGELOG.txt

@@ -45,6 +45,9 @@ Other changes:
 
 - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(),
   RadioButton(), Selectable(). Regression from 2025/01/13. (#8370)
+- InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect)
+  when a user callback modified the buffer contents in a way that altered the
+  visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut]
 - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom]
 
 -----------------------------------------------------------------------

+ 1 - 0
imgui.cpp

@@ -2012,6 +2012,7 @@ const char* ImStreolRange(const char* str, const char* str_end)
 
 const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find beginning-of-line
 {
+    IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + strlen(buf_begin));
     while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
         buf_mid_line--;
     return buf_mid_line;

+ 13 - 1
imgui_widgets.cpp

@@ -4669,7 +4669,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
     // Select the buffer to render.
     const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state;
-    const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
+    bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
 
     // Password pushes a temporary font with only a fallback glyph
     if (is_password && !is_displaying_hint)
@@ -5151,6 +5151,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     const int buf_display_max_length = 2 * 1024 * 1024;
     const char* buf_display = buf_display_from_state ? state->TextA.Data : buf; //-V595
     const char* buf_display_end = NULL; // We have specialized paths below for setting the length
+
+    // Display hint when contents is empty
+    // At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368)
+    const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
+    if (new_is_displaying_hint != is_displaying_hint)
+    {
+        if (is_password && !is_displaying_hint)
+            PopFont();
+        is_displaying_hint = new_is_displaying_hint;
+        if (is_password && !is_displaying_hint)
+            PushPasswordFont();
+    }
     if (is_displaying_hint)
     {
         buf_display = hint;