diff options
author | Tim Burke <tim.burke@gmail.com> | 2020-09-28 09:34:58 -0700 |
---|---|---|
committer | Tim Burke <tim.burke@gmail.com> | 2020-09-28 13:56:00 -0700 |
commit | 9a0bac4ceb15ba0e6b24d0cd021972341e97e60b (patch) | |
tree | 3a57a0dc7234b7ad96d91f2e50eb82d6e9f6d58b /swift/common/request_helpers.py | |
parent | 004052dc65406e012822312f267d8374e760d34e (diff) | |
download | swift-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.py | 24 |
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 |