Skip to content

Commit

Permalink
Fix SingleCommandTextProtocol parsing (#1259)
Browse files Browse the repository at this point in the history
* fix SingleCommandTextProtocol

* comment fix

* fix space
  • Loading branch information
egecetin authored Dec 8, 2023
1 parent b31bdfa commit 4e848ce
Showing 1 changed file with 33 additions and 24 deletions.
57 changes: 33 additions & 24 deletions Packet++/src/SingleCommandTextProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,41 @@

#define ASCII_HYPHEN 0x2d
#define ASCII_SPACE 0x20
#define MAX_COMMAND_LENGTH 9 // From SMTP command "STARTTLS" + 1 byte hyphen or space
#define MIN_PACKET_LENGTH 2 // CRLF

namespace pcpp
{

size_t SingleCommandTextProtocol::getArgumentFieldOffset() const
{
size_t maxLen;
if (m_DataLen < 5)
if (m_DataLen < MAX_COMMAND_LENGTH)
maxLen = m_DataLen;
else
maxLen = 5;
maxLen = MAX_COMMAND_LENGTH;

// Find <SP> if exists
uint8_t *pos = (uint8_t *)memchr(m_Data, ASCII_SPACE, maxLen);
if (pos)
return pos - m_Data;
// To correctly detect multi-line packets with the option containing a space in
// the first MAX_CONTENT_LENGTH bytes, search the both of hyphen and space to take
// correct command delimiter

// Find Hyphen "-" if exists
pos = (uint8_t *)memchr(m_Data, ASCII_HYPHEN, maxLen);
if (pos)
return pos - m_Data;
std::string field(reinterpret_cast<char *>(m_Data), maxLen);

return m_DataLen - 1;
size_t posHyphen = field.find_first_of(ASCII_HYPHEN);
size_t posSpace = field.find_first_of(ASCII_SPACE);
size_t posCRLF = field.rfind("\r\n");

// No delimiter or packet end
if (posHyphen == std::string::npos && posSpace == std::string::npos && posCRLF == std::string::npos)
return 0;
// Both hyphen and space found
else if (posHyphen != std::string::npos || posSpace != std::string::npos)
return std::min(posSpace, posHyphen);
// If nothing found but there is a CRLF it is a only command packet
else if (posCRLF != std::string::npos)
return posCRLF;

return 0;
}

void SingleCommandTextProtocol::setDelimiter(bool hyphen)
Expand All @@ -38,17 +50,17 @@ namespace pcpp
memset(&m_Data[getArgumentFieldOffset()], ASCII_SPACE, 1);
}

bool SingleCommandTextProtocol::hyphenRequired(const std::string& value)
bool SingleCommandTextProtocol::hyphenRequired(const std::string &value)
{
size_t firstPos = value.find_first_of("\r\n");
size_t lastPos = value.find_last_of("\r\n");
return (firstPos != std::string::npos) && (lastPos != std::string::npos) && (firstPos != lastPos - 1);
size_t firstPos = value.find("\r\n");
size_t lastPos = value.rfind("\r\n");
return (firstPos != std::string::npos) && (lastPos != std::string::npos) && (firstPos != lastPos);
}

SingleCommandTextProtocol::SingleCommandTextProtocol(const std::string &command, const std::string &option)
{
m_Data = new uint8_t[6];
m_DataLen = 6;
m_Data = new uint8_t[MIN_PACKET_LENGTH];
m_DataLen = MIN_PACKET_LENGTH;
if (!command.empty())
setCommandInternal(command);
if (!option.empty())
Expand Down Expand Up @@ -80,7 +92,7 @@ namespace pcpp

bool SingleCommandTextProtocol::setCommandOptionInternal(std::string value)
{
size_t lastPos = value.find_last_of("\r\n");
size_t lastPos = value.rfind("\r\n");
if (lastPos == std::string::npos || lastPos != value.size() - 2)
value += "\r\n";

Expand Down Expand Up @@ -123,18 +135,15 @@ namespace pcpp
return "";
}

bool SingleCommandTextProtocol::isMultiLine() const
{
return m_Data[getArgumentFieldOffset()] == ASCII_HYPHEN;
}
bool SingleCommandTextProtocol::isMultiLine() const { return m_Data[getArgumentFieldOffset()] == ASCII_HYPHEN; }

bool SingleCommandTextProtocol::isDataValid(const uint8_t *data, size_t dataSize)
{
if (data == nullptr || dataSize < 6)
if (data == nullptr || dataSize < MIN_PACKET_LENGTH)
return false;

std::string payload = std::string((char *)data, dataSize);
return payload.find_last_of("\r\n") == dataSize - 1;
return payload.rfind("\r\n") == dataSize - 2;
}

} // namespace pcpp

0 comments on commit 4e848ce

Please sign in to comment.