ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
61.14k stars 10.3k forks source link

Crash when trying to use automatic line wrapping: #793

Closed xaxxon closed 8 years ago

xaxxon commented 8 years ago

I had some code that printed text in a window and it was sometimes too long, so I thought I'd change it to use line wrapping. I tried changing from text colored to text wrapped, and it crashed. So I saw that in the header file it said text wrapped was just a helper around a couple other calls, so I added those other calls aroudn my textcolored instead. Still crashed. I then upgraded to latest version, and it still crashes.

In the very bottom of this listing, you can see my code -- I pointed out which line I had before that worked and the line directly above and below it that are causing the crash.

Happy to provide any more data.


=================================================================
==16670==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0001073ff420 at pc 0x000106d602ce bp 0x7fff5fbfbcd0 sp 0x7fff5fbfbcc8
READ of size 1 at 0x0001073ff420 thread T0
    #0 0x106d602cd in ImFont::CalcTextSizeA(float, float, float, char const*, char const*, char const**) const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106d602cd)
    #1 0x106c6b132 in ImGui::CalcTextSize(char const*, char const*, bool, float) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106c6b132)
    #2 0x106c6410b in ImGui::TextUnformatted(char const*, char const*) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106c6410b)
    #3 0x106ca5ace in ImGui::TextV(char const*, __va_list_tag*) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106ca5ace)
    #4 0x106ca5b0d in ImGui::TextColoredV(ImVec4 const&, char const*, __va_list_tag*) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106ca5b0d)
    #5 0x106ca5d53 in ImGui::TextColored(ImVec4 const&, char const*, ...) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106ca5d53)
    #6 0x1001e4014 in Console::draw()::$_3::operator()() const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1001e4014)
    #7 0x1001e21fc in void std::__1::__invoke_void_return_wrapper<void>::__call<Console::draw()::$_3&>(Console::draw()::$_3&&&) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1001e21fc)
    #8 0x1001e20a8 in std::__1::__function::__func<Console::draw()::$_3, std::__1::allocator<Console::draw()::$_3>, void ()>::operator()() (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1001e20a8)
    #9 0x1000c8162 in std::__1::function<float ()>::operator()() const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1000c8162)
    #10 0x1003053b5 in Gui::window(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool*, std::__1::function<void ()>, int) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1003053b5)
    #11 0x100128d2c in Console::draw() (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x100128d2c)
    #12 0x10026c77c in Game::loop()::$_5::operator()() const::'lambda'()::operator()() const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x10026c77c)
    #13 0x10026b736 in std::__1::result_of<Game::loop()::$_5::operator()() const::'lambda'() ()>::type v8toolkit::Context::operator()<Game::loop()::$_5::operator()() const::'lambda'()>(Game::loop()::$_5::operator()() const::'lambda'()&&) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x10026b736)
    #14 0x1002677b8 in Game::loop()::$_5::operator()() const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1002677b8)
    #15 0x100215679 in std::__1::result_of<Game::loop()::$_5 ()>::type v8toolkit::Isolate::operator()<Game::loop()::$_5>(Game::loop()::$_5&&) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x100215679)
    #16 0x1002153be in Game::loop() (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x1002153be)
    #17 0x106d78b8c in main (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106d78b8c)
    #18 0x7fff90b3d5ac in start (/usr/lib/system/libdyld.dylib+0x35ac)
    #19 0x0  (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x0)

0x0001073ff420 is located 0 bytes to the right of global variable 'GImDefaultContext' defined in '/Users/xaxxon/apb/imgui/imgui.cpp:715:25' (0x1073fb980) of size 15008
SUMMARY: AddressSanitizer: global-buffer-overflow (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106d602cd) in ImFont::CalcTextSizeA(float, float, float, char const*, char const*, char const**) const
Shadow bytes around the buggy address:
  0x100020e7fe30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020e7fe40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020e7fe50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020e7fe60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100020e7fe70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100020e7fe80: 00 00 00 00[f9]f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x100020e7fe90: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x100020e7fea0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x100020e7feb0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x100020e7fec0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x100020e7fed0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16670==ABORTING
(lldb) AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.
Process 16670 stopped
* thread #1: tid = 0x81fe3, 0x000000010eba28e0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie(), queue = 'com.apple.main-thread', stop reason = Global buffer overflow detected
    frame #0: 0x000000010eba28e0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie()
libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie:
->  0x10eba28e0 <+0>: pushq  %rbx
    0x10eba28e1 <+1>: movl   $0x1, %eax
    0x10eba28e6 <+6>: lock   
    0x10eba28e7 <+7>: xaddl  %eax, 0x27792e(%rip)      ; __asan::AsanDie()::num_calls
(lldb)  
error: No auto repeat.
(lldb) bt
* thread #1: tid = 0x81fe3, 0x000000010eba28e0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie(), queue = 'com.apple.main-thread', stop reason = Global buffer overflow detected
  * frame #0: 0x000000010eba28e0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie()
    frame #1: 0x000000010eba7065 libclang_rt.asan_osx_dynamic.dylib`__sanitizer::Die() + 85
    frame #2: 0x000000010eba032a libclang_rt.asan_osx_dynamic.dylib`__asan::ScopedInErrorReport::~ScopedInErrorReport() + 218
    frame #3: 0x000000010eb9fda1 libclang_rt.asan_osx_dynamic.dylib`__asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) + 4097
    frame #4: 0x000000010eba06c6 libclang_rt.asan_osx_dynamic.dylib`__asan_report_load1 + 54
    frame #5: 0x0000000106d602ce apb`ImFont::CalcTextSizeA(this=0x000060b000087060, size=13, max_width=3.40282347E+38, wrap_width=1008, text_begin="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"..., text_end="", remaining=0x0000000000000000) const + 1390 at imgui_draw.cpp:1926
    frame #6: 0x0000000106c6b133 apb`ImGui::CalcTextSize(text="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"..., text_end="", hide_text_after_double_hash=false, wrap_width=1008) + 723 at imgui.cpp:2980
    frame #7: 0x0000000106c6410c apb`ImGui::TextUnformatted(text="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"..., text_end="") + 5580 at imgui.cpp:5394
    frame #8: 0x0000000106ca5acf apb`ImGui::TextV(fmt="%s", args=0x00007fff5fbfc920) + 223 at imgui.cpp:5244
    frame #9: 0x0000000106ca5b0e apb`ImGui::TextColoredV(col=0x00007fff5fbfcef0, fmt="%s", args=0x00007fff5fbfc920) + 46 at imgui.cpp:5258
    frame #10: 0x0000000106ca5d54 apb`ImGui::TextColored(col=0x00007fff5fbfcef0, fmt="%s") + 564 at imgui.cpp:5266
    frame #11: 0x00000001001e4015 apb`Console::draw(this=0x00007fff5fbfdb68)::$_3::operator()() const + 7685 at console.cpp:209
    frame #12: 0x00000001001e21fd apb`void std::__1::__invoke_void_return_wrapper<void>::__call<Console::draw()::$_3&>(Console::draw()::$_3&&&) [inlined] decltype(__f=0x00007fff5fbfdb68)::$_3&>(fp)(std::__1::forward<>(fp0))) std::__1::__invoke<Console::draw()::$_3&>(Console::draw()::$_3&&&) + 45 at __functional_base:365
    frame #13: 0x00000001001e21ec apb`void std::__1::__invoke_void_return_wrapper<void>::__call<Console::draw(__args=0x00007fff5fbfdb68)::$_3&>(Console::draw()::$_3&&&) + 28 at __functional_base:417
    frame #14: 0x00000001001e20a9 apb`std::__1::__function::__func<Console::draw()::$_3, std::__1::allocator<Console::draw()::$_3>, void ()>::operator(this=0x00007fff5fbfdb60)() + 41 at functional:1533
    frame #15: 0x00000001000c8163 apb`std::__1::function<void ()>::operator(this=0x00007fff5fbfdb60)() const + 339 at functional:1891
    frame #16: 0x00000001003053b6 apb`Gui::window(name="console", show_window=0x00007fff5fbfdb10, window_builder=function<void ()> @ 0x00007fff5fbfdb60, flags=319)>, int) + 806 at gui.cpp:437
    frame #17: 0x0000000100128d2d apb`Console::draw(this=0x000061100008f100) + 1917 at console.cpp:168
    frame #18: 0x000000010026c77d apb`Game::loop(this=0x00007fff5fbfe980)::$_5::operator()() const::'lambda'()::operator()() const + 3517 at game.cpp:413
    frame #19: 0x000000010026b737 apb`std::__1::result_of<Game::loop()::$_5::operator()() const::'lambda'() ()>::type v8toolkit::Context::operator(this=0x00006060000de620, callable=0x00007fff5fbfe980)<Game::loop()::$_5::operator()() const::'lambda'()>(Game::loop()::$_5::operator()() const::'lambda'()&&) + 2231 at javascript.h:212
    frame #20: 0x00000001002677b9 apb`Game::loop(this=0x00007fff5fbff220)::$_5::operator()() const + 1241 at game.cpp:370
    frame #21: 0x000000010021567a apb`std::__1::result_of<Game::loop()::$_5 ()>::type v8toolkit::Isolate::operator(this=0x000060400006a650, callable=0x00007fff5fbff220)<Game::loop()::$_5>(Game::loop()::$_5&&) + 570 at javascript.h:480
    frame #22: 0x00000001002153bf apb`Game::loop(this=0x0000612000055cc0) + 751 at game.cpp:362
    frame #23: 0x0000000106d78b8d apb`main(argc=1, argv=0x00007fff5fbff820) + 1549 at apb.cpp:46
    frame #24: 0x00007fff90b3d5ad libdyld.dylib`start + 1
