Fix multiple crashes related to incorrect rz_iterator usage.

RzAnalysisBytes are owned by the iterator, so returning analysis bytes while destroying iterator owning it is incorrect.
This commit is contained in:
Karliss 2024-02-27 00:14:01 +02:00 committed by karliss
parent 70024929af
commit 6b660e7a48
3 changed files with 32 additions and 16 deletions

View File

@ -698,18 +698,16 @@ void CutterCore::delFlag(const QString &name)
emit flagsChanged(); emit flagsChanged();
} }
PRzAnalysisBytes CutterCore::getRzAnalysisBytesSingle(RVA addr) CutterRzIter<RzAnalysisBytes> CutterCore::getRzAnalysisBytesSingle(RVA addr)
{ {
CORE_LOCK(); CORE_LOCK();
ut8 buf[128]; ut8 buf[128];
rz_io_read_at(core->io, addr, buf, sizeof(buf)); rz_io_read_at(core->io, addr, buf, sizeof(buf));
auto seek = seekTemp(addr); // Warning! only safe to use with stack buffer, due to instruction count being 1
auto abiter = fromOwned(rz_core_analysis_bytes(core, addr, buf, sizeof(buf), 1)); auto result =
auto ab = CutterRzIter<RzAnalysisBytes>(rz_core_analysis_bytes(core, addr, buf, sizeof(buf), 1));
abiter ? reinterpret_cast<RzAnalysisBytes *>(rz_iterator_next(abiter.get())) : nullptr; return result;
return { ab, rz_analysis_bytes_free };
} }
QString CutterCore::getInstructionBytes(RVA addr) QString CutterCore::getInstructionBytes(RVA addr)

View File

@ -62,8 +62,6 @@ struct CUTTER_EXPORT RegisterRef
QString name; QString name;
}; };
using PRzAnalysisBytes = std::unique_ptr<RzAnalysisBytes, decltype(rz_analysis_bytes_free) *>;
class CUTTER_EXPORT CutterCore : public QObject class CUTTER_EXPORT CutterCore : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -248,7 +246,7 @@ public:
QString getGlobalVariableType(RVA offset); QString getGlobalVariableType(RVA offset);
/* Edition functions */ /* Edition functions */
PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr); CutterRzIter<RzAnalysisBytes> getRzAnalysisBytesSingle(RVA addr);
QString getInstructionBytes(RVA addr); QString getInstructionBytes(RVA addr);
QString getInstructionOpcode(RVA addr); QString getInstructionOpcode(RVA addr);
void editInstruction(RVA addr, const QString &inst, bool fillWithNops = false); void editInstruction(RVA addr, const QString &inst, bool fillWithNops = false);

View File

@ -51,12 +51,6 @@ static inline auto fromOwned(RZ_OWN RzList *data) -> UniquePtrCP<decltype(data),
return { data, {} }; return { data, {} };
} }
static inline auto fromOwned(RZ_OWN RzIterator *data)
-> UniquePtrCP<decltype(data), &rz_iterator_free>
{
return { data, {} };
}
// Rizin list iteration macros // Rizin list iteration macros
// deprecated, prefer using CutterPVector and CutterRzList instead // deprecated, prefer using CutterPVector and CutterRzList instead
#define CutterRzListForeach(list, it, type, x) \ #define CutterRzListForeach(list, it, type, x) \
@ -170,4 +164,30 @@ public:
iterator end() const { return iterator(nullptr); } iterator end() const { return iterator(nullptr); }
}; };
template<typename T>
class CutterRzIter
{
UniquePtrC<RzIterator, &rz_iterator_free> rzIter;
public:
CutterRzIter(RzIterator *rzIter) : rzIter(rzIter)
{
// immediately attempt advancing by 1, otherwise it's hard to distinguish whether current
// element is null due to not having called next, or due to having run out of elements
if (rzIter) {
++*this;
}
}
CutterRzIter<T> &operator++()
{
rz_iterator_next(rzIter.get());
return *this;
}
operator bool() { return rzIter && rzIter->cur; }
T &operator*() { return *reinterpret_cast<RzAnalysisBytes *>(rzIter->cur); }
T *get() { return reinterpret_cast<RzAnalysisBytes *>(rzIter->cur); }
T *operator->() { return reinterpret_cast<RzAnalysisBytes *>(rzIter->cur); }
};
#endif // RIZINCPP_H #endif // RIZINCPP_H