I did an attempt at a bump, and also sent it upstream:
https://github.com/PyO3/maturin/pull/3349

Also attached as a patch, against the latest commit on the maturin main branch.

//Alex

Den tors 29 okt. 2026 kl 12:20 skrev Colin Watson <[email protected]>:
>
> On Wed, Oct 28, 2026 at 09:00:06PM +0100, Alexander Kjäll wrote:
> >We needed to do a fast bump of zip to version 9, to handle a bunch of CVE's.
> >
> >Please bump this package to use zip 9 instead of zip 5.
>
> When I tried this (using `cargo add [email protected]` followed by `cargo test`
> in the upstream repository, for testing convenience), I got:
>
> error[E0107]: struct takes 2 lifetime arguments but 1 lifetime argument was 
> supplied
>    --> src/compression.rs:97:58
>     |
> 97 |     pub(crate) fn get_file_options(&self) -> 
> zip::write::FileOptions<'static, ()> {
>     |                                                          ^^^^^^^^^^^ 
> ------- supplied 1 lifetime argument
>     |                                                          |
>     |                                                          expected 2 
> lifetime arguments
>     |
> note: struct defined here, with 2 lifetime parameters: `'k`, `'n`
>    --> 
> /home/cjwatson/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zip-9.1.3/src/write/options.rs:53:12
>     |
> 53 | pub struct FileOptions<'k, 'n, T: sealed::FileOptionExtension> {
>     |            ^^^^^^^^^^^ --  --
> help: add missing lifetime argument
>     |
> 97 |     pub(crate) fn get_file_options(&self) -> 
> zip::write::FileOptions<'static, 'static, ()> {
>     |                                                                         
>     +++++++++
>
> For more information about this error, try `rustc --explain E0107`.
>
>
> OK, so I did that.  Then I get this mess:
>
> error[E0599]: the method `to_string` exists for enum `Result<Cow<'_, str>, 
> ZipError>`, but its trait bounds were not satisfied
>     --> tests/common/integration.rs:568:37
>      |
> 568 |         if !seen.insert(file.name().to_string()) {
>      |                                     ^^^^^^^^^ method cannot be called 
> on `Result<Cow<'_, str>, ZipError>` due to unsatisfied trait bounds
>      |
>     ::: /usr/src/rustc-1.97.1/library/core/src/result.rs:557:1
>      |
> 557 | pub enum Result<T, E> {
>      | --------------------- doesn't satisfy `Result<Cow<'_, str>, ZipError>: 
> ToString` or `Result<Cow<'_, str>, ZipError>: std::fmt::Display`
>      |
>      = note: the following trait bounds were not satisfied:
>              `Result<Cow<'_, str>, ZipError>: std::fmt::Display`
>              which is required by `Result<Cow<'_, str>, ZipError>: ToString`
>
> error[E0277]: `Result<Cow<'_, str>, ZipError>` doesn't implement 
> `std::fmt::Display`
>     --> tests/common/integration.rs:569:41
>      |
> 569 |             bail!("Duplicate file: {}", file.name());
>      |                                    --   ^^^^^^^^^^^ `Result<Cow<'_, 
> str>, ZipError>` cannot be formatted with the default formatter
>      |                                    |
>      |                                    required by this formatting 
> parameter
>      |
>      = help: the trait `std::fmt::Display` is not implemented for 
> `Result<Cow<'_, str>, ZipError>`
>      = note: in format strings you may be able to use `{:?}` (or {:#?} for 
> pretty-print) instead
>      = note: this error originates in the macro 
> `$crate::__export::format_args` which comes from the expansion of the macro 
> `bail` (in Nightly builds, run with -Z macro-backtrace for more info)
>
> error[E0631]: type mismatch in closure arguments
>     --> tests/common/other.rs:387:17
>      |
> 381 |     let drop_platform_specific_files = |file: &&str| -> bool {
>      |                                        --------------------- found 
> signature defined here
> ...
> 387 |         .filter(drop_platform_specific_files)
>      |          ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected due to this
>      |          |
>      |          required by a bound introduced by this call
>      |
>      = note: expected closure signature `for<'a> fn(&'a Result<Cow<'_, str>, 
> ZipError>) -> _`
>                 found closure signature `fn(&&str) -> _`
> note: required by a bound in `filter`
>     --> /usr/src/rustc-1.97.1/library/core/src/iter/traits/iterator.rs:955:34
>      |
> 952 |     fn filter<P>(self, predicate: P) -> Filter<Self, P>
>      |        ------ required by a bound in this associated function
> ...
> 955 |         P: FnMut(&Self::Item) -> bool,
>      |                                  ^^^^ required by this bound in 
> `Iterator::filter`
> help: consider wrapping the function in a closure
>      |
> 387 |         .filter(|arg0: &Result<Cow<'_, str>, ZipError>| 
> drop_platform_specific_files(/* &&str */))
>      |                 +++++++++++++++++++++++++++++++++++++++                
>              +++++++++++++
>
> error[E0599]: the method `map` exists for struct `Filter<impl Iterator<Item = 
> Result<Cow<'_, str>, ZipError>>, {closure@tests/common/other.rs:381:40: 
> 381:61}>`, but its trait bounds were not satisfied
>     --> tests/common/other.rs:388:10
>      |
> 381 |       let drop_platform_specific_files = |file: &&str| -> bool {
>      |                                          --------------------- doesn't 
> satisfy `<_ as FnOnce<(&Result<Cow<'_, str>, ZipError>,)>>::Output = bool`
> ...
> 385 |       Ok(wheel
>      |  ________-
> 386 | |         .file_names()
> 387 | |         .filter(drop_platform_specific_files)
> 388 | |         .map(str::to_owned)
>      | |         -^^^ method cannot be called due to unsatisfied trait bounds
>      | |_________|
>      |
>      |
>     ::: /usr/src/rustc-1.97.1/library/core/src/iter/adapters/filter.rs:21:1
>      |
>   21 |   pub struct Filter<I, P> {
>      |   ----------------------- doesn't satisfy `_: Iterator`
>      |
>      = note: the following trait bounds were not satisfied:
>              `<{closure@tests/common/other.rs:381:40: 381:61} as 
> FnOnce<(&Result<Cow<'_, str>, ZipError>,)>>::Output = bool`
>              which is required by `Filter<impl Iterator<Item = Result<Cow<'_, 
> str>, ZipError>>, {closure@tests/common/other.rs:381:40: 381:61}>: Iterator`
>              `Filter<impl Iterator<Item = Result<Cow<'_, str>, ZipError>>, 
> {closure@tests/common/other.rs:381:40: 381:61}>: Iterator`
>              which is required by `&mut Filter<impl Iterator<Item = 
> Result<Cow<'_, str>, ZipError>>, {closure@tests/common/other.rs:381:40: 
> 381:61}>: Iterator`
>
> error[E0599]: no method named `contains` found for reference `&Result<Cow<'_, 
> str>, ZipError>` in the current scope
>     --> tests/common/other.rs:398:23
>      |
> 398 |         .filter(|f| f.contains(".dist-info/sboms/"))
>      |                       ^^^^^^^^ method not found in `&Result<Cow<'_, 
> str>, ZipError>`
>      |
>      = help: items from traits can only be used if the trait is in scope
> help: trait `Seq` which provides `contains` is implemented but not in scope; 
> perhaps you want to import it
>      |
>    1 + use chumsky::container::Seq;
>      |
>
> error[E0599]: the method `to_string` exists for enum `Result<Cow<'_, str>, 
> ZipError>`, but its trait bounds were not satisfied
>     --> tests/common/other.rs:399:20
>      |
> 399 |         .map(|f| f.to_string())
>      |                    ^^^^^^^^^ method cannot be called on 
> `Result<Cow<'_, str>, ZipError>` due to unsatisfied trait bounds
>      |
>     ::: /usr/src/rustc-1.97.1/library/core/src/result.rs:557:1
>      |
> 557 | pub enum Result<T, E> {
>      | --------------------- doesn't satisfy `Result<Cow<'_, str>, ZipError>: 
> ToString` or `Result<Cow<'_, str>, ZipError>: std::fmt::Display`
>      |
>      = note: the following trait bounds were not satisfied:
>              `Result<Cow<'_, str>, ZipError>: std::fmt::Display`
>              which is required by `Result<Cow<'_, str>, ZipError>: ToString`
>
> error[E0599]: no method named `ends_with` found for reference 
> `&Result<Cow<'_, str>, ZipError>` in the current scope
>     --> tests/common/other.rs:671:37
>      |
> 671 |                 .filter(|name| name.ends_with(".so"))
>      |                                     ^^^^^^^^^ method not found in 
> `&Result<Cow<'_, str>, ZipError>`
>
> error[E0369]: binary operation `==` cannot be applied to type 
> `Vec<Result<Cow<'_, str>, ZipError>>`
>     --> tests/common/other.rs:673:13
>      |
> 673 | /             assert_eq!(
> 674 | |                 extensions,
> 675 | |                 [format!(
> 676 | |                     
> "pyo3_abi3_and_abi3t/pyo3_abi3_and_abi3t{expected_suffix}"
> 677 | |                 )]
> 678 | |             );
>      | |             ^
>      | |             |
>      | |_____________Vec<Result<Cow<'_, str>, ZipError>>
>      |               [std::string::String; 1]
>      |
> note: `Result<Cow<'_, str>, ZipError>` does not implement 
> `PartialEq<std::string::String>`
>     --> /usr/src/rustc-1.97.1/library/core/src/result.rs:557:1
>      |
> 557 | pub enum Result<T, E> {
>      | ^^^^^^^^^^^^^^^^^^^^^ `Result<Cow<'_, str>, ZipError>` is defined in 
> another crate
>      = note: this error originates in the macro `$crate::assert_eq` which 
> comes from the expansion of the macro `assert_eq` (in Nightly builds, run 
> with -Z macro-backtrace for more info)
>
> error[E0599]: no method named `starts_with` found for reference 
> `&Result<Cow<'_, str>, ZipError>` in the current scope
>     --> tests/common/other.rs:803:29
>      |
> 803 |         .filter(|name| name.starts_with("bin_with_python_module/"))
>      |                             ^^^^^^^^^^^ method not found in 
> `&Result<Cow<'_, str>, ZipError>`
>
> error[E0369]: binary operation `==` cannot be applied to type 
> `Vec<Result<Cow<'_, str>, ZipError>>`
>     --> tests/common/other.rs:812:5
>      |
> 812 |     assert_eq!(package_files, expected);
>      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>      |     |
>      |     Vec<Result<Cow<'_, str>, ZipError>>
>      |     Vec<&str>
>      |
> note: `Result<Cow<'_, str>, ZipError>` does not implement `PartialEq<&str>`
>     --> /usr/src/rustc-1.97.1/library/core/src/result.rs:557:1
>      |
> 557 | pub enum Result<T, E> {
>      | ^^^^^^^^^^^^^^^^^^^^^ `Result<Cow<'_, str>, ZipError>` is defined in 
> another crate
>      = note: this error originates in the macro `$crate::assert_eq` which 
> comes from the expansion of the macro `assert_eq` (in Nightly builds, run 
> with -Z macro-backtrace for more info)
>
> Some errors have detailed explanations: E0277, E0369, E0599, E0631.
> For more information about an error, try `rustc --explain E0277`.
>
>
> This is beyond me.  Help?
>
> --
> Colin Watson (he/him)                              [[email protected]]
diff --git c/Cargo.toml i/Cargo.toml
index 5d7eb7f7..1587e6cb 100644
--- c/Cargo.toml
+++ i/Cargo.toml
@@ -58,7 +58,7 @@ tar = "0.4.46"
 tempfile = "3.2.0"
 toml = "1.1.2"
 toml_edit = "0.25.0"
-zip = { version = "8.1.0", default-features = false, features = [
+zip = { version = "9.1.3", default-features = false, features = [
     "bzip2",
     "deflate",
     "time",
diff --git c/src/compression.rs i/src/compression.rs
index 9253d20e..5251d33e 100644
--- c/src/compression.rs
+++ i/src/compression.rs
@@ -94,7 +94,7 @@ impl CompressionOptions {
         }
     }

-    pub(crate) fn get_file_options(&self) -> zip::write::FileOptions<'static, ()> {
+    pub(crate) fn get_file_options(&self) -> zip::write::SimpleFileOptions {
         let method = if cfg!(feature = "faster-tests") {
             // Unlike users which can use the develop subcommand, the tests have to go through
             // packing a zip which pip than has to unpack. This makes this 2-3 times faster
diff --git c/tests/common/integration.rs i/tests/common/integration.rs
index 000d89e8..8e1d47e9 100644
--- c/tests/common/integration.rs
+++ i/tests/common/integration.rs
@@ -565,8 +565,9 @@ fn check_for_duplicates(wheel: &Path) -> Result<()> {
     let mut reader = File::open(wheel)?;
     // We have to use this API since `ZipArchive` deduplicates names.
     while let Some(file) = zip::read::read_zipfile_from_stream(&mut reader)? {
-        if !seen.insert(file.name().to_string()) {
-            bail!("Duplicate file: {}", file.name());
+        let name = file.name()?.into_owned();
+        if !seen.insert(name.clone()) {
+            bail!("Duplicate file: {name}");
         }
     }
     Ok(())
diff --git c/tests/common/other.rs i/tests/common/other.rs
index a8761427..a5cfc9ee 100644
--- c/tests/common/other.rs
+++ i/tests/common/other.rs
@@ -378,14 +378,16 @@ pub fn check_wheel_files(

 pub fn wheel_files(package: impl AsRef<Path>, unique_name: &str) -> Result<BTreeSet<String>> {
     let wheel = build_wheel_files(package, unique_name)?;
-    let drop_platform_specific_files = |file: &&str| -> bool {
+    let drop_platform_specific_files = |file: &str| -> bool {
         !matches!(Path::new(file).extension(), Some(ext) if ext == "pyc" || ext == "pyd" || ext == "so" || ext == "pdb" || ext == "dwp")
             && !file.contains(".dSYM/")
     };
     Ok(wheel
         .file_names()
-        .filter(drop_platform_specific_files)
-        .map(str::to_owned)
+        .collect::<Result<Vec<_>, _>>()?
+        .into_iter()
+        .filter(|file| drop_platform_specific_files(file))
+        .map(|file| file.into_owned())
         .collect::<BTreeSet<_>>())
 }

@@ -395,8 +397,10 @@ pub fn check_wheel_files_with_sbom(package: impl AsRef<Path>, unique_name: &str)

     let sbom_files: Vec<String> = wheel
         .file_names()
+        .collect::<Result<Vec<_>, _>>()?
+        .into_iter()
         .filter(|f| f.contains(".dist-info/sboms/"))
-        .map(|f| f.to_string())
+        .map(|f| f.into_owned())
         .collect();
     assert!(
         !sbom_files.is_empty(),
@@ -668,6 +672,8 @@ pub fn combined_stable_abi_wheel_selection(unique_name: &str, features: &[&str])
             let archive = ZipArchive::new(File::open(&wheel.path)?)?;
             let extensions: Vec<_> = archive
                 .file_names()
+                .collect::<Result<Vec<_>, _>>()?
+                .into_iter()
                 .filter(|name| name.ends_with(".so"))
                 .collect();
             assert_eq!(
@@ -800,6 +806,8 @@ pub fn test_target_dir_in_python_package() -> Result<()> {
     )?;
     let package_files: Vec<_> = wheel
         .file_names()
+        .collect::<Result<Vec<_>, _>>()?
+        .into_iter()
         .filter(|name| name.starts_with("bin_with_python_module/"))
         .collect();
     #[allow(unused_mut)]

Reply via email to