don't panic on missing checksum (fix #1387) (#1389)

fix https://git.deuxfleurs.fr/Deuxfleurs/garage/issues/1387

Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/1389
Reviewed-by: Alex <lx@deuxfleurs.fr>
Co-authored-by: trinity-1686a <trinity-1686a@noreply.localhost>
Co-committed-by: trinity-1686a <trinity-1686a@noreply.localhost>
This commit is contained in:
trinity-1686a
2026-03-17 18:16:37 +00:00
committed by Alex
parent 9848ec7f4e
commit 60244b60dd
4 changed files with 45 additions and 16 deletions
+39 -10
View File
@@ -11,6 +11,7 @@ use http::{HeaderMap, HeaderName, HeaderValue};
use garage_util::data::*; use garage_util::data::*;
use super::*; use super::*;
use crate::common_error::CommonError;
pub use garage_model::s3::object_table::{ChecksumAlgorithm, ChecksumValue}; pub use garage_model::s3::object_table::{ChecksumAlgorithm, ChecksumValue};
@@ -201,7 +202,7 @@ impl Checksums {
} }
if let Some(extra) = expected.extra { if let Some(extra) = expected.extra {
let algo = extra.algorithm(); let algo = extra.algorithm();
let calculated = self.extract(Some(algo)); let calculated = self.extract(Some(algo))?;
if calculated != Some(extra) { if calculated != Some(extra) {
return Err(Error::InvalidDigest(format!( return Err(Error::InvalidDigest(format!(
"Failed to validate checksum for algorithm {:?}: calculated {:?}, expected {:?}", "Failed to validate checksum for algorithm {:?}: calculated {:?}, expected {:?}",
@@ -212,17 +213,45 @@ impl Checksums {
Ok(()) Ok(())
} }
pub fn extract(&self, algo: Option<ChecksumAlgorithm>) -> Option<ChecksumValue> { pub fn extract(&self, algo: Option<ChecksumAlgorithm>) -> Result<Option<ChecksumValue>, Error> {
match algo { Ok(match algo {
None => None, None => None,
Some(ChecksumAlgorithm::Crc32) => Some(ChecksumValue::Crc32(self.crc32.unwrap())), Some(ChecksumAlgorithm::Crc32) => {
Some(ChecksumAlgorithm::Crc32c) => Some(ChecksumValue::Crc32c(self.crc32c.unwrap())), Some(ChecksumValue::Crc32(self.crc32.ok_or_else(|| {
Some(ChecksumAlgorithm::Crc64Nvme) => { CommonError::BadRequest(
Some(ChecksumValue::Crc64Nvme(self.crc64nvme.unwrap())) "Requested checksum verification without providing checksum".to_string(),
)
})?))
} }
Some(ChecksumAlgorithm::Sha1) => Some(ChecksumValue::Sha1(self.sha1.unwrap())), Some(ChecksumAlgorithm::Crc32c) => {
Some(ChecksumAlgorithm::Sha256) => Some(ChecksumValue::Sha256(self.sha256.unwrap())), Some(ChecksumValue::Crc32c(self.crc32c.ok_or_else(|| {
} CommonError::BadRequest(
"Requested checksum verification without providing checksum".to_string(),
)
})?))
}
Some(ChecksumAlgorithm::Crc64Nvme) => Some(ChecksumValue::Crc64Nvme(
self.crc64nvme.ok_or_else(|| {
CommonError::BadRequest(
"Requested checksum verification without providing checksum".to_string(),
)
})?,
)),
Some(ChecksumAlgorithm::Sha1) => {
Some(ChecksumValue::Sha1(self.sha1.ok_or_else(|| {
CommonError::BadRequest(
"Requested checksum verification without providing checksum".to_string(),
)
})?))
}
Some(ChecksumAlgorithm::Sha256) => {
Some(ChecksumValue::Sha256(self.sha256.ok_or_else(|| {
CommonError::BadRequest(
"Requested checksum verification without providing checksum".to_string(),
)
})?))
}
})
} }
} }
+1 -1
View File
@@ -706,7 +706,7 @@ pub async fn handle_upload_part_copy(
let checksums = checksummer.finalize(); let checksums = checksummer.finalize();
let etag = dest_encryption.etag_from_md5(&checksums.md5); let etag = dest_encryption.etag_from_md5(&checksums.md5);
let checksum = checksums.extract(dest_object_checksum_algorithm.map(|(algo, _)| algo)); let checksum = checksums.extract(dest_object_checksum_algorithm.map(|(algo, _)| algo))?;
// Put the part's ETag in the Versiontable // Put the part's ETag in the Versiontable
dest_mpu.parts.put( dest_mpu.parts.put(
+1 -1
View File
@@ -225,7 +225,7 @@ pub async fn handle_put_part(
MpuPart { MpuPart {
version: version_uuid, version: version_uuid,
etag: Some(etag.clone()), etag: Some(etag.clone()),
checksum: checksums.extract(checksum_algorithm.map(|(algo, _)| algo)), checksum: checksums.extract(checksum_algorithm.map(|(algo, _)| algo))?,
size: Some(total_size), size: Some(total_size),
}, },
); );
+4 -4
View File
@@ -178,7 +178,7 @@ pub(crate) async fn save_stream<S: Stream<Item = Result<Bytes, Error>> + Unpin>(
checksums.verify(&expected)?; checksums.verify(&expected)?;
} }
ChecksumMode::Calculate(algo) => { ChecksumMode::Calculate(algo) => {
meta.checksum = checksums.extract(algo); meta.checksum = checksums.extract(algo)?;
} }
ChecksumMode::VerifyFrom { ChecksumMode::VerifyFrom {
checksummer, checksummer,
@@ -189,7 +189,7 @@ pub(crate) async fn save_stream<S: Stream<Item = Result<Bytes, Error>> + Unpin>(
.await .await
.ok_or_internal_error("checksum calculation")??; .ok_or_internal_error("checksum calculation")??;
if let Some(algo) = trailer_algo { if let Some(algo) = trailer_algo {
meta.checksum = checksums.extract(Some(algo)); meta.checksum = checksums.extract(Some(algo))?;
} }
} }
} }
@@ -280,7 +280,7 @@ pub(crate) async fn save_stream<S: Stream<Item = Result<Bytes, Error>> + Unpin>(
checksums.verify(&expected)?; checksums.verify(&expected)?;
} }
ChecksumMode::Calculate(algo) => { ChecksumMode::Calculate(algo) => {
meta.checksum = checksums.extract(algo); meta.checksum = checksums.extract(algo)?;
} }
ChecksumMode::VerifyFrom { ChecksumMode::VerifyFrom {
checksummer, checksummer,
@@ -290,7 +290,7 @@ pub(crate) async fn save_stream<S: Stream<Item = Result<Bytes, Error>> + Unpin>(
.await .await
.ok_or_internal_error("checksum calculation")??; .ok_or_internal_error("checksum calculation")??;
if let Some(algo) = trailer_algo { if let Some(algo) = trailer_algo {
meta.checksum = checksums.extract(Some(algo)); meta.checksum = checksums.extract(Some(algo))?;
} }
} }
} }