(lldb) up
frame #1: 0x000000010eba7065 libclang_rt.asan_osx_dynamic.dylib`__sanitizer::Die() + 85
libclang_rt.asan_osx_dynamic.dylib`__sanitizer::Die:
    0x10eba7065 <+85>:  leaq   0x339dc(%rip), %rax       ; __sanitizer::common_flags_dont_use
    0x10eba706c <+92>:  cmpb   $0x0, 0xa4(%rax)
    0x10eba7073 <+99>:  jne    0x10eba7080               ; <+112>
    0x10eba7075 <+101>: movl   0xa0(%rax), %edi
(lldb) 
frame #2: 0x000000010eba032a libclang_rt.asan_osx_dynamic.dylib`__asan::ScopedInErrorReport::~ScopedInErrorReport() + 218
libclang_rt.asan_osx_dynamic.dylib`__asan::ScopedInErrorReport::~ScopedInErrorReport:
    0x10eba032a <+218>: nopw   (%rax,%rax)

libclang_rt.asan_osx_dynamic.dylib`__asan::ReportInvalidPointerPair:
    0x10eba0330 <+0>:   pushq  %rbp
    0x10eba0331 <+1>:   pushq  %r15
    0x10eba0333 <+3>:   pushq  %r14
(lldb) 
frame #3: 0x000000010eb9fda1 libclang_rt.asan_osx_dynamic.dylib`__asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) + 4097
libclang_rt.asan_osx_dynamic.dylib`__asan::ReportGenericError:
    0x10eb9fda1 <+4097>: addq   $0x958, %rsp              ; imm = 0x958 
    0x10eb9fda8 <+4104>: popq   %rbx
    0x10eb9fda9 <+4105>: popq   %r12
    0x10eb9fdab <+4107>: popq   %r13
(lldb) 
frame #4: 0x000000010eba06c6 libclang_rt.asan_osx_dynamic.dylib`__asan_report_load1 + 54
libclang_rt.asan_osx_dynamic.dylib`__asan_report_load1:
    0x10eba06c6 <+54>: addq   $0x20, %rsp
    0x10eba06ca <+58>: popq   %rbp
    0x10eba06cb <+59>: retq   
    0x10eba06cc <+60>: nopl   (%rax)
(lldb) 
frame #5: 0x0000000106d602ce apb`ImFont::CalcTextSizeA(this=0x000060b000087060, size=13, max_width=3.40282347E+38, wrap_width=1008, text_begin="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"..., text_end="", remaining=0x0000000000000000) const + 1390 at imgui_draw.cpp:1926
   1923                 // Wrapping skips upcoming blanks
   1924                 while (s < text_end)
   1925                 {
-> 1926                     const char c = *s;
   1927                     if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
   1928                 }
   1929                 continue;
(lldb) p *s
(const char) $1 = '\0'
(lldb) up
frame #6: 0x0000000106c6b133 apb`ImGui::CalcTextSize(text="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"..., text_end="", hide_text_after_double_hash=false, wrap_width=1008) + 723 at imgui.cpp:2980
   2977     const float font_size = g.FontSize;
   2978     if (text == text_display_end)
   2979         return ImVec2(0.0f, font_size);
