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)]