(stream: BinaryIO, *, declared_size: int, label: str)
| 260 | |
| 261 | |
| 262 | def hash_stream(stream: BinaryIO, *, declared_size: int, label: str) -> tuple[str, int]: |
| 263 | if declared_size < 0 or declared_size > MAX_MEMBER_BYTES: |
| 264 | raise ContractError(f"archive member has an invalid size: {label}") |
| 265 | digest = hashlib.sha256() |
| 266 | total = 0 |
| 267 | while True: |
| 268 | chunk = stream.read(min(1024 * 1024, declared_size - total + 1)) |
| 269 | if not chunk: |
| 270 | break |
| 271 | total += len(chunk) |
| 272 | if total > declared_size or total > MAX_MEMBER_BYTES: |
| 273 | raise ContractError(f"archive member exceeded its declared size: {label}") |
| 274 | digest.update(chunk) |
| 275 | if total != declared_size: |
| 276 | raise ContractError(f"archive member size does not match metadata: {label}") |
| 277 | return digest.hexdigest(), total |
| 278 | |
| 279 | |
| 280 | def verify_tar( |
no test coverage detected