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

QMetaMethod::invoke Segmentation Fault

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1: Critical
    • Resolution: Done
    • Affects Version/s: 5.8.0
    • Fix Version/s: 5.9.0
    • Component/s: Core: Object Model
    • Labels:
      None
    • Environment:

      All enviroments

    • Commits:
      d4cdc4542609e61d04802902d73c693faa8d8969

      Description

      Sorry I do not have the time to produce a small test case.

      Use any call to invoke QMetaMethod::invoke with multiple arguments where one of the parameters is an unregistered data type and the following parameter can be registered. E.g. two arguments, first is an enum with Q_ENUM, second is a QSharedPointer<MyObject> where MyObject is derived from QObject.

      Another thing to see this clearly as a bug, look at the value of i in the for loop running from 1 to paramCount. Whereas the moc-files produced by moc expect the arguments numbered from 0 to paramCount-1.

      Specifically it is the section handling the Registration of the Arguments:
      } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {

      Original text:

      In QueuedConnections the arguments are stored as pointers to objects create by QMetaType::create.

      The for loop below is copied from the Qt Source 5.8.
      If a type is known, " if (types[i] != QMetaType::UnknownType) {"
      then args[i] is set to the new object.
      Yet there is the case that the type is unknown and need to get registered first.

                 }  else if (param[i]) {
                      // Try to register the type and try again before reporting an error.
      

      But in this branch of the if-clause the value of args[i] is never set. So in the case the typed gets registered correctly, the corresponding args[i] is left at an undefined value while types[i] is set. This will cause a segmentation at the latest in QMetaCallEvent destructor which tries to delete args[i].

      The bug is in a for loop of qmetaobject.cpp line 2242ff (in the source version of Qt 5.8). As line numbers might have gotten shiften a copy of the for loop below.

       for (int i = 1; i < paramCount; ++i) {
                  types[i] = QMetaType::type(typeNames[i]);
                  if (types[i] != QMetaType::UnknownType) {
                      args[i] = QMetaType::create(types[i], param[i]);
                      ++nargs;
                  } else if (param[i]) {
                      // Try to register the type and try again before reporting an error.
                      void *argv[] = { &types[i], &i };
                      QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType,
                                            idx_relative + idx_offset, argv);
                      if (types[i] == -1) {
                          qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
                                  typeNames[i]);
                          for (int x = 1; x < i; ++x) {
                              if (types[x] && args[x])
                                  QMetaType::destroy(types[x], args[x]);
                          }
                          free(types);
                          free(args);
                          return false;
                      }
                  }
              }
      

        Attachments

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

          Activity

            People

            • Assignee:
              ogoffart Olivier Goffart (Woboq GmbH)
              Reporter:
              akrebs akrebs
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Gerrit Reviews

                There are no open Gerrit changes