From 6b660e7a481e87f73b995dee96788ef3ccd9c4f4 Mon Sep 17 00:00:00 2001 From: Karliss Date: Tue, 27 Feb 2024 00:14:01 +0200 Subject: [PATCH] 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. --- src/core/Cutter.cpp | 12 +++++------- src/core/Cutter.h | 4 +--- src/core/RizinCpp.h | 32 ++++++++++++++++++++++++++------ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 3b2eaa48..3bce681a 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -698,18 +698,16 @@ void CutterCore::delFlag(const QString &name) emit flagsChanged(); } -PRzAnalysisBytes CutterCore::getRzAnalysisBytesSingle(RVA addr) +CutterRzIter 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(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(rz_core_analysis_bytes(core, addr, buf, sizeof(buf), 1)); + return result; } QString CutterCore::getInstructionBytes(RVA addr) diff --git a/src/core/Cutter.h b/src/core/Cutter.h index 9634381b..1ebf89f8 100644 --- a/src/core/Cutter.h +++ b/src/core/Cutter.h @@ -62,8 +62,6 @@ struct CUTTER_EXPORT RegisterRef QString name; }; -using PRzAnalysisBytes = std::unique_ptr; - class CUTTER_EXPORT CutterCore : public QObject { Q_OBJECT @@ -248,7 +246,7 @@ public: QString getGlobalVariableType(RVA offset); /* Edition functions */ - PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr); + CutterRzIter getRzAnalysisBytesSingle(RVA addr); QString getInstructionBytes(RVA addr); QString getInstructionOpcode(RVA addr); void editInstruction(RVA addr, const QString &inst, bool fillWithNops = false); diff --git a/src/core/RizinCpp.h b/src/core/RizinCpp.h index 65fd95b6..0e0e1620 100644 --- a/src/core/RizinCpp.h +++ b/src/core/RizinCpp.h @@ -51,12 +51,6 @@ static inline auto fromOwned(RZ_OWN RzList *data) -> UniquePtrCP UniquePtrCP -{ - 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 +class CutterRzIter +{ + UniquePtrC 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 &operator++() + { + rz_iterator_next(rzIter.get()); + return *this; + } + operator bool() { return rzIter && rzIter->cur; } + T &operator*() { return *reinterpret_cast(rzIter->cur); } + T *get() { return reinterpret_cast(rzIter->cur); } + T *operator->() { return reinterpret_cast(rzIter->cur); } +}; + #endif // RIZINCPP_H