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

Member call on null pointer on destruction of QWebEnginePage

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 5.12.0 Beta 4
    • 5.10.0, 5.12.0 Beta 3
    • None
    • macOS 10.12 / Ubuntu 17.04
    • 6c08137faf1a53db879701126608833474a2450b (qt/qtdeclarative/5.12)

    Description

      With a Qt WebEngine build with undefined sanitizer enabled, when running the tst_qwebenginehistoryinterface / tst_qwebengineshutdown test , the following crash is reported.

      /Volumes/T3/Dev/qt/qt510_source/qtdeclarative/src/quick/items/qquickopenglshadereffectnode.cpp:369:58: runtime error: member call on null pointer of type 'QObject'
      SUMMARY: AddressSanitizer: undefined-behavior /Volumes/T3/Dev/qt/qt510_source/qtdeclarative/src/quick/items/qquickopenglshadereffectnode.cpp:369:58 in
      ASAN:DEADLYSIGNAL
      =================================================================
      ==47701==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00013b934ba8 bp 0x7fff563d9f10 sp 0x7fff563d9e20 T0)
      ==47701==The signal is caused by a READ memory access.
      ==47701==Hint: address points to the zero page.
      [47702:775:1215/180415.686813:INFO:cpu_info.cc(50)] Available number of cores: 8
          #0 0x13b934ba7 in QQuickOpenGLShaderEffectMaterialCache::get(bool) qquickopenglshadereffectnode.cpp:369
          #1 0x13b935c84 in QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache() qquickopenglshadereffectnode.cpp:462
          #2 0x13b58aacd in QQuickRenderControlPrivate::windowDestroyed() qquickrendercontrol.cpp:196
          #3 0x13b5896ab in QQuickRenderControl::~QQuickRenderControl() qquickrendercontrol.cpp:181
          #4 0x109a797e9 in QQuickWidgetRenderControl::~QQuickWidgetRenderControl() qquickwidget.cpp:79
          #5 0x109a38d5c in QQuickWidgetPrivate::~QQuickWidgetPrivate() qquickwidget.cpp:219
          #6 0x109a3a3a9 in QQuickWidgetPrivate::~QQuickWidgetPrivate() qquickwidget.cpp:209
          #7 0x148c01846 in QObject::~QObject() qscopedpointer.h:107
          #8 0x13d59974a in QWidget::~QWidget() qwidget.cpp:1735
          #9 0x10990bb7d in QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget::~RenderWidgetHostViewQtDelegateWidget() render_widget_host_view_qt_delegate_widget.h:51
      [47702:775:1215/180430.691969:INFO:child_thread_impl.cc(854)] ChildThreadImpl::EnsureConnected()
          #10 0x10c3fb45f in QtWebEngineCore::RenderWidgetHostViewQt::~RenderWidgetHostViewQt() memory:2537
          #11 0x10c3fbd19 in QtWebEngineCore::RenderWidgetHostViewQt::~RenderWidgetHostViewQt() render_widget_host_view_qt.cpp:364
          #12 0x10ea2c051 in content::RenderWidgetHostImpl::Destroy(bool) render_widget_host_impl.cc:1797
          #13 0x10ea2070c in content::RenderViewHostImpl::ShutdownAndDestroy() render_view_host_impl.cc:748
          #14 0x10e2e6ebf in content::FrameTree::ReleaseRenderViewHostRef(content::RenderViewHostImpl*) frame_tree.cc:371
          #15 0x10e37f2ff in content::RenderFrameHostImpl::~RenderFrameHostImpl() render_frame_host_impl.cc:605
          #16 0x10e381425 in content::RenderFrameHostImpl::~RenderFrameHostImpl() render_frame_host_impl.cc:546
          #17 0x10e40410b in content::RenderFrameHostManager::~RenderFrameHostManager() memory:2537
          #18 0x10e2ecde0 in content::FrameTreeNode::~FrameTreeNode() frame_tree_node.cc:191
          #19 0x10e2e2a01 in content::FrameTree::~FrameTree() frame_tree.cc:116
          #20 0x10ed331dc in content::WebContentsImpl::~WebContentsImpl() web_contents_impl.cc:653
          #21 0x10ed34b65 in content::WebContentsImpl::~WebContentsImpl() web_contents_impl.cc:546
          #22 0x10c4b843d in QtWebEngineCore::WebContentsAdapterPrivate::~WebContentsAdapterPrivate() memory:2537
          #23 0x10c4bc300 in QScopedPointer<QtWebEngineCore::WebContentsAdapterPrivate, QScopedPointerDeleter<QtWebEngineCore::WebContentsAdapterPrivate> >::~QScopedPointer() web_contents_adapter.cpp:365
          #24 0x10c4bc25a in QtWebEngineCore::WebContentsAdapter::~WebContentsAdapter() web_contents_adapter.cpp:407
          #25 0x1098a2811 in QSharedPointer<QtWebEngineCore::WebContentsAdapter>::deref(QtSharedPointer::ExternalRefCountData*) qsharedpointer_impl.h:157
          #26 0x10984f54a in QWebEnginePagePrivate::~QWebEnginePagePrivate() qwebenginepage.cpp:242
          #27 0x10984f889 in QWebEnginePagePrivate::~QWebEnginePagePrivate() qwebenginepage.cpp:239
          #28 0x10986501e in QWebEnginePage::~QWebEnginePage() qscopedpointer.h:107
          #29 0x1098653b9 in QWebEnginePage::~QWebEnginePage() qwebenginepage.cpp:814
          #30 0x148c0314b in QObjectPrivate::deleteChildren() qobject.cpp:1992
          #31 0x13d59928f in QWidget::~QWidget() qwidget.cpp:1711
          #32 0x1098d74a9 in QWebEngineView::~QWebEngineView() qwebengineview.cpp:148
          #33 0x148b2c60c in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const qmetaobject.cpp:2305
          #34 0x109d22aed in QTest::TestMethods::invokeTestOnData(int) const qmetaobject.h:122
          #35 0x109d251a1 in QTest::TestMethods::invokeTest(int, char const*, QTest::WatchDog*) const qtestcase.cpp:1074
          #36 0x109d29f42 in QTest::TestMethods::invokeTests(QObject*) const qtestcase.cpp:1391
          #37 0x109d2d184 in QTest::qRun() qtestcase.cpp:1831
          #38 0x109d2c24f in QTest::qExec(QObject*, int, char**) qtestcase.cpp:1718
          #39 0x109828888 in main tst_qwebenginehistoryinterface.cpp:105
          #40 0x7fffcb6dc234 in start (libdyld.dylib:x86_64+0x5234)
      
      ==47701==Register values:
      rax = 0x0000000000000000  rbx = 0x00007fff563d9e80  rcx = 0x0000000000000000  rdx = 0x0000000000000000
      rdi = 0x9ddfea08eb382d69  rsi = 0x0000000000000000  rbp = 0x00007fff563d9f10  rsp = 0x00007fff563d9e20
       r8 = 0x000000000000003f   r9 = 0x0000000000000007  r10 = 0x00007fffcb80a966  r11 = 0x0000000000000206
      r12 = 0x0000000000000000  r13 = 0x00007fff563d9e20  r14 = 0x000060d00004d000  r15 = 0x92f0c4d889f2fdb9
      AddressSanitizer can not provide additional info.
      SUMMARY: AddressSanitizer: SEGV qquickopenglshadereffectnode.cpp:369 in QQuickOpenGLShaderEffectMaterialCache::get(bool)
      ==47701==ABORTING
      

      The relevant code in declarative is:

      class QQuickOpenGLShaderEffectMaterialCache : public QObject
      {
          Q_OBJECT
      public:
          static QQuickOpenGLShaderEffectMaterialCache *get(bool create = true) {
              QOpenGLContext *ctx = QOpenGLContext::currentContext();
              QQuickOpenGLShaderEffectMaterialCache *me = ctx->findChild<QQuickOpenGLShaderEffectMaterialCache *>(QStringLiteral("__qt_ShaderEffectCache"), Qt::FindDirectChildrenOnly);
              if (!me && create) {
                  me = new QQuickOpenGLShaderEffectMaterialCache();
                  me->setObjectName(QStringLiteral("__qt_ShaderEffectCache"));
                  me->setParent(ctx);
              }
              return me;
          }
          QHash<QQuickOpenGLShaderEffectMaterialKey, QSGMaterialType *> cache;
      };
      

      ctx->findChild is accessed, when ctx is 0.
      Adding a null pointer check avoids the crash, but that probably means that the cache member instance is leaked, because the only place where its values get deleted is in
      QuickOpenGLShaderEffectMaterial::cleanupMaterialCache, and if we do not return a cache object, that method will not call qDeleteAll.

      This avoids the crash, but possibly leaks.

      diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp
      index 5dbfee73c..c23aa1954 100644
      --- a/src/quick/items/qquickopenglshadereffectnode.cpp
      +++ b/src/quick/items/qquickopenglshadereffectnode.cpp
      @@ -366,7 +366,9 @@ class QQuickOpenGLShaderEffectMaterialCache : public QObject
       public:
           static QQuickOpenGLShaderEffectMaterialCache *get(bool create = true) {
               QOpenGLContext *ctx = QOpenGLContext::currentContext();
      -        QQuickOpenGLShaderEffectMaterialCache *me = ctx->findChild<QQuickOpenGLShaderEffectMaterialCache *>(QStringLiteral("__qt_ShaderEffectCache"), Qt::FindDirectChildrenOnly);
      +        QQuickOpenGLShaderEffectMaterialCache *me = 0;
      +        if (ctx)
      +            me = ctx->findChild<QQuickOpenGLShaderEffectMaterialCache *>(QStringLiteral("__qt_ShaderEffectCache"), Qt::FindDirectChildrenOnly);
               if (!me && create) {
                   me = new QQuickOpenGLShaderEffectMaterialCache();
                   me->setObjectName(QStringLiteral("__qt_ShaderEffectCache"));
      

      I have not yet figured out why the ctx is null.
      Also not sure if this is a bug in WebEngine or Quick.

      Attachments

        Issue Links

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

          Activity

            People

              juri.valdmann Jüri Valdmann (Inactive)
              alexandru.croitor Alexandru Croitor
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes