1
0
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:
Gaurav Karna
2026-10-02 15:11:45 -07:00
committed by meta-codesync[bot]
parent 1d30cc568b
commit 87c2e187bf
2 changed files with 25 additions and 19 deletions

View File

@@ -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;
}

View File

@@ -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) {