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

irritating gotcha and crash in QCompleter popup()

    XMLWordPrintable

Details

    • All
    • 425e635ec (dev), d7db55431 (6.5), ab9fd4f8e (tqtc/lts-6.2)

    Description

      Seemingly harmless code crashes on line if (watched == popup()).

      #include <QApplication>
      #include <QComboBox>
      #include <QCompleter>
      #include <QListView>
      
      class MyCompleter : public QCompleter
      {
      public:
          MyCompleter()
          {
              setPopup(new QListView());
              popup()->installEventFilter(this);
          }
      
      protected:
          bool eventFilter(QObject *watched, QEvent *event) override
          {
              // The following line crashes. Can you spot the problem?
              if (watched == popup())
              {
                  // do something...
              }
      
              return QCompleter::eventFilter(watched, event);
          }
      };
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          QComboBox cb;
          cb.setEditable(true);
          cb.setCompleter(new MyCompleter());
          cb.show();
          return a.exec();
      }
      

      I explored the issue and the problem seems to be this:

      Line setPopup(new QListWidget()); calls QCompleter::setPopup() which installs event filter on the popup (so the line where we install the event filter is actually not needed, Qt does this for us automatically - but this is just implementation details so it is better to install the event filter ourselves), causes some events (ChildEvent) to be invoked and caught by the event filter.

      Now, the overridden event filter calls QCompleter::popup(). Its implementation contains the following line if (!d->popup ... etc.. So it checks d->popup but it is still equal to nullptr since d->popup is set in the very last line of QCompleter::setPopup(), which has not yet been executed.

      As a result the whole thing leads to infinite recursion of calling the event filter.

      I am reporting this as a bug because I think that some reordering of code in QCompleter::setPopup() may actually make the code (which is actually correct) not crash. Specifically I guess that moving d->popup = popup; several lines upwards might actually solve the issue.

      Attachments

        1. screenshot-1.png
          screenshot-1.png
          86 kB
        2. screenshot-2.png
          screenshot-2.png
          100 kB
        3. screenshot-3.png
          screenshot-3.png
          425 kB
        4. screenshot-4.png
          screenshot-4.png
          570 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            axelspoerl Axel Spoerl
            vladimir.kraus Vladimir Kraus
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes