summaryrefslogtreecommitdiff
path: root/swift/common/request_helpers.py
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2020-09-28 09:34:58 -0700
committerTim Burke <tim.burke@gmail.com>2020-09-28 13:56:00 -0700
commit9a0bac4ceb15ba0e6b24d0cd021972341e97e60b (patch)
tree3a57a0dc7234b7ad96d91f2e50eb82d6e9f6d58b /swift/common/request_helpers.py
parent004052dc65406e012822312f267d8374e760d34e (diff)
downloadswift-9a0bac4ceb15ba0e6b24d0cd021972341e97e60b.tar.gz
Fail short reads in SegmentedIterable
...and check for it *before* doing the MD5 check. We see this happen ocassionally, but as best I can tell, it's always due to a ChunkReadTimeout popping in the proxy that it can't recover from. Change-Id: If238725bbec4fc3f6c8d000599c735a7c4972f7d
Diffstat (limited to 'swift/common/request_helpers.py')
-rw-r--r--swift/common/request_helpers.py24
1 files changed, 18 insertions, 6 deletions
diff --git a/swift/common/request_helpers.py b/swift/common/request_helpers.py
index 000752e52..f79b47f9c 100644
--- a/swift/common/request_helpers.py
+++ b/swift/common/request_helpers.py
@@ -597,6 +597,7 @@ class SegmentedIterable(object):
else:
self.current_resp = seg_resp
+ resp_len = 0
seg_hash = None
if seg_resp.etag and not seg_req.headers.get('Range'):
# Only calculate the MD5 if it we can use it to validate
@@ -609,15 +610,26 @@ class SegmentedIterable(object):
for chunk in itertools.chain.from_iterable(document_iters):
if seg_hash:
seg_hash.update(chunk)
+ resp_len += len(chunk)
yield (seg_req.path, chunk)
close_if_possible(seg_resp.app_iter)
- if seg_hash and seg_hash.hexdigest() != seg_resp.etag:
- raise SegmentError(
- "Bad MD5 checksum in %(name)s for %(seg)s: headers had"
- " %(etag)s, but object MD5 was actually %(actual)s" %
- {'seg': seg_req.path, 'etag': seg_resp.etag,
- 'name': self.name, 'actual': seg_hash.hexdigest()})
+ if seg_hash:
+ if resp_len != seg_resp.content_length:
+ raise SegmentError(
+ "Bad response length for %(seg)s as part of %(name)s: "
+ "headers had %(from_headers)s, but response length "
+ "was actually %(actual)s" %
+ {'seg': seg_req.path,
+ 'from_headers': seg_resp.content_length,
+ 'name': self.name, 'actual': resp_len})
+ if seg_hash.hexdigest() != seg_resp.etag:
+ raise SegmentError(
+ "Bad MD5 checksum for %(seg)s as part of %(name)s: "
+ "headers had %(etag)s, but object MD5 was actually "
+ "%(actual)s" %
+ {'seg': seg_req.path, 'etag': seg_resp.etag,
+ 'name': self.name, 'actual': seg_hash.hexdigest()})
def _byte_counting_iter(self):
# Checks that we give the client the right number of bytes. Raises