1
mirror of https://github.com/monero-project/monero-gui synced 2025-01-03 20:56:23 +01:00

Merge pull request #2758

742a465 AddressBook: thread-safety, fix use-after-free (xiphon)
This commit is contained in:
luigi1111 2020-02-04 14:36:35 -05:00
commit 080ec28eb4
No known key found for this signature in database
GPG Key ID: F4ACA0183641E010
3 changed files with 71 additions and 44 deletions

View File

@ -46,58 +46,85 @@ int AddressBook::errorCode() const
return m_addressBookImpl->errorCode(); return m_addressBookImpl->errorCode();
} }
QList<Monero::AddressBookRow*> AddressBook::getAll(bool update) const void AddressBook::getAll()
{ {
qDebug(__FUNCTION__); qDebug(__FUNCTION__);
emit refreshStarted(); emit refreshStarted();
if(update) {
m_rows.clear(); QWriteLocker locker(&m_lock);
if (m_rows.empty()){ m_rows.clear();
for (auto &abr: m_addressBookImpl->getAll()) { for (auto &abr: m_addressBookImpl->getAll()) {
m_rows.append(abr); m_rows.append(abr);
} }
} }
emit refreshFinished(); emit refreshFinished();
return m_rows;
} }
Monero::AddressBookRow * AddressBook::getRow(int index) const bool AddressBook::getRow(int index, std::function<void (Monero::AddressBookRow &)> callback) const
{ {
return m_rows.at(index); QReadLocker locker(&m_lock);
if (index < 0 || index >= m_rows.size())
{
return false;
}
callback(*m_rows.value(index));
return true;
} }
bool AddressBook::addRow(const QString &address, const QString &payment_id, const QString &description) const bool AddressBook::addRow(const QString &address, const QString &payment_id, const QString &description)
{ {
// virtual bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) = 0; // virtual bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) = 0;
bool r = m_addressBookImpl->addRow(address.toStdString(), payment_id.toStdString(), description.toStdString()); bool result;
if(r) {
getAll(true); QWriteLocker locker(&m_lock);
return r; result = m_addressBookImpl->addRow(address.toStdString(), payment_id.toStdString(), description.toStdString());
}
if (result)
{
getAll();
}
return result;
} }
bool AddressBook::deleteRow(int rowId) const bool AddressBook::deleteRow(int rowId)
{ {
bool r = m_addressBookImpl->deleteRow(rowId); bool result;
{
QWriteLocker locker(&m_lock);
result = m_addressBookImpl->deleteRow(rowId);
}
// Fetch new data from wallet2. // Fetch new data from wallet2.
getAll(true); if (result)
{
getAll();
}
return r; return result;
} }
quint64 AddressBook::count() const quint64 AddressBook::count() const
{ {
QReadLocker locker(&m_lock);
return m_rows.size(); return m_rows.size();
} }
int AddressBook::lookupPaymentID(const QString &payment_id) const int AddressBook::lookupPaymentID(const QString &payment_id) const
{ {
QReadLocker locker(&m_lock);
return m_addressBookImpl->lookupPaymentID(payment_id.toStdString()); return m_addressBookImpl->lookupPaymentID(payment_id.toStdString());
} }

View File

@ -31,6 +31,7 @@
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include <QObject> #include <QObject>
#include <QReadWriteLock>
#include <QList> #include <QList>
#include <QDateTime> #include <QDateTime>
@ -43,10 +44,9 @@ class AddressBook : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
Q_INVOKABLE QList<Monero::AddressBookRow*> getAll(bool update = false) const; Q_INVOKABLE bool getRow(int index, std::function<void (Monero::AddressBookRow &)> callback) const;
Q_INVOKABLE Monero::AddressBookRow * getRow(int index) const; Q_INVOKABLE bool addRow(const QString &address, const QString &payment_id, const QString &description);
Q_INVOKABLE bool addRow(const QString &address, const QString &payment_id, const QString &description) const; Q_INVOKABLE bool deleteRow(int rowId);
Q_INVOKABLE bool deleteRow(int rowId) const;
quint64 count() const; quint64 count() const;
Q_INVOKABLE QString errorString() const; Q_INVOKABLE QString errorString() const;
Q_INVOKABLE int errorCode() const; Q_INVOKABLE int errorCode() const;
@ -61,6 +61,8 @@ public:
Q_ENUM(ErrorCode); Q_ENUM(ErrorCode);
private:
void getAll();
signals: signals:
void refreshStarted() const; void refreshStarted() const;
@ -73,6 +75,7 @@ private:
explicit AddressBook(Monero::AddressBook * abImpl, QObject *parent); explicit AddressBook(Monero::AddressBook * abImpl, QObject *parent);
friend class Wallet; friend class Wallet;
Monero::AddressBook * m_addressBookImpl; Monero::AddressBook * m_addressBookImpl;
mutable QReadWriteLock m_lock;
mutable QList<Monero::AddressBookRow*> m_rows; mutable QList<Monero::AddressBookRow*> m_rows;
}; };

View File

@ -57,30 +57,27 @@ int AddressBookModel::rowCount(const QModelIndex &) const
QVariant AddressBookModel::data(const QModelIndex &index, int role) const QVariant AddressBookModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid()) QVariant result;
return QVariant();
if (index.row() < 0 || (unsigned)index.row() >= m_addressBook->count()) { bool found = m_addressBook->getRow(index.row(), [&result, &role](const Monero::AddressBookRow &row) {
return QVariant(); switch (role) {
} case AddressBookAddressRole:
result = QString::fromStdString(row.getAddress());
Monero::AddressBookRow * ar = m_addressBook->getRow(index.row()); break;
case AddressBookDescriptionRole:
QVariant result = ""; result = QString::fromStdString(row.getDescription());
switch (role) { break;
case AddressBookAddressRole: case AddressBookPaymentIdRole:
result = QString::fromStdString(ar->getAddress()); result = QString::fromStdString(row.getPaymentId());
break; break;
case AddressBookDescriptionRole: case AddressBookRowIdRole:
result = QString::fromStdString(ar->getDescription()); // Qt doesnt support size_t overload type casting
break; result.setValue(row.getRowId());
case AddressBookPaymentIdRole: break;
result = QString::fromStdString(ar->getPaymentId()); }
break; });
case AddressBookRowIdRole: if (!found) {
// Qt doesnt support size_t overload type casting qCritical("%s: internal error: invalid index %d", __FUNCTION__, index.row());
result.setValue(ar->getRowId());
break;
} }
return result; return result;