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();
}
PRzAnalysisBytes CutterCore::getRzAnalysisBytesSingle(RVA addr)
CutterRzIter<RzAnalysisBytes> CutterCore::getRzAnalysisBytesSingle(RVA addr)
{
CORE_LOCK();
ut8 buf[128];
rz_io_read_at(core->io, addr, buf, sizeof(buf));
auto seek = seekTemp(addr);
auto abiter = fromOwned(rz_core_analysis_bytes(core, addr, buf, sizeof(buf), 1));
auto ab =
abiter ? reinterpret_cast<RzAnalysisBytes *>(rz_iterator_next(abiter.get())) : nullptr;
return { ab, rz_analysis_bytes_free };
// Warning! only safe to use with stack buffer, due to instruction count being 1
auto result =
CutterRzIter<RzAnalysisBytes>(rz_core_analysis_bytes(core, addr, buf, sizeof(buf), 1));
return result;
}
QString CutterCore::getInstructionBytes(RVA addr)

View File

@ -62,8 +62,6 @@ struct CUTTER_EXPORT RegisterRef
QString name;
};
using PRzAnalysisBytes = std::unique_ptr<RzAnalysisBytes, decltype(rz_analysis_bytes_free) *>;
class CUTTER_EXPORT CutterCore : public QObject
{
Q_OBJECT
@ -248,7 +246,7 @@ public:
QString getGlobalVariableType(RVA offset);
/* Edition functions */
PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr);
CutterRzIter<RzAnalysisBytes> getRzAnalysisBytesSingle(RVA addr);
QString getInstructionBytes(RVA addr);
QString getInstructionOpcode(RVA addr);
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, {} };
}
static inline auto fromOwned(RZ_OWN RzIterator *data)
-> UniquePtrCP<decltype(data), &rz_iterator_free>
{
return { data, {} };
}
// Rizin list iteration macros
// deprecated, prefer using CutterPVector and CutterRzList instead
#define CutterRzListForeach(list, it, type, x) \
@ -170,4 +164,30 @@ public:
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