diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc index 525d3c96cc9..d9cfabf5518 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc @@ -682,9 +682,10 @@ void PackedDecode::endIngest(int4 bufPos) endPos.end = (*endPos.seqIter).end; // Make sure there is at least one character after ingested buffer if (bufPos == BUFFER_SIZE) { - // Last buffer was entirely filled - uint1 *endbuf = new uint1[1]; // Add one more buffer - inStream.emplace_back(endbuf,endbuf + 1); + // Last buffer was entirely filled — append a 1-byte tail chunk + auto owned = make_unique(1); + uint1 *endbuf = owned.get(); + inStream.emplace_back(move(owned),endbuf,endbuf + 1); bufPos = 0; } uint1 *buf = inStream.back().start; @@ -698,10 +699,8 @@ void PackedDecode::endIngest(int4 bufPos) PackedDecode::~PackedDecode(void) { - list::const_iterator iter; - for(iter=inStream.begin();iter!=inStream.end();++iter) { - delete [] (*iter).start; - } + // inStream's chunks own their buffers via ByteChunk::storage (unique_ptr), + // which cleans up automatically on chunk destruction. No manual delete[] needed. } void PackedDecode::ingestStream(istream &s) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh index 9817f7b0131..340d8d9ba89 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh @@ -19,11 +19,15 @@ #include "xml.hh" #include "opcodes.hh" #include +#include #include namespace ghidra { using std::list; +using std::make_unique; +using std::move; +using std::unique_ptr; using std::unordered_map; /// \brief An annotation for a data element to being transferred to/from a stream @@ -513,13 +517,22 @@ class PackedDecode : public Decoder { public: static const int4 BUFFER_SIZE; ///< The size, in bytes, of a single cached chunk of the input stream private: - /// \brief A bounded array of bytes + /// \brief A bounded array of bytes, owning its storage + /// + /// The chunk owns the underlying buffer via \b storage and exposes a [start,end) + /// window into it. The window typically covers the entire buffer; callers that + /// need a sub-range (e.g. the 1-byte padding tail in endIngest) pass an + /// explicit end pointer at construction. The unique_ptr cleans up on chunk + /// destruction, so PackedDecode's destructor no longer walks inStream. + /// Move-only — list::emplace_back constructs in place, so no copies needed. class ByteChunk { friend class PackedDecode; - uint1 *start; ///< Start of the byte array - uint1 *end; ///< End of the byte array + unique_ptr storage; ///< Owning storage for the byte array + uint1 *start; ///< Start of the valid window (points into storage) + uint1 *end; ///< End of the valid window (one past the last valid byte) public: - ByteChunk(uint1 *s,uint1 *e) { start = s; end = e; } ///< Constructor + ByteChunk(unique_ptr buf,uint1 *s,uint1 *e) : + storage(move(buf)), start(s), end(e) {} ///< Constructor }; /// \brief An iterator into input stream class Position { @@ -651,8 +664,9 @@ inline void PackedDecode::advancePosition(Position &pos,uint4 skip) inline uint1 *PackedDecode::allocateNextInputBuffer(int4 pad) { - uint1 *buf = new uint1[BUFFER_SIZE + pad]; - inStream.emplace_back(buf,buf+BUFFER_SIZE); + auto owned = make_unique(BUFFER_SIZE + pad); + uint1 *buf = owned.get(); + inStream.emplace_back(move(owned),buf,buf+BUFFER_SIZE); return buf; } diff --git a/gradle/cppRaiiAudit.gradle b/gradle/cppRaiiAudit.gradle index 94eaf3058ea..39059faf397 100644 --- a/gradle/cppRaiiAudit.gradle +++ b/gradle/cppRaiiAudit.gradle @@ -41,9 +41,13 @@ final Pattern RAW_NEW_PATTERN = Pattern.compile( // the address / space / rangeutil triangle that the audit named as // foundation files; subsequent stages extend the set. final Set PROTECTED_FILES = [ + // Rec 31 Stage 1 (#31-2) 'Ghidra/Features/Decompiler/src/decompile/cpp/address.cc', 'Ghidra/Features/Decompiler/src/decompile/cpp/space.cc', 'Ghidra/Features/Decompiler/src/decompile/cpp/rangeutil.cc', + // Rec 31 Stage 2 (#31-3) — marshal half + 'Ghidra/Features/Decompiler/src/decompile/cpp/marshal.cc', + 'Ghidra/Features/Decompiler/src/decompile/cpp/marshal.hh', ] as Set task cppRaiiAudit {