-> 2980     ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
   2981 
   2982     // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field)
   2983     const float font_scale = font_size / font->FontSize;
(lldb) 
frame #7: 0x0000000106c6410c apb`ImGui::TextUnformatted(text="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"..., text_end="") + 5580 at imgui.cpp:5394
   5391     else
   5392     {
   5393         const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
-> 5394         const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
   5395 
   5396         // Account of baseline offset
   5397         ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
(lldb) p text_bebin
error: use of undeclared identifier 'text_bebin'
error: 1 errors parsing expression
(lldb) p text_begin
(const char *) $2 = 0x00000001073fe818 "Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079831a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010743c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000fac45 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059ebbf _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcacc0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcab6d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bca9c9 _ZNSt3__110__fu"...
(lldb) up
frame #8: 0x0000000106ca5acf apb`ImGui::TextV(fmt="%s", args=0x00007fff5fbfc920) + 223 at imgui.cpp:5244
   5241 
   5242     ImGuiContext& g = *GImGui;
   5243     const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
-> 5244     TextUnformatted(g.TempBuffer, text_end);
   5245 }
   5246 
   5247 void ImGui::Text(const char* fmt, ...)
(lldb) up
frame #9: 0x0000000106ca5b0e apb`ImGui::TextColoredV(col=0x00007fff5fbfcef0, fmt="%s", args=0x00007fff5fbfc920) + 46 at imgui.cpp:5258
   5255 void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
   5256 {
   5257     PushStyleColor(ImGuiCol_Text, col);
-> 5258     TextV(fmt, args);
   5259     PopStyleColor();
   5260 }
   5261 
(lldb) up
frame #10: 0x0000000106ca5d54 apb`ImGui::TextColored(col=0x00007fff5fbfcef0, fmt="%s") + 564 at imgui.cpp:5266
   5263 {
   5264     va_list args;
   5265     va_start(args, fmt);
-> 5266     TextColoredV(col, fmt, args);
   5267     va_end(args);
   5268 }
   5269 
(lldb) p col
(const ImVec4) $3 = (x = 1, y = 0.200000003, z = 0.200000003, w = 1)
(lldb) p fmt
(const char *) $4 = 0x0000000106f0fdc0 "%s"
(lldb) p args
(va_list) $5 = {
  [0] = (gp_offset = 24, fp_offset = 48, overflow_arg_area = 0x00007fff5fbfcb60, reg_save_area = 0x00007fff5fbfca60)
}
(lldb) up
frame #11: 0x00000001001e4015 apb`Console::draw(this=0x00007fff5fbfdb68)::$_3::operator()() const + 7685 at console.cpp:209
   206  
   207                      case ConsoleMessage::Type::ERROR:
   208                          ImGui::PushTextWrapPos(0.0f);
-> 209                          ImGui::TextColored(ImVec4(1,.2,.2,1), "%s", i->message.c_str());    <=== THIS LINE WORKED FINE BEFORE BEFORE ADDING THE LINES DIRECTLY ABOVE AND BELOW IT
   210                      ImGui::PopTextWrapPos();
   211                          break;
   212                  }
ocornut commented 8 years ago

Those are two different things you are discussing.

The first one is an assert that checks that you didn't alter the text buffer in the text edit custom callback without maintaining its length. Have you read the comment next to it?

// You need to maintain BufTextLen if you change the text!
IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); 

The second, can you double-check that i->message.c_str() point to a proper zero-terminated string? If you look at the string passed to TextUnformatted() is looks rather dodgy, it is mean to be that long (multiple lines of content)?

ocornut commented 8 years ago

Both appears to be bug in your code not in imgui..

xaxxon commented 8 years ago

image

That's an example of what it looks like without line wrapping.

Yes, I realized after I posted the edit that the two were unrelated and removed the edit. I'll do those other things now.

ocornut commented 8 years ago

I wonder if ImGui::TextV() behave correctly on overflow? Check around that. Can you add test/breakpoint to see if the w==-1 codepath got executed?

int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
{
    int w = vsnprintf(buf, buf_size, fmt, args);
    buf[buf_size-1] = 0;
    return (w == -1) ? buf_size : w;
}

PS: If you are going to display big chunk of text here using TextUnformatted(buf) will be faster than Text("%s", buf); and not have a size limitation. Bug if any should definitively be fixed.

xaxxon commented 8 years ago
**frame #7: 0x0000000106c64f9c apb`ImGui::TextUnformatted(**text="Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079911a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010777c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000faf85 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059f97f _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcbac0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcb96d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bcb7c9 _ZNSt3__110__fu"..., text_end="") + 5580 at imgui.cpp:5394
   5391     else
   5392     {
   5393         const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
-> 5394         const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
   5395 
   5396         // Account of baseline offset
   5397         ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
(lldb) p text_begin;
(const char *) $1 = 0x00000001073ff878 "Module: core Callback new_map failed: Couldn't find object factory named core/fueltruck2\n0   apb                                 0x000000010079911a _ZN19StackTraceExceptionC2Ev + 506\n1   apb                                 0x000000010010777c _ZN12ApbExceptionC2IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 284\n2   apb                                 0x00000001000faf85 _ZN12ApbExceptionC1IJRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEES9_DpOT_ + 37\n3   apb                                 0x000000010059f97f _ZNK16ObjectCollection3getERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 2783\n4   apb                                 0x0000000100bcbac0 _ZN9v8toolkit4BindI7JobListMS1_FvR3JobEEclES3_ + 320\n5   apb                                 0x0000000100bcb96d _ZNSt3__128__invoke_void_return_wrapperIvE6__callIJRN9v8toolkit4BindI7JobListMS5_FvR3JobEEES7_EEEvDpOT_ + 77\n6   apb                                 0x0000000100bcb7c9 _ZNSt3__110__fu"...
(lldb) p text_end
(const char *) $2 = 0x00000001074006f1 ""

and


frame #11: 0x00000001001e4ce2 apb`Console::draw(this=0x00007fff5fbfdb68)::$_3::operator()() const + 10114 at console.cpp:218
   215                          auto len = strlen(i->message.c_str());
   216                          fprintf(stderr, "strlen of thing I'm sending to imgui: %lu\n", len);
   217  
-> 218                          ImGui::TextColored(ImVec4(1, .2, .2, 1), "%s", i->message.c_str());
   219                          ImGui::PopTextWrapPos();
   220                          break;
   221                      }
(lldb) 

outputs:


Generating framebuffers with dimensions 1024 768
Destroying framebuffers - happens when resizing window and closing program
Setting timer delta to 0 because time difference between updates > 3s
**strlen of thing I'm sending to imgui: 3705**
=================================================================
==17219==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000107400480 at pc 0x000106d6115e bp 0x7fff5fbfb970 sp 0x7fff5fbfb968
READ of size 1 at 0x000107400480 thread T0
    #0 0x106d6115d in ImFont::CalcTextSizeA(float, float, float, char const*, char const*, char const**) const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106d6115d)
    #1 0x106c6bfc2 in ImGui::CalcTextSize(char const*, char const*, bool, float) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106c6bfc2)
    #2 0x106c64f9b in ImGui::TextUnformatted(char const*, char const*) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106c64f9b)
ocornut commented 8 years ago

OK so text_end is very wrong here. Could you track what happens in TextV() ?

ocornut commented 8 years ago

OK in ImFormatString and ImFormatStringV Try to change

return (w == -1) ? buf_size-1 : w; to return (w == -1) ? buf_size : w;

Assuming your lib/compiler version of vsnprintf if one that ever returns -1. Or inspect around that.

xaxxon commented 8 years ago

IGNORE THIS:

