Skip to content

Commit

Permalink
Fixes PointerVector's slicing issue for polymorphic types. (#1550)
Browse files Browse the repository at this point in the history
* Fixes PointerVector's slicing issue for polymorphic types.

- Adds a clone method that is enabled when the held type is non-polymorphic or contains a clone method.
- Deprecates the copy constructor and copy assignment operator.

* Fixed usages of post C++11 symbols.

* Updated PointerVector to use Copier helper struct to facilitate a copy mechanism.

* Added clone to RawPacket as it is polymorphic.

* Remove unused include.
  • Loading branch information
Dimi1010 authored Sep 20, 2024
1 parent 0aa0c83 commit 1debe6b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 10 deletions.
44 changes: 34 additions & 10 deletions Common++/header/PointerVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdexcept>
#include <vector>
#include <memory>
#include <type_traits>

#include "DeprecationUtils.h"

Expand All @@ -17,6 +18,34 @@
*/
namespace pcpp
{
namespace internal
{
/**
* @brief A helper struct to facilitate the creation of a copy of an object.
* @tparam T The type of object to copy.
* @tparam Enable Helper parameter for SFINAE.
*/
template <class T, class Enable = void> struct Copier
{
std::unique_ptr<T> operator()(const T& obj) const
{
return std::unique_ptr<T>(new T(obj));
}
};

/**
* @brief A specialization of Copier to facilitate the safe copying of polymorphic objects via clone() method.
* @tparam T The type of object to copy.
*/
template <class T> struct Copier<T, typename std::enable_if<std::is_polymorphic<T>::value>::type>
{
std::unique_ptr<T> operator()(const T& obj) const
{
// Clone can return unique_ptr or raw pointer.
return std::unique_ptr<T>(std::move(obj.clone()));
}
};
} // namespace internal

/**
* @class PointerVector
Expand Down Expand Up @@ -343,21 +372,16 @@ namespace pcpp
static std::vector<T*> deepCopyUnsafe(std::vector<T*> const& origin)
{
std::vector<T*> copyVec;
// Allocate the vector initially to ensure no exceptions are thrown during push_back.
copyVec.reserve(origin.size());

try
{
for (const auto iter : origin)
{
T* objCopy = new T(*iter);
try
{
copyVec.push_back(objCopy);
}
catch (const std::exception&)
{
delete objCopy;
throw;
}
std::unique_ptr<T> objCopy = internal::Copier<T>()(*iter);
// There shouldn't be a memory leak as the vector is reserved.
copyVec.push_back(objCopy.release());
}
}
catch (const std::exception&)
Expand Down
6 changes: 6 additions & 0 deletions Packet++/header/RawPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ namespace pcpp
*/
RawPacket& operator=(const RawPacket& other);

/**
* @brief Clones the current packet. Caller is responsible for deallocation of the memory.
* @return A pointer to the new RawPacket object which is a clone of this object
*/
virtual RawPacket* clone() const;

/**
* @return RawPacket object type. Each derived class should return a different value
*/
Expand Down
5 changes: 5 additions & 0 deletions Packet++/src/RawPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ namespace pcpp
return *this;
}

RawPacket* RawPacket::clone() const
{
return new RawPacket(*this);
}

void RawPacket::copyDataFrom(const RawPacket& other, bool allocateData)
{
if (!other.m_RawPacketSet)
Expand Down
7 changes: 7 additions & 0 deletions Pcap++/header/MBufRawPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ namespace pcpp
*/
MBufRawPacket& operator=(const MBufRawPacket& other);

/**
* @brief Clone this MBufRawPacket object. See copy constructor for details.
* The caller is responsible for the deallocation of the returned pointer.
* @return A pointer to the new MBufRawPacket object which is a clone of this object
*/
MBufRawPacket* clone() const override;

/**
* Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method
* which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this
Expand Down
5 changes: 5 additions & 0 deletions Pcap++/src/MBufRawPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ namespace pcpp
return *this;
}

MBufRawPacket* MBufRawPacket::clone() const
{
return new MBufRawPacket(*this);
}

bool MBufRawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType,
int frameLength)
{
Expand Down

0 comments on commit 1debe6b

Please sign in to comment.