mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 18:20:26 +01:00
fix a potential DoS (through memory exhaustion) by restricting HTML form field name and value sizes
This commit is contained in:
parent
4392f13b9c
commit
f6d8d0e10a
@ -154,13 +154,11 @@ public:
|
||||
/// - the request's persistent connection state is left unchanged
|
||||
/// - the content transfer encoding is set to chunked
|
||||
|
||||
|
||||
std::streamsize calculateContentLength();
|
||||
/// Calculate the content length for the form.
|
||||
/// May be UNKNOWN_CONTENT_LENGTH if not possible
|
||||
/// to calculate
|
||||
|
||||
|
||||
void write(std::ostream& ostr, const std::string& boundary);
|
||||
/// Writes the form data to the given output stream,
|
||||
/// using the specified encoding.
|
||||
@ -186,11 +184,19 @@ public:
|
||||
/// Specify 0 for unlimited (not recommended).
|
||||
///
|
||||
/// The default limit is 100.
|
||||
|
||||
void setValueLengthLimit(int limit);
|
||||
/// Sets the maximum size for form field values
|
||||
/// stored as strings.
|
||||
|
||||
int getValueLengthLimit() const;
|
||||
/// Returns the maximum size for form field values
|
||||
/// stored as strings.
|
||||
|
||||
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
|
||||
static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
|
||||
|
||||
static const int UNKNOWN_CONTENT_LENGTH;
|
||||
|
||||
protected:
|
||||
void readUrl(std::istream& istr);
|
||||
void readMultipart(std::istream& istr, PartHandler& handler);
|
||||
@ -203,7 +209,9 @@ private:
|
||||
|
||||
enum Limits
|
||||
{
|
||||
DFL_FIELD_LIMIT = 100
|
||||
DFL_FIELD_LIMIT = 100,
|
||||
MAX_NAME_LENGTH = 1024,
|
||||
DFL_MAX_VALUE_LENGTH = 256*1024
|
||||
};
|
||||
|
||||
struct Part
|
||||
@ -215,6 +223,7 @@ private:
|
||||
typedef std::vector<Part> PartVec;
|
||||
|
||||
int _fieldLimit;
|
||||
int _valueLengthLimit;
|
||||
std::string _encoding;
|
||||
std::string _boundary;
|
||||
PartVec _parts;
|
||||
@ -242,6 +251,12 @@ inline int HTMLForm::getFieldLimit() const
|
||||
}
|
||||
|
||||
|
||||
inline int HTMLForm::getValueLengthLimit() const
|
||||
{
|
||||
return _valueLengthLimit;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
|
||||
|
@ -73,6 +73,7 @@ private:
|
||||
|
||||
HTMLForm::HTMLForm():
|
||||
_fieldLimit(DFL_FIELD_LIMIT),
|
||||
_valueLengthLimit(DFL_MAX_VALUE_LENGTH),
|
||||
_encoding(ENCODING_URL)
|
||||
{
|
||||
}
|
||||
@ -80,27 +81,31 @@ HTMLForm::HTMLForm():
|
||||
|
||||
HTMLForm::HTMLForm(const std::string& encoding):
|
||||
_fieldLimit(DFL_FIELD_LIMIT),
|
||||
_valueLengthLimit(DFL_MAX_VALUE_LENGTH),
|
||||
_encoding(encoding)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler):
|
||||
_fieldLimit(DFL_FIELD_LIMIT)
|
||||
_fieldLimit(DFL_FIELD_LIMIT),
|
||||
_valueLengthLimit(DFL_MAX_VALUE_LENGTH)
|
||||
{
|
||||
load(request, requestBody, handler);
|
||||
}
|
||||
|
||||
|
||||
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody):
|
||||
_fieldLimit(DFL_FIELD_LIMIT)
|
||||
_fieldLimit(DFL_FIELD_LIMIT),
|
||||
_valueLengthLimit(DFL_MAX_VALUE_LENGTH)
|
||||
{
|
||||
load(request, requestBody);
|
||||
}
|
||||
|
||||
|
||||
HTMLForm::HTMLForm(const HTTPRequest& request):
|
||||
_fieldLimit(DFL_FIELD_LIMIT)
|
||||
_fieldLimit(DFL_FIELD_LIMIT),
|
||||
_valueLengthLimit(DFL_MAX_VALUE_LENGTH)
|
||||
{
|
||||
load(request);
|
||||
}
|
||||
@ -296,7 +301,10 @@ void HTMLForm::readUrl(std::istream& istr)
|
||||
while (ch != eof && ch != '=' && ch != '&')
|
||||
{
|
||||
if (ch == '+') ch = ' ';
|
||||
name += (char) ch;
|
||||
if (name.size() < MAX_NAME_LENGTH)
|
||||
name += (char) ch;
|
||||
else
|
||||
throw HTMLFormException("Field name too long");
|
||||
ch = istr.get();
|
||||
}
|
||||
if (ch == '=')
|
||||
@ -305,7 +313,10 @@ void HTMLForm::readUrl(std::istream& istr)
|
||||
while (ch != eof && ch != '&')
|
||||
{
|
||||
if (ch == '+') ch = ' ';
|
||||
value += (char) ch;
|
||||
if (value.size() < _valueLengthLimit)
|
||||
value += (char) ch;
|
||||
else
|
||||
throw HTMLFormException("Field value too long");
|
||||
ch = istr.get();
|
||||
}
|
||||
}
|
||||
@ -359,7 +370,10 @@ void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
|
||||
int ch = istr.get();
|
||||
while (ch != eof)
|
||||
{
|
||||
value += (char) ch;
|
||||
if (value.size() < _valueLengthLimit)
|
||||
value += (char) ch;
|
||||
else
|
||||
throw HTMLFormException("Field value too long");
|
||||
ch = istr.get();
|
||||
}
|
||||
add(name, value);
|
||||
@ -439,4 +453,12 @@ void HTMLForm::setFieldLimit(int limit)
|
||||
}
|
||||
|
||||
|
||||
void HTMLForm::setValueLengthLimit(int limit)
|
||||
{
|
||||
poco_assert (limit >= 0);
|
||||
|
||||
_valueLengthLimit = limit;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
Loading…
Reference in New Issue
Block a user