[konversation] Crash in marker cleanup code (kde#210106)

Rex Dieter rdieter at fedoraproject.org
Fri Oct 21 16:45:02 UTC 2011


commit c8eb8ebb48ac2e5bc3743a2949b003f5f4a6801e
Author: Rex Dieter <rdieter at fedoraproject.org>
Date:   Fri Oct 21 11:45:01 2011 -0500

    Crash in marker cleanup code (kde#210106)

 ... konversation-1.3.1-fix_scroll_background.patch |    0
 konversation.spec                                  |   16 +-
 konverstation-1.3.1-kdebug210106.patch             |  418 ++++++++++++++++++++
 3 files changed, 431 insertions(+), 3 deletions(-)
---
diff --git a/konvi-1.3.1_fix-scroll_background.patch b/konversation-1.3.1-fix_scroll_background.patch
similarity index 100%
rename from konvi-1.3.1_fix-scroll_background.patch
rename to konversation-1.3.1-fix_scroll_background.patch
diff --git a/konversation.spec b/konversation.spec
index c90b6f1..94c21b0 100644
--- a/konversation.spec
+++ b/konversation.spec
@@ -1,7 +1,7 @@
 
 Name:           konversation
 Version:        1.3.1
-Release:        4%{?dist}
+Release:        5%{?dist}
 Summary:        A user friendly IRC client
 
 Group:          Applications/Internet
@@ -10,7 +10,11 @@ URL:            http://konversation.kde.org/
 Source0:        ftp://ftp.kde.org/pub/kde/%{?pre:un}stable/konversation/%{version}%{?pre:-%{pre}}/src/konversation-%{version}%{?pre:-%{pre}}.tar.bz2
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
-Patch10: konvi-1.3.1_fix-scroll_background.patch
+#Upstream patches
+Patch100: konversation-1.3.1-fix_scroll_background.patch
+# Crash in marker cleanup code [QList::*, IRCView::cullMarkedLine]
+# http://bugs.kde.org/210106
+Patch101: konverstation-1.3.1-kdebug210106.patch
 
 BuildRequires:  desktop-file-utils
 BuildRequires:  gettext
@@ -34,7 +38,10 @@ to chat windows; configurable background colors and much more
 
 %prep
 %setup -q -n %{name}-%{version}%{?pre:-%{pre}}
-%patch10 -p1
+
+%patch100 -p1 -b .fix_scroll_background
+%patch101 -p1 -b .kdebug210106
+
 
 %build
 mkdir -p %{_target_platform}
@@ -86,6 +93,9 @@ fi
 
 
 %changelog
+* Fri Oct 21 2011 Rex Dieter <rdieter at fedoraproject.org> 1.3.1-5
+- Crash in marker cleanup code (kde#210106)
+
 * Sat Mar 12 2011 Kevin Kofler <Kevin at tigcc.ticalc.org> - 1.3.1-4
 - add Requires: qca-ossl
 
diff --git a/konverstation-1.3.1-kdebug210106.patch b/konverstation-1.3.1-kdebug210106.patch
new file mode 100644
index 0000000..ec31781
--- /dev/null
+++ b/konverstation-1.3.1-kdebug210106.patch
@@ -0,0 +1,418 @@
+From: eli mackenzie <argonel at gmail.com>
+Date: Fri, 30 Sep 2011 10:41:58 +0000
+Subject: reformulation of cbe876c for v1.3.1
+X-Git-Url: http://quickgit.kde.org/?p=konversation.git&amp;a=commitdiff&amp;h=4a9627ef625342b450b1101ac1575bab44b5641a
+---
+reformulation of cbe876c for v1.3.1
+
+CCBUG:210106
+---
+
+
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,15 @@
++Changes from 1.3.1 to 1.3.1 #4056.1
++This patch was created as a stop-gap measure to allow
++Konversation 1.3.1 to work with Qt 4.7.4 and newer. Nokia allowed a
++source-incompatible change to fix a bug in QtCreator, which
++causes Konversation to crash when keeping track of the marker and
++remember lines.
++
++As this is not a released version, do not report bugs against it.
++
++For more information about the Qt change, see QTBUG-20916.
++
++
+ Changes from 1.3 to 1.3.1:
+ Konversation 1.3.1 is a maintenance release that improves program behavior
+ and fixes defects, the most serious of which is a regression that unfortu-
+
+--- a/src/commit.h
++++ b/src/commit.h
+@@ -1,4 +1,4 @@
+ // This COMMIT number is added to version string to be used as "patch level"
+ #ifndef COMMIT
+-#define COMMIT 4056
++#define COMMIT 4056.1
+ #endif
+
+--- a/src/version.h
++++ b/src/version.h
+@@ -1,3 +1,3 @@
+ #ifndef KONVI_VERSION
+-#define KONVI_VERSION "1.3.1"
++#define KONVI_VERSION "1.3.1 #4056.1"
+ #endif
+
+--- a/src/viewer/ircview.cpp
++++ b/src/viewer/ircview.cpp
+@@ -11,7 +11,7 @@
+   Copyright (C) 2002 Dario Abatianni <eisfuchs at tigress.com>
+   Copyright (C) 2005-2007 Peter Simonsson <psn at linux.se>
+   Copyright (C) 2006-2008 Eike Hein <hein at kde.org>
+-  Copyright (C) 2004-2009 Eli Mackenzie <argonel at gmail.com>
++  Copyright (C) 2004-2011 Eli Mackenzie <argonel at gmail.com>
+ */
+ 
+ #include "ircview.h"
+@@ -111,7 +111,10 @@ class SelectionPin
+             if (d->textCursor().hasSelection())
+             {
+                 int end = d->document()->rootFrame()->lastPosition();
+-                QTextBlock b = d->document()->lastBlock();
++
++                //WARNING if selection pins don't work in some build environments, we need to keep the result
++                d->document()->lastBlock();
++
+                 pos = d->textCursor().position();
+                 anc = d->textCursor().anchor();
+                 if (pos != end && anc != end)
+@@ -132,7 +135,7 @@ class SelectionPin
+ };
+ 
+ 
+-IRCView::IRCView(QWidget* parent, Server* newServer) : KTextBrowser(parent), m_nextCullIsMarker(false), m_rememberLinePosition(-1), m_rememberLineDirtyBit(false), markerFormatObject(this)
++IRCView::IRCView(QWidget* parent, Server* newServer) : KTextBrowser(parent), m_rememberLine(0), m_lastMarkerLine(0), m_rememberLineDirtyBit(false), markerFormatObject(this)
+ {
+     m_copyUrlMenu = false;
+     m_resetScrollbar = true;
+@@ -325,34 +328,6 @@ bool IRCView::searchNext(bool reversed)
+     return find(m_pattern, m_searchFlags);
+ }
+ 
+-//// Marker lines
+-
+-#define _S(x) #x << (x)
+-void dump_doc(QTextDocument* document)
+-{
+-    QTextBlock b(document->firstBlock());
+-    while (b.isValid())
+-    {
+-        kDebug()    << _S(b.position())
+-                    << _S(b.length())
+-                    << _S(b.userState())
+-                    ;
+-                    b=b.next();
+-    };
+-}
+-
+-QDebug operator<<(QDebug dbg, QList<QTextBlock> &l)
+-{
+-    dbg.space() << _S(l.count()) << endl;
+-        for (int i=0; i< l.count(); ++i)
+-        {
+-            QTextBlock b=l[i];
+-            dbg.space() << _S(i) << _S(b.blockNumber()) << _S(b.length()) << _S(b.userState()) << endl;
+-        }
+-
+-    return dbg.space();
+-}
+-
+ class IrcViewMimeData : public QMimeData
+ {
+ public:
+@@ -417,13 +392,52 @@ void IRCView::dropEvent(QDropEvent* e)
+         emit urlsDropped(KUrl::List::fromMimeData(e->mimeData(), KUrl::List::PreferLocalUrls));
+ }
+ 
++// Marker lines
++
++// This object gets stuffed into the userData field of a text block.
++// Qt does not give us a way to track blocks, so we have to
++// rely on the destructor of this object to notify us that a
++// block we care about was removed from the document. This does not
++// prevent the first block bug from deleting the wrong block's data,
++// however that should not result in a crash.
++struct Burr: public QTextBlockUserData
++{
++    Burr(IRCView* o, Burr* prev, QTextBlock b, int objFormat)
++        : m_block(b), m_format(objFormat), m_prev(prev), m_next(0),
++        m_owner(o)
++    {
++        if (m_prev)
++            m_prev->m_next = this;
++    }
++
++    ~Burr()
++    {
++        m_owner->blockDeleted(this);
++        unlink();
++    }
++
++    void unlink()
++    {
++        if (m_prev)
++            m_prev->m_next = m_next;
++        if (m_next)
++            m_next->m_prev = m_prev;
++    }
++
++    QTextBlock m_block;
++    int m_format;
++    Burr* m_prev, *m_next;
++    IRCView* m_owner;
++};
++
+ void IrcViewMarkerLine::drawObject(QPainter *painter, const QRectF &r, QTextDocument *doc, int posInDocument, const QTextFormat &format)
+ {
+     Q_UNUSED(format);
+ 
+     QTextBlock block=doc->findBlock(posInDocument);
+     QPen pen;
+-    switch (block.userState())
++    Burr* b = dynamic_cast<Burr*>(block.userData());
++    switch (b->m_format)
+     {
+         case IRCView::BlockIsMarker:
+             pen.setColor(Preferences::self()->color(Preferences::ActionMessage));
+@@ -456,33 +470,36 @@ QSizeF IrcViewMarkerLine::intrinsicSize(
+     return QSizeF(width, 6); // FIXME this is a hardcoded value...
+ }
+ 
++QTextCharFormat IRCView::getFormat(ObjectFormats x)
++{
++    QTextCharFormat f;
++    f.setObjectType(x);
++    return f;
++}
++
++void IRCView::blockDeleted(Burr* b) //slot
++{
++    //tracking only the tail
++    if (b == m_lastMarkerLine)
++        m_lastMarkerLine = b->m_prev;
++
++    if (b == m_rememberLine)
++        m_rememberLine = 0;
++}
++
+ void IRCView::cullMarkedLine(int where, int rem, int add) //slot
+ {
+-    if (where == 0 && add == 0 && rem !=0)
+-    {
+-        if (document()->blockCount() == 1 && document()->firstBlock().length() == 1)
+-        {
++    int blockCount = document()->blockCount();
++    QTextBlock prime = document()->firstBlock();
++
++    if (prime.length() == 1 && document()->blockCount() == 1)
+             wipeLineParagraphs();
+-        }
+-        else
+-        {
+-            if (m_nextCullIsMarker)
+-            {
+-                //move the remember line up.. if the cull removed it, this will forget its position
+-                if (m_rememberLinePosition >= 0)
+-                    --m_rememberLinePosition;
+-                m_markers.takeFirst();
+-            }
+-            int s = document()->firstBlock().userState();
+-            m_nextCullIsMarker = (s == BlockIsMarker || s == BlockIsRemember);
+-        }
+-    }
+ }
+ 
+ void IRCView::insertMarkerLine() //slot
+ {
+     //if the last line is already a marker of any kind, skip out
+-    if (lastBlockIsLine())
++    if (lastBlockIsLine(BlockIsMarker))
+         return;
+ 
+     //the code used to preserve the dirty bit status, but that was never affected by appendLine...
+@@ -505,7 +522,12 @@ void IRCView::cancelRememberLine() //slo
+ 
+ bool IRCView::lastBlockIsLine(int select)
+ {
+-    int state = document()->lastBlock().userState();
++    Burr *b = dynamic_cast<Burr*>(document()->lastBlock().userData());
++
++    int state = -1;
++
++    if (b)
++        state = b->m_format;
+ 
+     if (select == -1)
+         return (state == BlockIsRemember || state == BlockIsMarker);
+@@ -522,81 +544,51 @@ void IRCView::appendRememberLine()
+     if (lastBlockIsLine(BlockIsRemember))
+         return;
+ 
+-    // if we already have a rememberline, remove the previous one
+-    if (m_rememberLinePosition > -1)
++    if (m_rememberLine)
+     {
+-        //get the block that is the remember line
+-        QTextBlock rem = m_markers[m_rememberLinePosition];
+-        m_markers.removeAt(m_rememberLinePosition); //probably will be in there only once
+-        m_rememberLinePosition=-1;
++        QTextBlock rem = m_rememberLine->m_block;
+         voidLineBlock(rem);
++        if (m_rememberLine != 0)
++        {
++            kDebug() << "%%%%%%%%%%%%%%%%% m_rememberLine still set!";
++            // this probably means we had a block containing only 0x2029, so Scribe merged the userData/userState into the next
++            m_rememberLine = 0;
++        }
+     }
+ 
+-    //tell the control we did stuff
+-    //FIXME do we still do something like this?
+-    //repaintChanged();
++    m_rememberLine = appendLine(IRCView::RememberLine);
+ 
+-    //actually insert a line
+-    appendLine(IRCView::RememberLine);
+-
+-    //store the index of the remember line
+-    m_rememberLinePosition = m_markers.count() - 1;
+ }
+ 
+ void IRCView::voidLineBlock(QTextBlock rem)
+ {
+-    if (rem.blockNumber() == 0)
+-    {
+-        Q_ASSERT(m_nextCullIsMarker);
+-        m_nextCullIsMarker = false;
+-    }
+     QTextCursor c(rem);
+-    //FIXME make sure this doesn't flicker
++
+     c.select(QTextCursor::BlockUnderCursor);
+     c.removeSelectedText();
+ }
+ 
+ void IRCView::clearLines()
+ {
+-    //if we have a remember line, put it in the list
+-        //its already in the list
+ 
+-    kDebug() << _S(m_nextCullIsMarker) << _S(m_rememberLinePosition) << _S(textCursor().position()) << m_markers;
+-    dump_doc(document());
+-
+-    //are there any markers?
+-    if (hasLines())
++    while (hasLines())
+     {
+-        for (int i=0; i < m_markers.count(); ++i)
+-            voidLineBlock(m_markers[i]);
+-
+-        wipeLineParagraphs();
+-
+-        //FIXME do we have this? //repaintChanged();
+-    }
+-
++        //IRCView::blockDeleted takes care of the pointers
++        voidLineBlock(m_lastMarkerLine->m_block);
++    };
+ }
+ 
+ void IRCView::wipeLineParagraphs()
+ {
+-    m_nextCullIsMarker = false;
+-    m_rememberLinePosition = -1;
+-    m_markers.clear();
++    m_rememberLine = m_lastMarkerLine = 0;
+ }
+ 
+ bool IRCView::hasLines()
+ {
+-    return m_markers.count() > 0;
++    return m_lastMarkerLine != 0;
+ }
+ 
+-QTextCharFormat IRCView::getFormat(ObjectFormats x)
+-{
+-    QTextCharFormat f;
+-    f.setObjectType(x);
+-    return f;
+-}
+-
+-void IRCView::appendLine(IRCView::ObjectFormats type)
++Burr* IRCView::appendLine(IRCView::ObjectFormats type)
+ {
+     ScrollBarPin barpin(verticalScrollBar());
+     SelectionPin selpin(this);
+@@ -604,13 +596,21 @@ void IRCView::appendLine(IRCView::Object
+     QTextCursor cursor(document());
+     cursor.movePosition(QTextCursor::End);
+ 
+-    cursor.insertBlock();
++    if (cursor.block().length() > 1) // this will be a 0x2029
++        cursor.insertBlock();
+     cursor.insertText(QString(QChar::ObjectReplacementCharacter), getFormat(type));
+-    cursor.block().setUserState(type == MarkerLine? BlockIsMarker : BlockIsRemember);
+ 
+-    m_markers.append(cursor.block());
+-}
++    QTextBlock block = cursor.block();
++    Burr *b = new Burr(this, m_lastMarkerLine, block, type == MarkerLine? BlockIsMarker : BlockIsRemember);
++    block.setUserData(b);
++
++    m_lastMarkerLine = b;
+ 
++    //TODO figure out what this is for
++    cursor.setPosition(block.position());
++
++    return b;
++}
+ 
+ //// Other stuff
+ 
+
+--- a/src/viewer/ircview.h
++++ b/src/viewer/ircview.h
+@@ -24,7 +24,7 @@
+ 
+ class Server;
+ class ChatWindow;
+-
++class Burr;
+ 
+ class KToggleAction;
+ class KMenu;
+@@ -139,9 +139,10 @@ class IRCView : public KTextBrowser
+         void appendRememberLine();
+ 
+         /// Create a remember line and insert it.
+-        void appendLine(ObjectFormats=MarkerLine);
++        /// @return - Pointer to the Burr that was inserted into the block
++        Burr* appendLine(ObjectFormats=MarkerLine);
+ 
+-        /// Forget the position of the remember line and markers.
++        /// Convenience method - forget the position of the remember line and markers.
+         void wipeLineParagraphs();
+ 
+         /// Convenience method - is the last block any sort of line, or a specific line?
+@@ -154,16 +155,22 @@ class IRCView : public KTextBrowser
+         /// Shortcut to get an object format of the desired type
+         QTextCharFormat getFormat(ObjectFormats);
+ 
++    public slots:
++        // Doesn't have to be a slot, but what the hay.
++        /// Called *only* from ~Burr(), by QTextBlockData::free
++        void blockDeleted(Burr* b);
++
+     private slots:
+-        /** Called to see if a marker is queued up for deletion. Only triggers if
+-            "where" is the beginning and there was nothing added.
+-        */
++        /** Called every time a change occurs to the document.
++         *
++         * Used to infer the clearing of the entire document,
++         * because Trolltech removed virtual from the method
++         * that would indicate authoritatively.
++         */
+         void cullMarkedLine(int, int, int);
+ 
+     private: //marker/remember line data
+-        bool m_nextCullIsMarker; ///< the next time a cull occurs, it'll be a marker
+-        QList<QTextBlock> m_markers; ///< what blocks are markers?
+-        int m_rememberLinePosition; ///< position of remember line in m_markers
++        Burr *m_rememberLine, *m_lastMarkerLine;
+         bool m_rememberLineDirtyBit; ///< the next append needs a remember line
+         IrcViewMarkerLine markerFormatObject; ///< a QTextObjectInterface
+ 
+


More information about the scm-commits mailing list