Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-39008

crash in QAccessibleEvent::uniqueId() on MacOS 10.9.2

    XMLWordPrintable

Details

    • macOS

    Description

      My application crashes when I remove a selected row from QAbstractTableModel/QTableView with Accessibility enabled in the MacOS (System Preferences -> Accessibility -> VoiceOver -> Enable VoiceOver). With Accessibility disabled it works fine. So the problem seems to be that in QTableView::selectionChanged(selected, deselected), those deselected indices are not checked for validity.

      Application's output before the crash:

      selected:(QItemSelectionRange(QModelIndex(0,1,0x0,LayersModel(0x10366da00) )  , QModelIndex(0,3,0x0,LayersModel(0x10366da00) )  )  )
      deselected:(QItemSelectionRange(QModelIndex(1,1,0x0,LayersModel(0x10366da00) )  , QModelIndex(1,3,0x0,LayersModel(0x10366da00) )  )  )
      rows count:1
      QAccessibleTable::child: Invalid index at:  1 1
      

      ...and the backtrace:

      * thread #1: tid = 0x225b1, 0x00000001023cd18d QtGui`QAccessibleEvent::uniqueId() const + 157, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
        * frame #0: 0x00000001023cd18d QtGui`QAccessibleEvent::uniqueId() const + 157
          frame #1: 0x00000001076a604d libqcocoa.dylib`___lldb_unnamed_function766$$libqcocoa.dylib + 29
          frame #2: 0x0000000102064b6c QtWidgets`QTableView::selectionChanged(QItemSelection const&, QItemSelection const&) + 764
          frame #3: 0x000000010020f9a8 Flame Painter 3 Pro`LayersView::selectionChanged(this=0x000000010a8bb900, selected=0x00007fff5fbeef90, deselected=0x00007fff5fbeef98) + 9860 at layers_view.cpp:166
          frame #4: 0x000000010203a010 QtWidgets`___lldb_unnamed_function3663$$QtWidgets + 1120
          frame #5: 0x0000000102b06b0f QtCore`QMetaObject::activate(QObject*, int, int, void**) + 1871
          frame #6: 0x0000000102a9351d QtCore`QItemSelectionModel::emitSelectionChanged(QItemSelection const&, QItemSelection const&) + 1165
          frame #7: 0x0000000102a9301b QtCore`QItemSelectionModel::select(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>) + 731
          frame #8: 0x00000001001f81a4 Flame Painter 3 Pro`LayersSelectionModel::select(this=0x000000010bc41dc0, selection=0x00007fff5fbef578, command=QItemSelectionModel::SelectionFlags at 0x00007fff5fbef090) + 4918 at layers_selection_model.cpp:35
          frame #9: 0x0000000102a92cfb QtCore`QItemSelectionModel::select(QModelIndex const&, QFlags<QItemSelectionModel::SelectionFlag>) + 59
          frame #10: 0x000000010020c439 Flame Painter 3 Pro`LayersView::selectRow(this=0x000000010a8bb900, row=0) + 1317 at layers_view.cpp:138
          frame #11: 0x000000010020c9f9 Flame Painter 3 Pro`LayersView::SelectCurrentLayer(this=0x000000010a8bb900) + 1291 at layers_view.cpp:146
          frame #12: 0x00000001000888ae Flame Painter 3 Pro`PanelLayers::DeleteSelectedLayers_Process(this=0x000000010a8b5950) + 1614 at panel_layers.cpp:300
      

      ...and here is the relevant code:

      void LayersView::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected)
      {
      	QDBGF("selected:" << selected);
      	QDBGF("deselected:" << deselected);
      	QDBGF("rows count:"<<mpModel->rowCount());
      	QTableView::selectionChanged(selected, deselected);
      }
      
      void LayersSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
      {
      	if (mSelectionLocked) { return; }
      	if (command == NoUpdate) { return; }
      	if (selection.empty()) { return; }
      
      	// Create a new expanded selection
      	QItemSelection sel;
      	for (const QItemSelectionRange& range : selection) {
      		const QModelIndex& tl = range.topLeft();
      		const QModelIndex& br = range.bottomRight();
      		sel.push_back(QItemSelectionRange(
      			mpModel->index(tl.row(), mpModel->SELECTION_START_COLUMN),
      			mpModel->index(br.row(), mpModel->columnCount()-1)));
      	}
      	QItemSelectionModel::select(sel, command);
      }
      
      void LayersView::selectRow(int row)
      {
      	if (!mpModel) return;
      	const QModelIndex& index = mpModel->index(row, mpModel->SELECTION_START_COLUMN);
      	selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
      	selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
      }
      

      The workaround I use for now is this:

      void LayersView::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected)
      {
      	QItemSelection deselected_ok;
      	if (mpModel) {
      		for (QModelIndex i : deselected.indexes()) {
      			if (i.column() < mpModel->columnCount() &&
      			    i.row()    < mpModel->rowCount())
      			{
      				deselected_ok.select(i, i);
      			}
      		}
      	}
      	QTableView::selectionChanged(selected, deselected_ok);
      }
      

      Thanks for all your great work on the Qt!

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              frederik Frederik Gladhorn
              michalfapso Michal Fapso
              Votes:
              1 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes