mirror of
https://github.com/facebook/proxygen.git
synced 2026-10-24 01:33:54 +03:00
Conform to appropriate Content-Length values
Summary: Reject malformed Content-Length values in the HTTP/1 codec before they can be framed leniently and forwarded verbatim. Reviewed By: hanidamlaj, samdlinn Differential Revision: D122834844 fbshipit-source-id: 73e1922a36bfd33b844f5aa44d09e36e40b57e37
This commit is contained in:
committed by
meta-codesync[bot]
parent
1d30cc568b
commit
87c2e187bf
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <proxygen/lib/http/codec/HTTP1xCodec.h>
|
||||
|
||||
#include <folly/Conv.h>
|
||||
#include <folly/Random.h>
|
||||
#include <folly/base64.h>
|
||||
#include <folly/io/Cursor.h>
|
||||
@@ -77,13 +78,17 @@ bool validateContentLen(const HTTPHeaders& hdrs) noexcept {
|
||||
const std::string* contentLen{nullptr};
|
||||
bool ok = !hdrs.forEachValueOfHeader(
|
||||
HTTP_HEADER_CONTENT_LENGTH, [&](const std::string& value) -> bool {
|
||||
if (folly::tryTo<uint64_t>(value).hasError()) {
|
||||
return true;
|
||||
}
|
||||
if (!contentLen) {
|
||||
contentLen = &value;
|
||||
return false; // continue
|
||||
}
|
||||
return *contentLen != value; // stop if different
|
||||
});
|
||||
LOG_IF(ERROR, !ok) << "Invalid message, multiple Content-Length headers";
|
||||
LOG_IF(ERROR, !ok)
|
||||
<< "Invalid message, malformed or multiple Content-Length headers";
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
@@ -592,25 +592,26 @@ TEST(HTTP1xCodecTest, TestMultipleIdenticalContentLengthHeaders) {
|
||||
EXPECT_EQ(callbacks.headersComplete, 1);
|
||||
}
|
||||
|
||||
TEST(HTTP1xCodecTest, TestMultipleDistinctContentLengthHeaders) {
|
||||
HTTP1xCodec codec(TransportDirection::DOWNSTREAM);
|
||||
FakeHTTPCodecCallback callbacks;
|
||||
codec.setCallback(&callbacks);
|
||||
folly::IOBufQueue writeBuf(folly::IOBufQueue::cacheChainLength());
|
||||
TEST(HTTP1xCodecTest, TestInvalidContentLengthHeaders) {
|
||||
for (auto contentLength : {"5\r\nContent-Length: 6", "1 2", "1\r\n 2"}) {
|
||||
SCOPED_TRACE(contentLength);
|
||||
HTTP1xCodec codec(TransportDirection::DOWNSTREAM);
|
||||
FakeHTTPCodecCallback callbacks;
|
||||
codec.setCallback(&callbacks);
|
||||
auto reqBuf = folly::IOBuf::copyBuffer(folly::to<std::string>(
|
||||
"POST /www.facebook.com HTTP/1.1\r\nHost: www.facebook.com\r\n"
|
||||
"Content-Length: ",
|
||||
contentLength,
|
||||
"\r\n\r\n"));
|
||||
codec.onIngress(*reqBuf);
|
||||
|
||||
// Generate a POST request with two distinct Content-Length headers
|
||||
auto reqBuf = folly::IOBuf::copyBuffer(
|
||||
"POST /www.facebook.com HTTP/1.1\r\nHost: www.facebook.com\r\n"
|
||||
"Content-Length: 5\r\nContent-Length: 6\r\n\r\n");
|
||||
codec.onIngress(*reqBuf);
|
||||
|
||||
// Check that the request fails before the codec finishes parsing the headers
|
||||
EXPECT_EQ(callbacks.streamErrors, 1);
|
||||
EXPECT_EQ(callbacks.messageBegin, 1);
|
||||
EXPECT_EQ(callbacks.headersComplete, 0);
|
||||
EXPECT_EQ(callbacks.lastParseError->getHttpStatusCode(), 400);
|
||||
EXPECT_THAT(callbacks.lastParseError->what(),
|
||||
HasSubstr("[Context]=invalid-content-length"));
|
||||
EXPECT_EQ(callbacks.streamErrors, 1);
|
||||
EXPECT_EQ(callbacks.messageBegin, 1);
|
||||
EXPECT_EQ(callbacks.headersComplete, 0);
|
||||
EXPECT_EQ(callbacks.lastParseError->getHttpStatusCode(), 400);
|
||||
EXPECT_THAT(callbacks.lastParseError->what(),
|
||||
HasSubstr("[Context]=invalid-content-length"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HTTP1xCodecTest, TestCorrectTransferEncodingHeader) {
|
||||
|
||||
Reference in New Issue
Block a user