I put a breakpoint in ImFormatStringV and it is not being called for the string that crashes. I get a bunch that work, but the crash happens (it's a clang address santizier check fail, technically) before the breakpoint is hit. Address sanitization CAN give false positives...

It's crashing before it gets to TextV, as well.

I'm on clang 3.8 on os x.

xaxxon commented 8 years ago

This is odd -- I send the string "no jobs" through, and it works. Then I send the "keyboard mouse text" line through and it works. Then I send the really long one through, the "strlen of thing I'm sending to imgui: 3706" is expected, but then the next breakpoint says the string is "no jobs" but the length is 3706. And then it crashes (I trimmed the crash report, but you can see it beginning)


Process 17282 resuming
Process 17282 stopped
* thread #1: tid = 0x89c4c, 0x0000000106ca6890 apb`ImGui::TextV(fmt="No jobs", args=0x00007fff5fbfd200) + 16 at imgui.cpp:5238, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
    frame #0: 0x0000000106ca6890 apb`ImGui::TextV(fmt="No jobs", args=0x00007fff5fbfd200) + 16 at imgui.cpp:5238
   5235 
   5236 void ImGui::TextV(const char* fmt, va_list args)
   5237 {
-> 5238     ImGuiWindow* window = GetCurrentWindow();
   5239     if (window->SkipItems)
   5240         return;
   5241 
(lldb) c
Process 17282 resuming
Process 17282 stopped
* thread #1: tid = 0x89c4c, 0x0000000106c429e7 apb`ImFormatStringV(buf="keyboard: 0 mouse: 0 text: 0", buf_size=3073, fmt="No jobs", args=0x00007fff5fbfd200) + 23 at imgui.cpp:959, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x0000000106c429e7 apb`ImFormatStringV(buf="keyboard: 0 mouse: 0 text: 0", buf_size=3073, fmt="No jobs", args=0x00007fff5fbfd200) + 23 at imgui.cpp:959
   956  
   957  int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
   958  {
-> 959      int w = vsnprintf(buf, buf_size, fmt, args);
   960      buf[buf_size-1] = 0;
   961      return (w == -1) ? buf_size : w;
   962  }
(lldb) 
Process 17282 resuming
strlen of thing I'm sending to imgui: 3706
Process 17282 stopped
* thread #1: tid = 0x89c4c, 0x0000000106ca6890 apb`ImGui::TextV(fmt="%s", args=0x00007fff5fbfc5c0) + 16 at imgui.cpp:5238, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
    frame #0: 0x0000000106ca6890 apb`ImGui::TextV(fmt="%s", args=0x00007fff5fbfc5c0) + 16 at imgui.cpp:5238
   5235 
   5236 void ImGui::TextV(const char* fmt, va_list args)
   5237 {
-> 5238     ImGuiWindow* window = GetCurrentWindow();
   5239     if (window->SkipItems)
   5240         return;
   5241 
(lldb) p args
(__va_list_tag *) $11 = 0x00007fff5fbfc5c0
(lldb) c
Process 17282 resuming
Process 17282 stopped
* thread #1: tid = 0x89c4c, 0x0000000106c429e7 apb`ImFormatStringV(buf="No jobs", buf_size=3073, fmt="%s", args=0x00007fff5fbfc5c0) + 23 at imgui.cpp:959, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x0000000106c429e7 apb`ImFormatStringV(buf="No jobs", buf_size=3073, fmt="%s", args=0x00007fff5fbfc5c0) + 23 at imgui.cpp:959
   956  
   957  int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
   958  {
-> 959      int w = vsnprintf(buf, buf_size, fmt, args);
   960      buf[buf_size-1] = 0;
   961      return (w == -1) ? buf_size : w;
   962  }
(lldb) c
Process 17282 resuming
=================================================================
==17282==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000107400480 at pc 0x000106d6115e bp 0x7fff5fbfb970 sp 0x7fff5fbfb968
READ of size 1 at 0x000107400480 thread T0
    #0 0x106d6115d in ImFont::CalcTextSizeA(float, float, float, char const*, char const*, char const**) const (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106d6115d)
    #1 0x106c6bfc2 in ImGui::CalcTextSize(char const*, char const*, bool, float) (/Users/xaxxon/Library/Caches/CLion2016.2/cmake/generated/apb-21357782/21357782/Debug/apb+0x106c6bfc2)
xaxxon commented 8 years ago

You said:

Try to change

return (w == -1) ? buf_size-1 : w; to return (w == -1) ? buf_size : w;

but it already says that:

https://github.com/ocornut/imgui/blob/master/imgui.cpp#L954

https://github.com/ocornut/imgui/blob/master/imgui.cpp#L961

ocornut commented 8 years ago

Sorry the other way around, add the -1

xaxxon commented 8 years ago

Not sure if you had already figured this out for sure, but it works for TextUnformatted:

                    ImGui::PushTextWrapPos(0.0f);
                    ImGui::TextUnformatted(i->message.c_str());
                    ImGui::PopTextWrapPos();

image

adding the -1 now

ocornut commented 8 years ago

Yes, but it must be fixed for the other path. Does the -1 fixes it?

I'm finding it hard to read or grasp the explanation or content of most of your posts above..

e.g.

This is odd -- I send the string "no jobs" through, and it works. Then I send the "keyboard mouse text" line through and it works. Then I send the really long one through, the "strlen of thing I'm sending to imgui: 3706" is expected, but then the next breakpoint says the string is "no jobs" but the length is 3706.

xaxxon commented 8 years ago

adding the -1 in those two places didn't seem to change anything.


int ImFormatString(char* buf, int buf_size, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buf, buf_size, fmt, args);
    va_end(args);
    buf[buf_size-1] = 0;
    return (w == -1) ? buf_size-1 : w;
}

int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
{
    int w = vsnprintf(buf, buf_size, fmt, args);
    buf[buf_size-1] = 0;
    return (w == -1) ? buf_size-1 : w;
}
ocornut commented 8 years ago

Hmm... if you have a predictable repro, could you trace into it and figure out at which point text_end becomes miscalculated?

With this code-path it will use GImGui->TempBuffer as a temporary buffer within TextV. char TempBuffer[1024*3+1]; // temporary text buffer 3073 bytes,

So GImGui->TempBuffer[3072] is valid, GImGui->TempBuffer[3073] not valid. Since the buffer is limited your text will be clamped here and text_end should be == GImGui->TempBuffer+3072

I can't find to find a repro so far. :(

The -1 fix is most definitively a correct fix that needs to be pushed, I'm very surprised this doesn't fix it for you.

xaxxon commented 8 years ago

You're building with clang and -fsanitize=address set?

ocornut commented 8 years ago

I'm building with visuals and adding asserts.

xaxxon commented 8 years ago

This probably isn't the most useful format, but this is a decimal ascii dump of the string. I have to go to sleep for the hour before I need to wake up, and I'll look at this more this afternoon/evening pacific time. Thanks for all your help. I really hope this isn't some sort of weird clang address sanitization bug...

[deleted ridiculousness]

ocornut commented 8 years ago

err, how about fopen("dump.txt", "wb") fwrite() fclose()?

xaxxon commented 8 years ago

So when I'm looking at it later, what is text_end supposed to be?

Hrmm, I wonder if trailing \n's cause problems?

ocornut commented 8 years ago

OK I think I know what it is, your vsnprintf() behave differently than MSVCRT one.

xaxxon commented 8 years ago
 The snprintf() and vsnprintf() functions will write at most size-1 of the characters printed into the output string (the size'th char-
 acter then gets the terminating `\0'); if the return value is greater than or equal to the size argument, the string was too short and
 some of the printed characters were discarded.  The output is always null-terminated, unless size is 0.
ocornut commented 8 years ago

C libraries can't agree on a behavior for vsnprintf(), great..

try:

int ImFormatString(char* buf, int buf_size, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buf, buf_size, fmt, args);
    va_end(args);
    if (w == -1 || w >= buf_size)
        w = buf_size - 1;
    buf[w] = 0;
    return w;
}

int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
{
    int w = vsnprintf(buf, buf_size, fmt, args);
    if (w == -1 || w >= buf_size)
        w = buf_size - 1;
    buf[w] = 0;
    return w;
}
xaxxon commented 8 years ago

I think we can safely conclude that you are, in fact, da man.

image

ocornut commented 8 years ago

It is mildly annoying because glibc and msvcrt behave differently, and there's actually genuine use for both behaviors. Right now with the way we are using it with the glibc behavior it is doing a little unnecessary work (we wouldn't mind if it stopped counting).

I'll push a fix. In your situation you should still use TextUnformatted either way :)

Thanks for the help. Safe sleep!

xaxxon commented 8 years ago

http://demin.ws/blog/english/2013/01/28/use-snprintf-on-different-platforms/

Yikes:

On Windows the situation is even worse. First, the function returns -1 similar to HP-UX if the buffer is not big enough. Second, it does not count the trailing zero in the length of its output, which means it does not append the trailing zero at all in the situation of the small buffer. Though, Microsoft does not recommend using snprintf() at all as a non-thread safe function, and recommends _snprintf_s() instead.