Skip to content

Commit 7416dbf

Browse files
committed
Verifying ContentRange on response from GetObject
removing q transfermanager
1 parent 63ad6e3 commit 7416dbf

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,33 @@ namespace Aws
825825
return rangeStream.str();
826826
}
827827

828+
static bool VerifyContentRange(const Aws::String& requestedRange, const Aws::String& responseContentRange)
829+
{
830+
if (requestedRange.empty() || responseContentRange.empty())
831+
{
832+
return false;
833+
}
834+
835+
if (requestedRange.find("bytes=") != 0)
836+
{
837+
return false;
838+
}
839+
Aws::String requestRange = requestedRange.substr(6);
840+
841+
if (responseContentRange.find("bytes ") != 0)
842+
{
843+
return false;
844+
}
845+
Aws::String responseRange = responseContentRange.substr(6);
846+
size_t slashPos = responseRange.find('/');
847+
if (slashPos != Aws::String::npos)
848+
{
849+
responseRange = responseRange.substr(0, slashPos);
850+
}
851+
852+
return requestRange == responseRange;
853+
}
854+
828855
void TransferManager::DoSinglePartDownload(const std::shared_ptr<TransferHandle>& handle)
829856
{
830857
auto queuedParts = handle->GetQueuedParts();
@@ -1091,7 +1118,6 @@ namespace Aws
10911118
const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context)
10921119
{
10931120
AWS_UNREFERENCED_PARAM(client);
1094-
AWS_UNREFERENCED_PARAM(request);
10951121

10961122
std::shared_ptr<TransferHandleAsyncContext> transferContext =
10971123
std::const_pointer_cast<TransferHandleAsyncContext>(std::static_pointer_cast<const TransferHandleAsyncContext>(context));
@@ -1110,6 +1136,37 @@ namespace Aws
11101136
}
11111137
else
11121138
{
1139+
if (request.RangeHasBeenSet())
1140+
{
1141+
const auto& requestedRange = request.GetRange();
1142+
const auto& responseContentRange = outcome.GetResult().GetContentRange();
1143+
1144+
if (!responseContentRange.empty())
1145+
{
1146+
if (!VerifyContentRange(requestedRange, responseContentRange))
1147+
{
1148+
Aws::Client::AWSError<Aws::S3::S3Errors> error(Aws::S3::S3Errors::INTERNAL_FAILURE,
1149+
"ContentRangeMismatch",
1150+
"ContentRange in response does not match requested range",
1151+
false);
1152+
AWS_LOGSTREAM_ERROR(CLASS_TAG, "Transfer handle [" << handle->GetId()
1153+
<< "] ContentRange mismatch. Requested: [" << requestedRange
1154+
<< "] Received: [" << responseContentRange << "]");
1155+
handle->ChangePartToFailed(partState);
1156+
handle->SetError(error);
1157+
TriggerErrorCallback(handle, error);
1158+
handle->Cancel();
1159+
1160+
if(partState->GetDownloadBuffer())
1161+
{
1162+
m_bufferManager.Release(partState->GetDownloadBuffer());
1163+
partState->SetDownloadBuffer(nullptr);
1164+
}
1165+
return;
1166+
}
1167+
}
1168+
}
1169+
11131170
if(handle->ShouldContinue())
11141171
{
11151172
Aws::IOStream* bufferStream = partState->GetDownloadPartStream();

tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,6 +2328,40 @@ TEST_P(TransferTests, TransferManager_TestRelativePrefix)
23282328
}
23292329
}
23302330

2331+
TEST_P(TransferTests, TransferManager_ContentRangeVerificationTest)
2332+
{
2333+
const Aws::String RandomFileName = Aws::Utils::UUID::RandomUUID();
2334+
Aws::String testFileName = MakeFilePath(RandomFileName.c_str());
2335+
ScopedTestFile testFile(testFileName, MEDIUM_TEST_SIZE, testString);
2336+
2337+
TransferManagerConfiguration transferManagerConfig(m_executor.get());
2338+
transferManagerConfig.s3Client = m_s3Clients[GetParam()];
2339+
auto transferManager = TransferManager::Create(transferManagerConfig);
2340+
2341+
std::shared_ptr<TransferHandle> uploadPtr = transferManager->UploadFile(testFileName, GetTestBucketName(), RandomFileName, "text/plain", Aws::Map<Aws::String, Aws::String>());
2342+
uploadPtr->WaitUntilFinished();
2343+
ASSERT_EQ(TransferStatus::COMPLETED, uploadPtr->GetStatus());
2344+
ASSERT_TRUE(WaitForObjectToPropagate(GetTestBucketName(), RandomFileName.c_str()));
2345+
2346+
auto downloadFileName = MakeDownloadFileName(RandomFileName);
2347+
auto createStreamFn = [=](){
2348+
#ifdef _MSC_VER
2349+
return Aws::New<Aws::FStream>(ALLOCATION_TAG, Aws::Utils::StringUtils::ToWString(downloadFileName.c_str()).c_str(), std::ios_base::out | std::ios_base::in | std::ios_base::binary | std::ios_base::trunc);
2350+
#else
2351+
return Aws::New<Aws::FStream>(ALLOCATION_TAG, downloadFileName.c_str(), std::ios_base::out | std::ios_base::in | std::ios_base::binary | std::ios_base::trunc);
2352+
#endif
2353+
};
2354+
2355+
uint64_t offset = 1024;
2356+
uint64_t partSize = 2048;
2357+
std::shared_ptr<TransferHandle> downloadPtr = transferManager->DownloadFile(GetTestBucketName(), RandomFileName, offset, partSize, createStreamFn);
2358+
2359+
downloadPtr->WaitUntilFinished();
2360+
ASSERT_EQ(TransferStatus::COMPLETED, downloadPtr->GetStatus());
2361+
ASSERT_EQ(partSize, downloadPtr->GetBytesTotalSize());
2362+
ASSERT_EQ(partSize, downloadPtr->GetBytesTransferred());
2363+
}
2364+
23312365
INSTANTIATE_TEST_SUITE_P(Https, TransferTests, testing::Values(TestType::Https));
23322366
INSTANTIATE_TEST_SUITE_P(Http, TransferTests, testing::Values(TestType::Http));
23332367

0 commit comments

Comments
 (0)