Skip to content

Commit f8a025a

Browse files
committed
Fix a potential crash with cloning clipboard data
1 parent 711e32b commit f8a025a

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/common/common.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,46 +115,58 @@ class ClipboardDataGuard final {
115115
};
116116

117117
explicit ClipboardDataGuard(const QMimeData &data, bool *abortCloning = nullptr)
118-
: m_dataGuard(&data)
118+
: m_data(&data)
119119
, m_abort(abortCloning)
120120
{
121+
// This uses simple connection to ensure pointer is not destroyed
122+
// instead of QPointer to work around a possible Qt bug
123+
// (https://bugzilla.redhat.com/show_bug.cgi?id=2320093).
124+
m_connection = QObject::connect(m_data, &QObject::destroyed, [this](){
125+
m_data = nullptr;
126+
log( QStringLiteral("Clipboard data deleted"), LogWarning );
127+
});
121128
m_timerExpire.start();
122129
}
123130

131+
~ClipboardDataGuard()
132+
{
133+
QObject::disconnect(m_connection);
134+
}
135+
124136
QStringList formats()
125137
{
126138
ElapsedGuard _(QStringLiteral(), QStringLiteral("formats"));
127-
return refresh() ? m_dataGuard->formats() : QStringList();
139+
return refresh() ? m_data->formats() : QStringList();
128140
}
129141

130142
bool hasFormat(const QString &mime)
131143
{
132144
ElapsedGuard _(QStringLiteral("hasFormat"), mime);
133-
return refresh() && m_dataGuard->hasFormat(mime);
145+
return refresh() && m_data->hasFormat(mime);
134146
}
135147

136148
QByteArray data(const QString &mime)
137149
{
138150
ElapsedGuard _(QStringLiteral("data"), mime);
139-
return refresh() ? m_dataGuard->data(mime) : QByteArray();
151+
return refresh() ? m_data->data(mime) : QByteArray();
140152
}
141153

142154
QList<QUrl> urls()
143155
{
144156
ElapsedGuard _(QStringLiteral(), QStringLiteral("urls"));
145-
return refresh() ? m_dataGuard->urls() : QList<QUrl>();
157+
return refresh() ? m_data->urls() : QList<QUrl>();
146158
}
147159

148160
QString text()
149161
{
150162
ElapsedGuard _(QStringLiteral(), QStringLiteral("text"));
151-
return refresh() ? m_dataGuard->text() : QString();
163+
return refresh() ? m_data->text() : QString();
152164
}
153165

154166
bool hasText()
155167
{
156168
ElapsedGuard _(QStringLiteral(), QStringLiteral("hasText"));
157-
return refresh() && m_dataGuard->hasText();
169+
return refresh() && m_data->hasText();
158170
}
159171

160172
QImage getImageData()
@@ -165,7 +177,7 @@ class ClipboardDataGuard final {
165177

166178
// NOTE: Application hangs if using multiple sessions and
167179
// calling QMimeData::hasImage() on X11 clipboard.
168-
QImage image = m_dataGuard->imageData().value<QImage>();
180+
QImage image = m_data->imageData().value<QImage>();
169181
if ( image.isNull() ) {
170182
image.loadFromData( data(QStringLiteral("image/png")), "png" );
171183
if ( image.isNull() ) {
@@ -209,25 +221,26 @@ class ClipboardDataGuard final {
209221
if (m_abort && *m_abort)
210222
return false;
211223

212-
if (m_dataGuard.isNull())
224+
if (!m_data)
213225
return false;
214226

215227
const auto elapsed = m_timerExpire.elapsed();
216228
if (elapsed > 5000) {
217229
log(QStringLiteral("Clipboard data expired, refusing to access old data"), LogWarning);
218-
m_dataGuard = nullptr;
230+
m_data = nullptr;
219231
return false;
220232
}
221233

222234
if (elapsed > 100)
223235
QCoreApplication::processEvents();
224236

225-
return !m_dataGuard.isNull();
237+
return m_data;
226238
}
227239

228-
QPointer<const QMimeData> m_dataGuard;
240+
const QMimeData *m_data;
229241
QElapsedTimer m_timerExpire;
230242
bool *m_abort = nullptr;
243+
QMetaObject::Connection m_connection;
231244

232245
#ifdef COPYQ_WS_X11
233246
WakeUpThread m_wakeUpThread;

0 commit comments

Comments
 (0)