#18629 closed defect (fixed)

Empty wxGrid ends application with an Assert.

Reported by: rocrail Owned by: Vadim Zeitlin <vadim@…>
Priority: normal Milestone:
Component: GUI-generic Version: dev-latest
Keywords: Cc: r.j.versluis@…
Blocked By: Blocking:
Patch: no

Description

Creating an empty grid will cause an assert.
This is an internal bug because checking a column pos without any columns is not possible.

With this small example the bug can be reproduced:

#include <wx/wx.h>
#include <wx/grid.h>

class MyApp : public wxApp
{
public:         
    bool OnInit()
    {
        wxFrame* frame = new wxFrame(nullptr, wxID_ANY, "wxGrid Test");
        wxGrid* grid = new wxGrid(frame,  wxID_ANY);
        grid->CreateGrid(0, 0);
        frame->Show();

        return true;
    }   
}; wxIMPLEMENT_APP(MyApp);

Change History (12)

comment:1 Changed 17 months ago by rocrail

  • Cc r.j.versluis@… added

Stack trace under macOS Catalina:

../include/wx/generic/grid.h(1522): assert "idx >= 0 && idx < m_numCols" failed in GetColPos(): invalid column index
Collecting stack trace information, please wait...Process 12687 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x0000000101409aa4 libwx_osx_cocoau-3.1.dylib`wxDefaultAssertHandler(wxString const&, int, wxString const&, wxString const&, wxString const&) + 116
libwx_osx_cocoau-3.1.dylib`wxDefaultAssertHandler:
->  0x101409aa4 <+116>: cmpl   $0x0, 0xc27d85(%rip)      ; guard variable for wxAppConsoleBase::GetValidTraits()::s_traitsConsole + 7
    0x101409aab <+123>: jle    0x101409b4f               ; <+287>
    0x101409ab1 <+129>: jmp    0x101409b92               ; <+354>
    0x101409ab6 <+134>: movq   0xc0b3bb(%rip), %rdi      ; wxAppConsoleBase::ms_appInstance
Target 0: (rocview) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
  * frame #0: 0x0000000101409aa4 libwx_osx_cocoau-3.1.dylib`wxDefaultAssertHandler(wxString const&, int, wxString const&, wxString const&, wxString const&) + 116
    frame #1: 0x0000000101407839 libwx_osx_cocoau-3.1.dylib`wxOnAssert(char const*, int, char const*, char const*, char const*) + 121
    frame #2: 0x0000000101603ff5 libwx_osx_cocoau-3.1.dylib`wxGUIEventLoop::~wxGUIEventLoop() + 197
    frame #3: 0x000000010154f676 libwx_osx_cocoau-3.1.dylib`wxDialog::ShowModal() + 182
    frame #4: 0x00000001017919b8 libwx_osx_cocoau-3.1.dylib`wxGenericMessageDialog::ShowModal() + 56
    frame #5: 0x000000010164faba libwx_osx_cocoau-3.1.dylib`wxGUIAppTraitsBase::ShowAssertDialog(wxString const&) + 506
    frame #6: 0x00000001014091a6 libwx_osx_cocoau-3.1.dylib`ShowAssertDialog(wxString const&, int, wxString const&, wxString const&, wxString const&, wxAppTraits*) + 838
    frame #7: 0x0000000101408cd8 libwx_osx_cocoau-3.1.dylib`wxAppConsoleBase::OnAssertFailure(wchar_t const*, int, wchar_t const*, wchar_t const*, wchar_t const*) + 248
    frame #8: 0x0000000101409b46 libwx_osx_cocoau-3.1.dylib`wxDefaultAssertHandler(wxString const&, int, wxString const&, wxString const&, wxString const&) + 278
    frame #9: 0x0000000101407839 libwx_osx_cocoau-3.1.dylib`wxOnAssert(char const*, int, char const*, char const*, char const*) + 121
    frame #10: 0x00000001017e61fc libwx_osx_cocoau-3.1.dylib`wxGrid::GetColPos(int) const + 76
    frame #11: 0x00000001017dbddf libwx_osx_cocoau-3.1.dylib`wxGrid::CalcColLabelsExposed(wxRegion const&, wxGridWindow*) const + 479
    frame #12: 0x00000001017dba69 libwx_osx_cocoau-3.1.dylib`wxGridColLabelWindow::OnPaint(wxPaintEvent&) + 313

comment:2 Changed 17 months ago by vadz

  • Status changed from new to confirmed

Thanks for reporting this, it looks like this bug was always there, but adding the assert checking for index validity in e2bd6ec8f73e0943a2dd9b9328642f578504497f made it more manifest.

I'll add a hack to avoid this problem.

comment:3 Changed 17 months ago by Vadim Zeitlin <vadim@…>

  • Owner set to Vadim Zeitlin <vadim@…>
  • Resolution set to fixed
  • Status changed from confirmed to closed

In 9c1e8fde/git-wxWidgets:

Avoid asserts when painting empty wxGridColLabelWindow

