fix(extract): treat tar mtime=0 as unset to fix unreadable entries (#4948)

An extracted entry whose tar header mtime is 0 was stored with
mod_time = UNIX_EPOCH, which xl.meta encodes as 0 nanos (= no
mod_time). On read-back the version failed valid() and parsing fell
into the legacy rmp_serde fallback, so every read of the object
returned 500 (invalid type: integer 0, expected an OffsetDateTime).

Treat mtime 0 as unset (tar convention) and fall back to the upload
time. Also fix two test-side issues uncovered behind the 500: the pax
fixture must use a ustar header for its XHeader entry, and the SSE-S3
extract tests must provision RUSTFS_SSE_S3_MASTER_KEY. Re-admit the 19
quarantined tests to the e2e-full merge gate.

Fixes #4842
This commit is contained in:
Zhengchao An
2026-07-17 19:00:31 +08:00
committed by GitHub
parent 8ace340694
commit e279a4f48a
3 changed files with 15 additions and 7 deletions
+4
View File
@@ -6872,10 +6872,14 @@ impl DefaultObjectUsecase {
}
let mut size =
i64::try_from(entry_size).map_err(|_| s3_error!(InvalidArgument, "Archive entry size does not fit into i64"))?;
// mtime 0 means "unset" in tar headers, and xl.meta cannot represent an
// epoch mod_time anyway (0 nanos decodes as no-mod_time, making the version
// unreadable — rustfs#4842), so fall back to the upload time instead.
let archive_entry_mod_time = f
.header()
.mtime()
.ok()
.filter(|&modified_at_secs| modified_at_secs > 0)
.and_then(|modified_at_secs| OffsetDateTime::from_unix_timestamp(modified_at_secs as i64).ok());
let mut metadata = HashMap::new();
let has_explicit_object_lock_retention = object_lock_mode.is_some() || object_lock_retain_until_date.is_some();