Assertion/crash in InputTextMultiline when pressing down-arrow on single empty line following text #6783

Closed
opened 2023-09-04 14:11:34 +00:00 by lithiumfluorine · 3 comments
lithiumfluorine commented 2023-09-04 14:11:34 +00:00 (Migrated from github.com)

Version/Branch of Dear ImGui:

Dear ImGui 1.89.9 WIP (18983)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: _WIN32
define: _WIN64
define: _MSC_VER=1935
define: _MSVC_LANG=202002
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_glfw
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000440
 DockingEnable
 ViewportsEnable
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60,0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 2 fonts, Flags: 0x00000000, TexSize: 512,256
io.DisplaySize: 1280,00,720,00
io.DisplayFramebufferScale: 1,00,1,00
--------------------------------
style.WindowPadding: 8,00,8,00
style.WindowBorderSize: 1,00
style.FramePadding: 4,00,3,00
style.FrameRounding: 0,00
style.FrameBorderSize: 0,00
style.ItemSpacing: 8,00,4,00
style.ItemInnerSpacing: 4,00,4,00

My Issue/Question:

Pressing down-arrow within an InputTextMultiline() on a final, single, empty line following some text causes an assertion.
It seems to be triggered by an out-of-range index on line 883 of imstb_textedit.h.

Video:

inputtextmultiline-assert.webm

Stacktrace:

[[ ... Boring Windows assert stuff skipped ... ]]
example.exe!_wassert(const wchar_t * expression, const wchar_t * file_name, unsigned int line_number) Line 444	C++
example.exe!ImVector<unsigned short>::operator[](int i) Line 1917	C++
example.exe!ImStb::STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState * obj, int idx) Line 3703	C++
example.exe!ImStb::stb_textedit_key(ImGuiInputTextState * str, ImStb::STB_TexteditState * state, int key) Line 883	C++
example.exe!ImGuiInputTextState::OnKeyPressed(int key) Line 3849	C++
example.exe!ImGui::InputTextEx(const char * label, const char * hint, char * buf, int buf_size, const ImVec2 & size_arg, int flags, int(*)(ImGuiInputTextCallbackData *) callback, void * callback_user_data) Line 4455	C++
example.exe!ImGui::InputTextMultiline(const char * label, char * buf, unsigned __int64 buf_size, const ImVec2 & size, int flags, int(*)(ImGuiInputTextCallbackData *) callback, void * user_data) Line 3631	C++
example.exe!ImGui::InputTextMultiline(const char * label, std::string * str, const ImVec2 & size, int flags, int(*)(ImGuiInputTextCallbackData *) callback, void * user_data) Line 69	C++
example.exe!main(char * * argv, int argc) Line 95	C++
[External Code]	

Standalone, minimal, complete and verifiable example:

#include "imgui_stdlib.h"
// ...

static std::string crash    = "Click this text then press down-arrow twice to cause an assert.\n";
static std::string nocrash1 = "This one doesn't have that issue.";
static std::string nocrash2 = "Neither does this one.\n\n";
        
ImGui::Begin("InputTextMultiline assert");
ImGui::InputTextMultiline("Crash", &crash);
ImGui::InputTextMultiline("No crash", &nocrash1);
ImGui::InputTextMultiline("No crash 2", &nocrash2);
ImGui::End();
**Version/Branch of Dear ImGui:** ``` Dear ImGui 1.89.9 WIP (18983) -------------------------------- sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20 define: __cplusplus=199711 define: _WIN32 define: _WIN64 define: _MSC_VER=1935 define: _MSVC_LANG=202002 define: IMGUI_HAS_VIEWPORT define: IMGUI_HAS_DOCK -------------------------------- io.BackendPlatformName: imgui_impl_glfw io.BackendRendererName: imgui_impl_opengl3 io.ConfigFlags: 0x00000440 DockingEnable ViewportsEnable io.ConfigViewportsNoDecoration io.ConfigInputTextCursorBlink io.ConfigWindowsResizeFromEdges io.ConfigMemoryCompactTimer = 60,0 io.BackendFlags: 0x00001C0E HasMouseCursors HasSetMousePos PlatformHasViewports HasMouseHoveredViewport RendererHasVtxOffset RendererHasViewports -------------------------------- io.Fonts: 2 fonts, Flags: 0x00000000, TexSize: 512,256 io.DisplaySize: 1280,00,720,00 io.DisplayFramebufferScale: 1,00,1,00 -------------------------------- style.WindowPadding: 8,00,8,00 style.WindowBorderSize: 1,00 style.FramePadding: 4,00,3,00 style.FrameRounding: 0,00 style.FrameBorderSize: 0,00 style.ItemSpacing: 8,00,4,00 style.ItemInnerSpacing: 4,00,4,00 ``` **My Issue/Question:** Pressing down-arrow within an `InputTextMultiline()` on a final, single, empty line following some text causes an assertion. It seems to be triggered by an out-of-range index on line 883 of `imstb_textedit.h`. **Video:** [inputtextmultiline-assert.webm](https://github.com/ocornut/imgui/assets/16268895/155b5b32-669b-4019-8172-37a30df1ac72) **Stacktrace:** ``` [[ ... Boring Windows assert stuff skipped ... ]] example.exe!_wassert(const wchar_t * expression, const wchar_t * file_name, unsigned int line_number) Line 444 C++ example.exe!ImVector<unsigned short>::operator[](int i) Line 1917 C++ example.exe!ImStb::STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState * obj, int idx) Line 3703 C++ example.exe!ImStb::stb_textedit_key(ImGuiInputTextState * str, ImStb::STB_TexteditState * state, int key) Line 883 C++ example.exe!ImGuiInputTextState::OnKeyPressed(int key) Line 3849 C++ example.exe!ImGui::InputTextEx(const char * label, const char * hint, char * buf, int buf_size, const ImVec2 & size_arg, int flags, int(*)(ImGuiInputTextCallbackData *) callback, void * callback_user_data) Line 4455 C++ example.exe!ImGui::InputTextMultiline(const char * label, char * buf, unsigned __int64 buf_size, const ImVec2 & size, int flags, int(*)(ImGuiInputTextCallbackData *) callback, void * user_data) Line 3631 C++ example.exe!ImGui::InputTextMultiline(const char * label, std::string * str, const ImVec2 & size, int flags, int(*)(ImGuiInputTextCallbackData *) callback, void * user_data) Line 69 C++ example.exe!main(char * * argv, int argc) Line 95 C++ [External Code] ``` **Standalone, minimal, complete and verifiable example:** ``` #include "imgui_stdlib.h" // ... static std::string crash = "Click this text then press down-arrow twice to cause an assert.\n"; static std::string nocrash1 = "This one doesn't have that issue."; static std::string nocrash2 = "Neither does this one.\n\n"; ImGui::Begin("InputTextMultiline assert"); ImGui::InputTextMultiline("Crash", &crash); ImGui::InputTextMultiline("No crash", &nocrash1); ImGui::InputTextMultiline("No crash 2", &nocrash2); ImGui::End(); ```
ocornut commented 2023-09-04 15:39:11 +00:00 (Migrated from github.com)

Confirmed like a bug related to some our of changes in InputText logic. Reproducible with raw const char* version.

Confirmed like a bug related to some our of changes in InputText logic. Reproducible with raw `const char*` version.
ocornut commented 2023-09-04 15:49:50 +00:00 (Migrated from github.com)

Regression added by commit 57a5b73a4c for #6000

Regression added by commit 57a5b73a4cd86ec8f7d4295010d7d082a07b806c for #6000
ocornut commented 2023-09-06 09:36:32 +00:00 (Migrated from github.com)

Pushed fix d8ef864 + more regression tests ocornut/imgui_test_engine@f0f74be707

It seems the issue was in the last two lines changed in 57a5b73a4c, to be able to test assertions and see where this was exercised I simply put a breakpoint in there and ran the test suite, then tried to understand why the test seemed like they worked.

I'm honestly surprisingly this wasn't noticed earlier, but essentially it wouldn't happen if the underlying buffer was big enough to contains the overflow. Added a better assert in STB_TEXTEDIT_GETCHAR().

Pushed fix d8ef864 + more regression tests https://github.com/ocornut/imgui_test_engine/commit/f0f74be707e8c9412677b0bb4aa01c0b26fe278a It seems the issue was in the last two lines changed in 57a5b73a4cd86ec8f7d4295010d7d082a07b806c, to be able to test assertions and see where this was exercised I simply put a breakpoint in there and ran the test suite, then tried to understand why the test seemed like they worked. I'm honestly surprisingly this wasn't noticed earlier, but essentially it wouldn't happen if the underlying buffer was big enough to contains the overflow. Added a better assert in `STB_TEXTEDIT_GETCHAR()`.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ocornut/imgui#6783
No description provided.