When the grid is empty, XToCol() has no choice but to return invalid
index (because there are no valid ones) when it's called from the
drawing code and passing such indices to GetColPos() results in an
assert, which is fatal inside wxEVT_PAINT handler.

Just short-circuit all this code by not doing anything in the case of
empty grid. This is sloppy, but simpler and more robust than any
alternatives.

Closes #18629.

comment:4 Changed 17 months ago by rocrail

  • Cc r.j.versluis@… removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

I just tested it, but the assert still ends the application under macOS.

../include/wx/generic/grid.h(1522): assert "idx >= 0 && idx < m_numCols" failed in GetColPos(): invalid column index
Collecting stack trace information, please wait...Process 18973 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x00000001017e620c libwx_osx_cocoau-3.1.dylib`wxGrid::GetColPos(int) const + 92
libwx_osx_cocoau-3.1.dylib`wxGrid::GetColPos:
->  0x1017e620c <+92>:  movq   0x5b0(%r14), %rax
    0x1017e6213 <+99>:  testq  %rax, %rax
    0x1017e6216 <+102>: je     0x1017e629f               ; <+239>
    0x1017e621c <+108>: movq   0x5c0(%r14), %rdx
Target 0: (rocview) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
  * frame #0: 0x00000001017e620c libwx_osx_cocoau-3.1.dylib`wxGrid::GetColPos(int) const + 92
    frame #1: 0x00000001017faa96 libwx_osx_cocoau-3.1.dylib`wxGridColumnOperations::GetLineEndPos(wxGrid const*, int) const + 118
    frame #2: 0x00000001017f2242 libwx_osx_cocoau-3.1.dylib`wxGrid::PosToEdgeOfLine(int, wxGridOperations const&) const + 98
    frame #3: 0x00000001017dc7e0 libwx_osx_cocoau-3.1.dylib`wxGrid::ProcessColLabelMouseEvent(wxMouseEvent&, wxGridColLabelWindow*) + 1792

comment:5 Changed 17 months ago by vadz

  • Status changed from reopened to confirmed

This is a different one :-( I'll fix it too in a moment.

comment:6 Changed 17 months ago by Vadim Zeitlin <vadim@…>

In 55f148a2/git-wxWidgets:

Avoid asserts when moving mouse in empty wxGridColLabelWindow too

The changes of the previous commit were insufficient, as we could also
use an invalid column index when handling mouse event in an empty grid.

Fix this by checking for the line validity in PosToEdgeOfLine() instead
of adding another ad hoc check to wxGridColLabelWindow itself, as it
seems reasonable for this function to verify that it uses valid indices.

See #18629.

comment:7 Changed 17 months ago by vadz

I'll wait with closing it until you can test the latest fix. I've tried moving the mouse around and resizing the window and it doesn't have any ill effects now, but please let me know if I've missed anything. TIA!

comment:8 Changed 17 months ago by rocrail

  • Cc r.j.versluis@… added

Thanks, the dialog with the empty grid does no longer crash.
However, clicking with the mouse pointer in the empty grid pops up an assert:

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libwx_osx_cocoau-3.1.dylib    	0x000000010197a20c wxGrid::GetColPos(int) const + 92
1   libwx_osx_cocoau-3.1.dylib    	0x000000010198ea96 wxGridColumnOperations::GetLineEndPos(wxGrid const*, int) const + 118
2   libwx_osx_cocoau-3.1.dylib    	0x0000000101986242 wxGrid::PosToEdgeOfLine(int, wxGridOperations const&) const + 98
3   libwx_osx_cocoau-3.1.dylib    	0x00000001019707e0 wxGrid::ProcessColLabelMouseEvent(wxMouseEvent&, wxGridColLabelWindow*) + 1792
4   libwx_osx_cocoau-3.1.dylib    	0x00000001016b62bf wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) + 447

comment:9 Changed 17 months ago by vadz

Strange, I can't reproduce this under MSW and I don't understand why would this be Mac-specific. With 55f148a2ea321daccd12e72cd986e7611ea8132f PosToEdgeOfLine() should return almost immediately, before calling GetLineEndPos() as line should be -1. Does it somehow have a different value for you?

comment:10 Changed 17 months ago by rocrail

  • Cc r.j.versluis@… removed

Maybe macOS provides zero instead of -1?

    // Get the bottom or rightmost line that could match.
    int line = oper.PosToLine(this, pos, NULL, true);

    if ( line == wxNOT_FOUND )
        return -1;

Just check if the grid has any rows and columns before trying to calculate some values...

comment:11 Changed 17 months ago by vadz

I don't see why would Mac be different and, worse, I've just tested it myself and I don't see the problem under Mac (10.14.6) neither. Are you absolutely sure you rebuilt with the commit mentioned above?

comment:12 Changed 17 months ago by rocrail

  • Cc r.j.versluis@… added
  • Resolution set to fixed
  • Status changed from confirmed to closed

Sorry, I recompiled all, and it seems now solved.
Thanks for your good work.

Note: See TracTickets for help on using tickets.