fix(deps): move zip to 9.1 (RUSTSEC-2026-0367/0368/0369)
The workspace pin goes from 8 to 9, kigi-tools drops its separate zip 3 pin for the workspace dependency, and office_oxide 0.1.16 follows onto zip 9. zip 9 decodes entry names on demand and can fail; the PPTX reader and the Windows update unpacker now report that error. The zip unpacker gains the two tests the tar path already had.
This commit is contained in:
5 files changed
+91
-66
No files matched your search
@@ -31,11 +31,7 @@ infer = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
image = { workspace = true, features = ["png", "jpeg", "gif", "webp", "bmp", "tiff", "ico"] }
|
||||
pdf_oxide = { workspace = true }
|
||||
# PPTX text extraction (implementations/read_file/pptx.rs). Deliberately NOT
|
||||
# `workspace = true`: the workspace `zip` pin has default features on, which
|
||||
# drag aes/bzip2/lzma/zstd into the shipped pager binary. PPTX entries are
|
||||
# only ever stored or deflated.
|
||||
zip = { version = "3", default-features = false, features = ["deflate-flate2"] }
|
||||
zip = { workspace = true }
|
||||
quick-xml = { workspace = true }
|
||||
indexmap = { workspace = true, features = ["serde"] }
|
||||
minijinja = { version = "2", features = ["custom_syntax"] }
|
||||
|
||||
@@ -31,10 +31,14 @@ pub(crate) fn extract_pptx_text_from_bytes(bytes: &[u8]) -> Result<String, Strin
|
||||
let mut archive = ZipArchive::new(Cursor::new(bytes))
|
||||
.map_err(|e| format!("Failed to open PPTX archive: {e}"))?;
|
||||
|
||||
let names = archive
|
||||
.file_names()
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| format!("Failed to read PPTX entry names: {e}"))?;
|
||||
// Collect slide numbers from `ppt/slides/slideN.xml` entries and sort
|
||||
// numerically so slide ordering matches the presentation.
|
||||
let mut slide_numbers: Vec<u32> = archive
|
||||
.file_names()
|
||||
let mut slide_numbers: Vec<u32> = names
|
||||
.iter()
|
||||
.filter_map(|name| {
|
||||
name.strip_prefix("ppt/slides/slide")?
|
||||
.strip_suffix(".xml")?
|
||||
|
||||
@@ -1108,7 +1108,7 @@ fn extract_kigi_binary_blocking(archive: &Path, dest_tmp: &Path) -> Result<()> {
|
||||
for i in 0..zip.len() {
|
||||
let mut entry = zip.by_index(i)?;
|
||||
let base_name = entry
|
||||
.name()
|
||||
.name()?
|
||||
.rsplit(['/', '\\'])
|
||||
.next()
|
||||
.unwrap_or_default()
|
||||
@@ -2798,6 +2798,52 @@ mod tests {
|
||||
assert!(extract_kigi_binary(&archive, &out).await.is_err());
|
||||
}
|
||||
|
||||
// Archive extraction (Windows: zip)
|
||||
|
||||
#[cfg(windows)]
|
||||
fn make_zip(entries: &[(&str, &[u8])]) -> Vec<u8> {
|
||||
use std::io::Write as _;
|
||||
let mut writer = zip::ZipWriter::new(std::io::Cursor::new(Vec::new()));
|
||||
for (name, data) in entries {
|
||||
writer
|
||||
.start_file(*name, zip::write::SimpleFileOptions::default())
|
||||
.unwrap();
|
||||
writer.write_all(data).unwrap();
|
||||
}
|
||||
writer.finish().unwrap().into_inner()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tokio::test]
|
||||
async fn test_extract_kigi_binary_finds_kigi_exe_entry() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let archive = dir.path().join("kigi-0.1.0-test.zip");
|
||||
std::fs::write(
|
||||
&archive,
|
||||
make_zip(&[("LICENSE", b"license text"), ("kigi.exe", b"MZ binary")]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let out = dir.path().join("kigi-extracted");
|
||||
extract_kigi_binary(&archive, &out).await.unwrap();
|
||||
assert_eq!(std::fs::read(&out).unwrap(), b"MZ binary");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tokio::test]
|
||||
async fn test_extract_kigi_binary_missing_exe_errors() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let archive = dir.path().join("kigi-0.1.0-test.zip");
|
||||
std::fs::write(&archive, make_zip(&[("LICENSE", b"license only")])).unwrap();
|
||||
|
||||
let out = dir.path().join("kigi-extracted");
|
||||
let err = extract_kigi_binary(&archive, &out).await.unwrap_err();
|
||||
assert!(
|
||||
format!("{err}").contains("no 'kigi.exe' binary"),
|
||||
"err: {err}"
|
||||
);
|
||||
}
|
||||
|
||||
// UpdateStatus serialization (camelCase contract for --json clients)
|
||||
|
||||
fn make_status() -> UpdateStatus {
|
||||
|
||||
Reference in new issue
Block a user