From 3b7aeaa2c5a9d3f3cc1fbfc9a642645cec1827be Mon Sep 17 00:00:00 2001 From: Lukas Tinkl Date: Wed, 17 Mar 2010 13:04:53 +0000 Subject: [PATCH] fix crash in kpixmapcache (#568389) --- kdelibs-4.4.2-kpixmapcache.patch | 167 +++++++++++++++++++++++++++++++ kdelibs.spec | 28 ++++-- 2 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 kdelibs-4.4.2-kpixmapcache.patch diff --git a/kdelibs-4.4.2-kpixmapcache.patch b/kdelibs-4.4.2-kpixmapcache.patch new file mode 100644 index 0000000..c7c6319 --- /dev/null +++ b/kdelibs-4.4.2-kpixmapcache.patch @@ -0,0 +1,167 @@ +--- kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/17 02:34:11 1104230 ++++ kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/17 02:38:08 1104231 +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -633,6 +634,10 @@ + qint32 leftchild, rightchild; + stream >> fkey >> foffset >> timesused >> lastused >> leftchild >> rightchild; + ++ if (fkey.isEmpty()) { ++ return start; ++ } ++ + if (key < fkey) { + if (leftchild) { + return binarySearchKey(stream, key, leftchild); +@@ -660,12 +665,21 @@ + // exist yet and there are no entries. Otherwise, do a binary search + // starting from the root node. + if (!stream.atEnd()) { ++ // One exception is that the root node may exist but be invalid, ++ // which can happen when the cache data is discarded. This is ++ // represented by an empty fkey ++ QString fkey; ++ stream >> fkey; ++ ++ if (fkey.isEmpty()) { ++ delete device; ++ return -1; ++ } ++ + int nodeoffset = binarySearchKey(stream, key, mIndexRootOffset); + + // Load the found entry and check if it's the one we're looking for. + device->seek(nodeoffset); +- QString fkey; +- stream >> fkey; + if (fkey == key) { + // Read offset and statistics + qint32 foffset; +@@ -814,7 +828,9 @@ + QString fkey; + stream.device()->seek(parentoffset); + stream >> fkey; +- if (key == fkey) { ++ ++ // The key would be empty if the cache had been discarded. ++ if (key == fkey || fkey.isEmpty()) { + // We're overwriting an existing entry + offset = parentoffset; + } +@@ -1195,16 +1211,14 @@ + return false; + } + +- d->invalidateMmapFiles(); +- d->unmmapFiles(); +- +- d->mEnabled = false; +- + KPCLockFile lock(d->mLockFileName); + // Hope we got the lock... + ++ d->invalidateMmapFiles(); ++ d->mEnabled = false; ++ + // Create index file +- QFile indexfile(d->mIndexFile); ++ KSaveFile indexfile(d->mIndexFile); + if (!indexfile.open(QIODevice::WriteOnly)) { + kError() << "Couldn't create index file" << d->mIndexFile; + return false; +@@ -1212,7 +1226,7 @@ + + d->mCacheId = ::time(0); + d->mTimestamp = ::time(0); +- ++ + // We can't know the full size until custom headers written. + // mmapFiles() will take care of correcting the size. + KPixmapCacheIndexHeader indexHeader = { {0}, KPIXMAPCACHE_VERSION, 0, d->mCacheId, d->mTimestamp }; +@@ -1221,7 +1235,7 @@ + indexfile.write(reinterpret_cast(&indexHeader), sizeof indexHeader); + + // Create data file +- QFile datafile(d->mDataFile); ++ KSaveFile datafile(d->mDataFile); + if (!datafile.open(QIODevice::WriteOnly)) { + kError() << "Couldn't create data file" << d->mDataFile; + return false; +@@ -1243,40 +1257,54 @@ + // Close the files and mmap them (if mmapping is used) + indexfile.close(); + datafile.close(); ++ indexfile.finalize(); ++ datafile.finalize(); ++ + d->mEnabled = true; + d->mmapFiles(); ++ + return true; + } + + void KPixmapCache::deleteCache(const QString& name) + { +- foreach (KPixmapCache::Private *d, Private::mCaches) { +- if (d->mName == name && d->mInited) { +- d->q->discard(); +- } +- } ++ QString indexFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + name + ".index"); ++ QString dataFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + name + ".data"); ++ ++ QFile::remove(indexFile); ++ QFile::remove(dataFile); + } + + void KPixmapCache::discard() + { +- d->invalidateMmapFiles(); +- d->unmmapFiles(); +- d->mInited = false; ++ // To "discard" the cache we simply have to make sure that every that ++ // was in there before is no longer present when we search for them. ++ // Easiest way to do *that* is to simply delete the index. ++ ++ KPCLockFile lock(d->mLockFileName); ++ if(!lock.isValid()) { ++ kError(264) << "Unable to lock pixmap cache when trying to discard it"; ++ return; ++ } ++ ++ QIODevice *device = d->indexDevice(); ++ if (!device) { ++ kError(264) << "Unable to access index when trying to discard cache"; ++ return; ++ } ++ ++ device->seek(d->mIndexRootOffset); ++ QDataStream stream(device); ++ ++ // Stream an empty QString as the hash key to signify that the cache ++ // has been discarded. ++ stream << QString(); + + if (d->mUseQPixmapCache) { + // TODO: This is broken, it removes every cached QPixmap in the whole + // process, not just this KPixmapCache. + QPixmapCache::clear(); + } +- +- QString indexFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + d->mName + ".index"); +- QString dataFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + d->mName + ".data"); +- +- QFile::remove(indexFile); +- QFile::remove(dataFile); +- +- // No need to remove the lockfile +- d->init(); + } + + void KPixmapCache::removeEntries(int newsize) diff --git a/kdelibs.spec b/kdelibs.spec index 3641b90..43bb6ef 100644 --- a/kdelibs.spec +++ b/kdelibs.spec @@ -8,7 +8,7 @@ Summary: KDE Libraries Version: 4.4.1 -Release: 3%{?dist} +Release: 6%{?dist} Name: kdelibs Epoch: 6 @@ -25,21 +25,22 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: kde4-macros(api) >= 2 BuildRequires: kde-filesystem >= 4-23 +%if 0%{?fedora} && 0%{?fedora} < 12 # used in kde.(sh|csh) Requires: coreutils grep -# dbus-launch needed here? don't think so, but be safe and keep -# for now -- Rex -Requires: dbus-x11 +%endif Requires: hicolor-icon-theme Requires: kde-filesystem >= 4-23 Requires: kde-settings %{?_kde4_macros_api:Requires: kde4-macros(api) = %{_kde4_macros_api} } -Requires: shared-mime-info -Requires: kdelibs-common +# versioned dep ok, as long as it comes from *here* +Requires: %{name}-common = %{epoch}:%{version}-%{release} +Requires: hal Requires: hunspell %global phonon_version %(pkg-config --modversion phonon 2>/dev/null || echo %{phonon_ver}) Requires: phonon%{?_isa} >= %{phonon_version} Requires: shared-desktop-ontologies +Requires: shared-mime-info %global soprano_version %(pkg-config --modversion soprano 2>/dev/null || echo %{soprano_ver}) Requires: soprano%{?_isa} >= %{soprano_version} %global strigi_version %(pkg-config --modversion libstreams 2>/dev/null || echo %{strigi_ver}) @@ -82,6 +83,8 @@ Patch24: kdelibs-4.3.1-drkonq.patch # paths (like /usr/lib64) already! With this, we can drop # -DCMAKE_SKIP_RPATH:BOOL=ON (finally) Patch27: kdelibs-4.3.98-no_rpath.patch +# bug:568389 (crash in kpixmapcache) +Patch28: kdelibs-4.4.2-kpixmapcache.patch # upstreamable @@ -230,6 +233,7 @@ format for easy browsing. %patch24 -p1 -b .drkonq %endif %patch27 -p1 -b .no_rpath +%patch28 -p1 -b .kpixmapcache # upstreamable patches @@ -425,6 +429,18 @@ rm -rf %{buildroot} %changelog +* Wed Mar 17 2010 Lukas Tinkl - 6:4.4.1-6 +- fix crash in KPixmapCache (bug#568389) + +* Tue Mar 09 2010 Rex Dieter - 6:4.4.1-5 +- rebuild (soprano) + +* Tue Mar 09 2010 Rex Dieter - 6:4.4.1-4 +- Requires: hal (for solid) +- drop Requires: dbus-x11 (it's already Req'd in kdebase-workspace) +- drop Requires: coreutils grep (F-12+) +- make Requires: kdelibs-common versioned + * Sun Feb 28 2010 Rex Dieter - 6:4.4.1-3 - put back CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE to avoid %%_libdir/kde/devel rpaths (#568495)