Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.

Commit c1fdf3a

Browse files
Jinming-Huvinjiang
authored andcommitted
Fix bug: 416 RangeNotSatisfiable exception is swallowed unintentionally
1 parent d669f5d commit c1fdf3a

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,15 @@ namespace azure { namespace storage {
666666
single_blob_download_threshold = protocol::default_single_block_download_threshold;
667667
}
668668

669+
// We use this variable to track if we are trying to download the whole blob or just a range.
670+
// In the former case, no exception should be thrown if the blob is empty.
671+
// In the latter case, exception should be thrown.
672+
// And the behavior should be consistent no matter we're downloading with multiple or single thread.
673+
bool no_throw_on_empty = false;
674+
669675
if (offset >= std::numeric_limits<utility::size64_t>::max())
670676
{
677+
no_throw_on_empty = true;
671678
if (length == 0)
672679
{
673680
offset = 0;
@@ -690,9 +697,9 @@ namespace azure { namespace storage {
690697
}
691698
catch (storage_exception &e)
692699
{
693-
// For empty blob, swallow the exception and update the attributes.
694-
if (e.result().http_status_code() == web::http::status_codes::RangeNotSatisfiable
695-
&& offset == 0)
700+
// If offset equals to 0 and HTTP status code is 416 RangeNotSatisfiable, then this is an empty blob.
701+
// For empty blob, update the attributes or throw an exception.
702+
if (e.result().http_status_code() == web::http::status_codes::RangeNotSatisfiable && offset == 0 && no_throw_on_empty)
696703
{
697704
return instance->download_attributes_async_impl(condition, options, context, timer_handler->get_cancellation_token(), false, timer_handler);
698705
}

Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,47 @@ SUITE(Blob)
10821082
CHECK(blob.properties().size() == target_length);
10831083
}
10841084

1085+
TEST_FIXTURE(blob_test_base, range_not_satisfiable_exception)
1086+
{
1087+
auto blob_name = get_random_string(20);
1088+
auto blob = m_container.get_block_blob_reference(blob_name);
1089+
blob.upload_text(utility::string_t());
1090+
1091+
auto blob2 = m_container.get_block_blob_reference(blob_name + _XPLATSTR("2"));
1092+
blob2.upload_text(_XPLATSTR("abcd"));
1093+
1094+
azure::storage::blob_request_options options1;
1095+
options1.set_parallelism_factor(1);
1096+
options1.set_use_transactional_crc64(false);
1097+
1098+
azure::storage::blob_request_options options2;
1099+
options2.set_parallelism_factor(2);
1100+
options2.set_use_transactional_crc64(false);
1101+
1102+
azure::storage::blob_request_options options3;
1103+
options3.set_parallelism_factor(1);
1104+
options3.set_use_transactional_crc64(true);
1105+
1106+
for (const auto& option : { options1, options2, options3 }) {
1107+
concurrency::streams::container_buffer<std::vector<uint8_t>> download_buffer;
1108+
1109+
// download whole blob, no exception
1110+
blob.download_to_stream(download_buffer.create_ostream(), azure::storage::access_condition(), option, azure::storage::operation_context());
1111+
1112+
// download range, should throw
1113+
CHECK_THROW(blob.download_range_to_stream(download_buffer.create_ostream(), 0, 100, azure::storage::access_condition(), option, azure::storage::operation_context()), azure::storage::storage_exception);
1114+
1115+
// download range(max, ...), no exception
1116+
blob.download_range_to_stream(download_buffer.create_ostream(), std::numeric_limits<utility::size64_t>::max(), 0, azure::storage::access_condition(), option, azure::storage::operation_context());
1117+
1118+
// download range(3, very large), no exception
1119+
blob2.download_range_to_stream(download_buffer.create_ostream(), 3, 100, azure::storage::access_condition(), option, azure::storage::operation_context());
1120+
1121+
// download range(4, ...), should throw
1122+
CHECK_THROW(blob2.download_range_to_stream(download_buffer.create_ostream(), 4, 100, azure::storage::access_condition(), option, azure::storage::operation_context()), azure::storage::storage_exception);
1123+
}
1124+
}
1125+
10851126
TEST_FIXTURE(blob_test_base, read_blob_with_invalid_if_none_match)
10861127
{
10871128
auto blob_name = get_random_string(20);

0 commit comments

Comments
 (0)