Commit 07d59092 authored by Neel Goyal's avatar Neel Goyal Committed by Facebook Github Bot

Fix issue when reading more than 2GB

Summary: If performRead is called with bufLen > 2GB then overflow occurred with the value passed to SSL_read.  We'll clamp it here. This should be fine since performRead will be called again as there is more data to read.

Reviewed By: andriigrynenko, knekritz, mingtaoy

Differential Revision: D15625000

fbshipit-source-id: 8633686a76baebd796139f3b20c6f7286339fd96
parent 6c11bbdc
......@@ -1328,7 +1328,14 @@ AsyncSSLSocket::performRead(void** buf, size_t* buflen, size_t* offset) {
return AsyncSocket::performRead(buf, buflen, offset);
}
int bytes = SSL_read(ssl_.get(), *buf, int(*buflen));
int numToRead = 0;
if (*buflen > std::numeric_limits<int>::max()) {
numToRead = std::numeric_limits<int>::max();
VLOG(4) << "Clamping SSL_read to " << numToRead;
} else {
numToRead = int(*buflen);
}
int bytes = SSL_read(ssl_.get(), *buf, numToRead);
if (server_ && renegotiateAttempted_) {
LOG(ERROR) << "AsyncSSLSocket(fd=" << fd_ << ", state=" << int(state_)
......
......@@ -215,6 +215,49 @@ TEST(AsyncSSLSocketTest, ConnectWriteReadClose) {
EXPECT_EQ(socket->getSSLSocket()->getTotalConnectTimeout().count(), 10000);
}
/**
* Same as above simple test, but with a large read len to test
* clamping behavior.
*/
TEST(AsyncSSLSocketTest, ConnectWriteReadLargeClose) {
// Start listening on a local port
WriteCallbackBase writeCallback;
ReadCallback readCallback(&writeCallback);
HandshakeCallback handshakeCallback(&readCallback);
SSLServerAcceptCallback acceptCallback(&handshakeCallback);
TestSSLServer server(&acceptCallback);
// Set up SSL context.
std::shared_ptr<SSLContext> sslContext(new SSLContext());
sslContext->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
// sslContext->loadTrustedCertificates("./trusted-ca-certificate.pem");
// sslContext->authenticate(true, false);
// connect
auto socket =
std::make_shared<BlockingSocket>(server.getAddress(), sslContext);
socket->open(std::chrono::milliseconds(10000));
// write()
uint8_t buf[128];
memset(buf, 'a', sizeof(buf));
socket->write(buf, sizeof(buf));
// read()
uint8_t readbuf[128];
// we will fake the read len but that should be fine
size_t readLen = 1L << 33;
uint32_t bytesRead = socket->read(readbuf, readLen);
EXPECT_EQ(bytesRead, 128);
EXPECT_EQ(memcmp(buf, readbuf, bytesRead), 0);
// close()
socket->close();
cerr << "ConnectWriteReadClose test completed" << endl;
EXPECT_EQ(socket->getSSLSocket()->getTotalConnectTimeout().count(), 10000);
}
/**
* Test reading after server close.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment