Skip to content

Commit f36ec92

Browse files
authored
Merge pull request #1117 from Altinity/backport/25.3.8/88668
25.3.8 Backport of ClickHouse#88668: make `HTTPChunkedStreamBuf::isComplete` noexcept
2 parents 6692348 + 2a5a015 commit f36ec92

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

base/poco/Net/include/Poco/Net/HTTPChunkedStream.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ namespace Net
4545
~HTTPChunkedStreamBuf();
4646
void close();
4747

48-
bool isComplete() const { return _chunk == std::char_traits<char>::eof(); }
48+
bool isComplete(bool read_from_device_to_check_eof = false) noexcept;
4949

5050
protected:
5151
int readFromDevice(char * buffer, std::streamsize length);
@@ -70,8 +70,6 @@ namespace Net
7070
~HTTPChunkedIOS();
7171
HTTPChunkedStreamBuf * rdbuf();
7272

73-
bool isComplete() const { return _buf.isComplete(); }
74-
7573
protected:
7674
HTTPChunkedStreamBuf _buf;
7775
};
@@ -83,6 +81,8 @@ namespace Net
8381
public:
8482
HTTPChunkedInputStream(HTTPSession & session);
8583
~HTTPChunkedInputStream();
84+
85+
bool isComplete() { return _buf.isComplete(/*read_from_device_to_check_eof*/ true); }
8686
};
8787

8888

@@ -92,6 +92,8 @@ namespace Net
9292
public:
9393
HTTPChunkedOutputStream(HTTPSession & session);
9494
~HTTPChunkedOutputStream();
95+
96+
bool isComplete() { return _buf.isComplete(); }
9597
};
9698

9799

base/poco/Net/src/HTTPChunkedStream.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void HTTPChunkedStreamBuf::close()
5454
sync();
5555
_session.write("0\r\n\r\n", 5);
5656

57-
_chunk = std::char_traits<char>::eof();
57+
_chunk = std::char_traits<char>::eof();
5858
}
5959
}
6060

@@ -90,7 +90,7 @@ unsigned int HTTPChunkedStreamBuf::parseChunkLen()
9090
if (size_t pos = line.find(';'); pos != std::string::npos)
9191
line.resize(pos);
9292

93-
unsigned chunkLen;
93+
unsigned chunkLen = 0;
9494
if (NumberParser::tryParseHex(line, chunkLen))
9595
return chunkLen;
9696
else
@@ -118,6 +118,9 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
118118

119119
if (_chunk > 0)
120120
{
121+
if (length == 0)
122+
return 0;
123+
121124
if (length > _chunk) length = _chunk;
122125
int n = _session.read(buffer, length);
123126
if (n > 0)
@@ -128,7 +131,7 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
128131
if (_chunk == 0) skipCRLF();
129132
return n;
130133
}
131-
else
134+
else
132135
{
133136
skipCRLF();
134137
_chunk = eof;
@@ -137,6 +140,26 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
137140
}
138141

139142

143+
bool HTTPChunkedStreamBuf::isComplete(bool read_from_device_to_check_eof) noexcept
144+
{
145+
if (read_from_device_to_check_eof)
146+
{
147+
try
148+
{
149+
/// If the stream is closed without final last chunk
150+
/// "Unexpected EOF" exception would be thrown
151+
readFromDevice(nullptr, 0);
152+
}
153+
catch (...)
154+
{
155+
return false;
156+
}
157+
}
158+
159+
return _chunk == std::char_traits<char>::eof();
160+
}
161+
162+
140163
int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
141164
{
142165
_chunkBuffer.clear();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <Poco/Net/HTTPChunkedStream.h>
4+
#include <Poco/Net/HTTPClientSession.h>
5+
6+
7+
TEST(HTTPChunkedStreamBuf, IsCompleteHandlesInvalidSocketException)
8+
{
9+
Poco::Net::HTTPClientSession session;
10+
Poco::Net::HTTPChunkedStreamBuf buf(session, std::ios::in);
11+
12+
/// Default-initialized socket throws InvalidSocketException in SocketImpl::receiveBytes,
13+
/// which HTTPChunkedStreamBuf::isComplete should swallow and return false.
14+
bool complete = buf.isComplete(true);
15+
ASSERT_FALSE(complete);
16+
}

tests/queries/0_stateless/02537_distributed_loosing_files_after_exception.reference renamed to tests/queries/0_stateless/02537_distributed_losing_files_after_exception.reference

File renamed without changes.

tests/queries/0_stateless/02537_distributed_loosing_files_after_exception.sql.j2 renamed to tests/queries/0_stateless/02537_distributed_losing_files_after_exception.sql.j2

File renamed without changes.

0 commit comments

Comments
 (0)