Skip to content

Commit fd26f88

Browse files
authored
Merge pull request #2024 from sydduckworth/blank-checksums-invalid
Fixed empty checksum validation
2 parents f97c7a6 + aedf3ae commit fd26f88

3 files changed

Lines changed: 29 additions & 10 deletions

File tree

asdf/_block/reader.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,14 @@ def data(self):
7676
data = self._data()
7777
else:
7878
data = self._data
79+
7980
if self.validate_checksum:
80-
checksum = bio.calculate_block_checksum(data)
81-
if not self._header["flags"] & constants.BLOCK_FLAG_STREAMED and checksum != self._header["checksum"]:
82-
msg = f"Block at {self.offset} does not match given checksum"
83-
raise ValueError(msg)
81+
if any(b != 0 for b in self._header["checksum"]):
82+
# Only validate if the header actually contains a checksum
83+
checksum = bio.calculate_block_checksum(data)
84+
if not self._header["flags"] & constants.BLOCK_FLAG_STREAMED and checksum != self._header["checksum"]:
85+
msg = f"Block at {self.offset} does not match given checksum"
86+
raise ValueError(msg)
8487
# only validate data the first time it's read
8588
self.validate_checksum = False
8689
return data

asdf/_tests/_block/test_reader.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,22 +175,37 @@ def test_closed_file(tmp_path):
175175
blk.load()
176176

177177

178-
@pytest.mark.parametrize("validate_checksums", [True, False])
179-
def test_bad_checksum(validate_checksums):
180-
buff = io.BytesIO(
178+
def empty_header(checksum):
179+
"""Return a header with all fields other than checksum set to zero."""
180+
181+
return io.BytesIO(
181182
constants.BLOCK_MAGIC
182183
+ b"\x000" # header size = 2
183184
+ b"\0\0\0\0" # flags = 4
184185
+ b"\0\0\0\0" # compression = 4
185186
+ b"\0\0\0\0\0\0\0\0" # allocated size = 8
186187
+ b"\0\0\0\0\0\0\0\0" # used size = 8
187188
+ b"\0\0\0\0\0\0\0\0" # data size = 8
188-
+ b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" # invalid checksum = 16
189+
+ checksum # checksum = 16
189190
)
190191

192+
193+
@pytest.mark.parametrize("validate_checksums", [True, False])
194+
def test_missing_checksum(validate_checksums):
195+
buff = empty_header(b"\0" * 16)
196+
with generic_io.get_file(buff, mode="r") as fd:
197+
# All-zero checksum should always be allowed
198+
read_blocks(fd, lazy_load=False, validate_checksums=validate_checksums)[0].data
199+
200+
201+
@pytest.mark.parametrize("validate_checksums", [True, False])
202+
def test_bad_checksum(validate_checksums):
203+
buff = empty_header(b"\1" + b"\0" * 15)
191204
with generic_io.get_file(buff, mode="r") as fd:
205+
block = read_blocks(fd, lazy_load=False, validate_checksums=validate_checksums)[0]
192206
if validate_checksums:
207+
# Invalid checksum should raise an exception if `validate_checksums=True`
193208
with pytest.raises(ValueError, match=r".* does not match given checksum"):
194-
read_blocks(fd, lazy_load=False, validate_checksums=validate_checksums)[0].data
209+
_ = block.data
195210
else:
196-
read_blocks(fd, lazy_load=False, validate_checksums=validate_checksums)[0].data
211+
_ = block.data

changes/2024.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed bug in which empty/all-zero block checksums were treated as invalid when ``validate_headers`` is enabled.

0 commit comments

Comments
 (0)