2009-04-17 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Fixed segmentation fault when GZipDecoder::decode() returns 0
	byte.
	* src/DownloadCommand.cc
	* src/bitfield.h
	* test/bitfieldTest.cc

	Fixed the bug that causes infinite loop if broken web server
	returns chunked response without last "0" chunk-size marker and
	closes connection.
	* src/DownloadCommand.cc

	Instantiate properly configured HttpDownloadCommand for
	non-resumable downlaods.
	* src/HttpResponseCommand.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-04-17 13:19:17 +00:00
parent d2d4f67bbe
commit 65a358c68b
5 changed files with 52 additions and 9 deletions

View File

@ -1,3 +1,20 @@
2009-04-17 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed segmentation fault when GZipDecoder::decode() returns 0
byte.
* src/DownloadCommand.cc
* src/bitfield.h
* test/bitfieldTest.cc
Fixed the bug that causes infinite loop if broken web server
returns chunked response without last "0" chunk-size marker and
closes connection.
* src/DownloadCommand.cc
Instantiate properly configured HttpDownloadCommand for
non-resumable downlaods.
* src/HttpResponseCommand.cc
2009-04-16 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Rewritten array operation functions.

View File

@ -156,17 +156,14 @@ bool DownloadCommand::executeInternal() {
}
#endif // ENABLE_MESSAGE_DIGEST
segment->updateWrittenLength(bufSizeFinal);
if(bufSizeFinal > 0) {
segment->updateWrittenLength(bufSizeFinal);
}
peerStat->updateDownloadLength(bufSize);
_requestGroup->getSegmentMan()->updateDownloadSpeedFor(peerStat);
if(_requestGroup->getTotalLength() != 0 && bufSize == 0 &&
!socket->wantRead() && !socket->wantWrite()) {
throw DlRetryEx(EX_GOT_EOF);
}
bool segmentComplete = false;
if(_transferEncodingDecoder.isNull() && _contentEncodingDecoder.isNull()) {
if(segment->complete()) {
@ -193,6 +190,11 @@ bool DownloadCommand::executeInternal() {
}
}
if(!segmentComplete && bufSize == 0 &&
!socket->wantRead() && !socket->wantWrite()) {
throw DlRetryEx(EX_GOT_EOF);
}
if(segmentComplete) {
logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid);
#ifdef ENABLE_MESSAGE_DIGEST

View File

@ -68,6 +68,12 @@
namespace aria2 {
static SharedHandle<Decoder> getTransferEncodingDecoder
(const SharedHandle<HttpResponse>& httpResponse);
static SharedHandle<Decoder> getContentEncodingDecoder
(const SharedHandle<HttpResponse>& httpResponse);
HttpResponseCommand::HttpResponseCommand(int32_t cuid,
const RequestHandle& req,
RequestGroup* requestGroup,
@ -147,6 +153,8 @@ bool HttpResponseCommand::executeInternal()
if(req->getMethod() == Request::METHOD_GET &&
(totalLength != 0 ||
!httpResponse->getHttpHeader()->defined(HttpHeader::CONTENT_LENGTH))){
// dctx->knowsTotalLength() == true only when server says the
// size of file is 0 explicitly.
dctx->markTotalLengthIsUnknown();
}
return handleOtherEncoding(httpResponse);
@ -158,8 +166,19 @@ bool HttpResponseCommand::executeInternal()
_requestGroup->validateTotalLength(httpResponse->getEntityLength());
// update last modified time
updateLastModifiedTime(httpResponse->getLastModifiedTime());
e->commands.push_back(createHttpDownloadCommand(httpResponse));
if(_requestGroup->getTotalLength() == 0) {
// Since total length is unknown, the file size in previously
// failed download could be larger than the size this time.
// Also we can't resume in this case too. So truncate the file
// anyway.
_requestGroup->getPieceStorage()->getDiskAdaptor()->truncate(0);
e->commands.push_back
(createHttpDownloadCommand(httpResponse,
getTransferEncodingDecoder(httpResponse),
getContentEncodingDecoder(httpResponse)));
} else {
e->commands.push_back(createHttpDownloadCommand(httpResponse));
}
return true;
}
}
@ -299,11 +318,12 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp
_requestGroup->shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
// In this context, knowsTotalLength() is true only when the file is
// really zero-length.
if(_requestGroup->getDownloadContext()->knowsTotalLength()) {
poolConnection();
return true;
}
e->commands.push_back
(createHttpDownloadCommand(httpResponse,
getTransferEncodingDecoder(httpResponse),

View File

@ -91,6 +91,9 @@ inline size_t countBit32(uint32_t n)
// Counts set bit in bitfield.
inline size_t countSetBit(const unsigned char* bitfield, size_t nbits)
{
if(nbits == 0) {
return 0;
}
size_t count = 0;
size_t size = sizeof(uint32_t);
size_t len = (nbits+7)/8;

View File

@ -45,6 +45,7 @@ void bitfieldTest::testCountSetBit()
CPPUNIT_ASSERT_EQUAL((size_t)37, bitfield::countSetBit(bitfield, 48));
CPPUNIT_ASSERT_EQUAL((size_t)36, bitfield::countSetBit(bitfield, 47));
CPPUNIT_ASSERT_EQUAL((size_t)28, bitfield::countSetBit(bitfield, 32));
CPPUNIT_ASSERT_EQUAL((size_t)0, bitfield::countSetBit(bitfield, 0));
}
void bitfieldTest::testLastByteMask()