mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 08:31:43 +02:00
fix potential DoS vulnerability (through memory exhaustion) by restricting maximum line length
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "Poco/Net/Net.h"
|
#include "Poco/Net/Net.h"
|
||||||
#include "Poco/Net/StreamSocket.h"
|
#include "Poco/Net/StreamSocket.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -80,7 +81,7 @@ public:
|
|||||||
|
|
||||||
DialogSocket& operator = (const DialogSocket& socket);
|
DialogSocket& operator = (const DialogSocket& socket);
|
||||||
/// Assignment operator.
|
/// Assignment operator.
|
||||||
|
|
||||||
void sendByte(unsigned char ch);
|
void sendByte(unsigned char ch);
|
||||||
/// Sends a single byte over the socket connection.
|
/// Sends a single byte over the socket connection.
|
||||||
|
|
||||||
@@ -189,13 +190,14 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void allocBuffer();
|
void allocBuffer();
|
||||||
void refill();
|
void refill();
|
||||||
bool receiveLine(std::string& line);
|
bool receiveLine(std::string& line, std::size_t lineLengthLimit = 0);
|
||||||
int receiveStatusLine(std::string& line);
|
int receiveStatusLine(std::string& line, std::size_t lineLengthLimit = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RECEIVE_BUFFER_SIZE = 1024,
|
RECEIVE_BUFFER_SIZE = 1024,
|
||||||
|
MAX_LINE_LENGTH = 4096,
|
||||||
EOF_CHAR = -1
|
EOF_CHAR = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Net/DialogSocket.h"
|
#include "Poco/Net/DialogSocket.h"
|
||||||
|
#include "Poco/Exception.h"
|
||||||
#include "Poco/Ascii.h"
|
#include "Poco/Ascii.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@@ -149,20 +150,20 @@ void DialogSocket::sendMessage(const std::string& message, const std::string& ar
|
|||||||
bool DialogSocket::receiveMessage(std::string& message)
|
bool DialogSocket::receiveMessage(std::string& message)
|
||||||
{
|
{
|
||||||
message.clear();
|
message.clear();
|
||||||
return receiveLine(message);
|
return receiveLine(message, MAX_LINE_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int DialogSocket::receiveStatusMessage(std::string& message)
|
int DialogSocket::receiveStatusMessage(std::string& message)
|
||||||
{
|
{
|
||||||
message.clear();
|
message.clear();
|
||||||
int status = receiveStatusLine(message);
|
int status = receiveStatusLine(message, MAX_LINE_LENGTH);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
while (status <= 0)
|
while (status <= 0)
|
||||||
{
|
{
|
||||||
message += '\n';
|
message += '\n';
|
||||||
status = receiveStatusLine(message);
|
status = receiveStatusLine(message, MAX_LINE_LENGTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
@@ -236,14 +237,17 @@ void DialogSocket::allocBuffer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DialogSocket::receiveLine(std::string& line)
|
bool DialogSocket::receiveLine(std::string& line, std::size_t lineLengthLimit)
|
||||||
{
|
{
|
||||||
// An old wisdom goes: be strict in what you emit
|
// An old wisdom goes: be strict in what you emit
|
||||||
// and generous in what you accept.
|
// and generous in what you accept.
|
||||||
int ch = get();
|
int ch = get();
|
||||||
while (ch != EOF_CHAR && ch != '\r' && ch != '\n')
|
while (ch != EOF_CHAR && ch != '\r' && ch != '\n')
|
||||||
{
|
{
|
||||||
line += (char) ch;
|
if (lineLengthLimit == 0 || line.size() < lineLengthLimit)
|
||||||
|
line += (char) ch;
|
||||||
|
else
|
||||||
|
throw Poco::IOException("Line too long");
|
||||||
ch = get();
|
ch = get();
|
||||||
}
|
}
|
||||||
if (ch == '\r' && peek() == '\n')
|
if (ch == '\r' && peek() == '\n')
|
||||||
@@ -254,7 +258,7 @@ bool DialogSocket::receiveLine(std::string& line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int DialogSocket::receiveStatusLine(std::string& line)
|
int DialogSocket::receiveStatusLine(std::string& line, std::size_t lineLengthLimit)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int ch = get();
|
int ch = get();
|
||||||
@@ -274,7 +278,7 @@ int DialogSocket::receiveStatusLine(std::string& line)
|
|||||||
status = -status;
|
status = -status;
|
||||||
}
|
}
|
||||||
else status = 0;
|
else status = 0;
|
||||||
if (ch != EOF_CHAR) receiveLine(line);
|
if (ch != EOF_CHAR) receiveLine(line, lineLengthLimit);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user