From 14ce65c6a1a87fa8f8848e7e6cc1a17f67b8c97d Mon Sep 17 00:00:00 2001 From: Elina Date: Tue, 3 Feb 2026 15:34:50 +0800 Subject: [PATCH 1/5] Remove mention of rustls-pemfile from docs This is not present in the README either and the link in lib.rs leads to a crate belonging to a repository that has already been archived. Linking to `rustls-pemfile` after https://github.com/rustls/pemfile/issues/61 feels incorrect --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7d50fff..2b3a18d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,7 @@ //! This crate provides types for representing X.509 certificates, keys and other types as //! commonly used in the rustls ecosystem. It is intended to be used by crates that need to work //! with such X.509 types, such as [rustls](https://crates.io/crates/rustls), -//! [rustls-webpki](https://crates.io/crates/rustls-webpki), -//! [rustls-pemfile](https://crates.io/crates/rustls-pemfile), and others. +//! [rustls-webpki](https://crates.io/crates/rustls-webpki), and others. //! //! Some of these crates used to define their own trivial wrappers around DER-encoded bytes. //! However, in order to avoid inconvenient dependency edges, these were all disconnected. By From 422d8cf008e8fc0697144fc3ad8ba5282dde7567 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Wed, 4 Mar 2026 09:16:04 +0000 Subject: [PATCH 2/5] Update ECH reference to RFC 9849 --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2b3a18d..5284cd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -786,7 +786,7 @@ impl SubjectPublicKeyInfoDer<'_> { } /// A TLS-encoded Encrypted Client Hello (ECH) configuration list (`ECHConfigList`); as specified in -/// [draft-ietf-tls-esni-18 §4](https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-4) +/// [RFC 9849 §4](https://datatracker.ietf.org/doc/html/rfc9849#section-4) #[derive(Clone, Eq, Hash, PartialEq)] pub struct EchConfigListBytes<'a>(BytesInner<'a>); From b796d3dc77b22ff820eae950a45cbc62e9203ec0 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 11 Apr 2026 01:03:10 +0200 Subject: [PATCH 3/5] pem: error for sections that are too large --- src/pem.rs | 9 +++++++++ tests/pem.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/pem.rs b/src/pem.rs index 3bee401..984e6d7 100644 --- a/src/pem.rs +++ b/src/pem.rs @@ -331,11 +331,16 @@ fn read( if section.is_some() { b64buf.extend(line); + if b64buf.len() > MAX_PEM_SECTION_SIZE { + return Err(Error::SectionTooLarge); + } } Ok(ControlFlow::Continue(())) } +const MAX_PEM_SECTION_SIZE: usize = 64 * 1024 * 1024; + enum SectionLabel { Known(SectionKind), Unknown(Vec), @@ -493,6 +498,9 @@ pub enum Error { /// No items found of desired type NoItemsFound, + + /// PEM section exceeds maximum allowed size of 64 MB + SectionTooLarge, } impl fmt::Display for Error { @@ -508,6 +516,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] Self::Io(e) => write!(f, "I/O error: {e}"), Self::NoItemsFound => write!(f, "no items found"), + Self::SectionTooLarge => write!(f, "PEM section exceeds maximum allowed size of 10 MB"), } } } diff --git a/tests/pem.rs b/tests/pem.rs index d982180..1d940a6 100644 --- a/tests/pem.rs +++ b/tests/pem.rs @@ -352,3 +352,44 @@ impl Read for ErrorReader { Err(io::Error::new(io::ErrorKind::Other, "read error")) } } + +/// Reproduction for . +/// +/// We should stop reading if a PEM section is too long. +#[test] +fn section_too_large() { + let reader = UnboundedReader { + header: b"-----BEGIN CERTIFICATE-----\n", + read: 0, + }; + + let mut buf_reader = io::BufReader::new(reader); + let result = pem::from_buf(&mut buf_reader); + assert!(matches!(result, Err(pem::Error::SectionTooLarge))); + let reader = buf_reader.into_inner(); + assert!(reader.read < 68_000_000, "{}", reader.read); +} + +struct UnboundedReader { + header: &'static [u8], + read: usize, +} + +impl Read for UnboundedReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + if !self.header.is_empty() { + let n = self.header.len().min(buf.len()); + buf[..n].copy_from_slice(&self.header[..n]); + self.header = &self.header[n..]; + self.read += n; + return Ok(n); + } + + // Emit a base64-like line (76 chars + newline, standard PEM width) + let line = b"QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\n"; + let n = line.len().min(buf.len()); + buf[..n].copy_from_slice(&line[..n]); + self.read += n; + Ok(n) + } +} From 20bcfe1e4e3404c129aa929425d9a2d20926d330 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 11 Apr 2026 01:03:26 +0200 Subject: [PATCH 4/5] Bump version to 1.14.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45034b0..e75593a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" dependencies = [ "crabgrind", "web-time", diff --git a/Cargo.toml b/Cargo.toml index 7228320..b6d43d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" edition = "2021" rust-version = "1.60" license = "MIT OR Apache-2.0" From bb3c1da0e69e8ee3dcdfb16c245f974d636ed481 Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Fri, 24 Apr 2026 13:43:08 +0100 Subject: [PATCH 5/5] Adjust PEM size limit to account for huge CRLs --- src/pem.rs | 6 ++++-- tests/pem.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pem.rs b/src/pem.rs index 984e6d7..473392f 100644 --- a/src/pem.rs +++ b/src/pem.rs @@ -339,7 +339,9 @@ fn read( Ok(ControlFlow::Continue(())) } -const MAX_PEM_SECTION_SIZE: usize = 64 * 1024 * 1024; +// We've seen CRLs of 100MB (DER) / ~135MB (PEM) in the wild. +// 256MB seems like an OK upper bound. +const MAX_PEM_SECTION_SIZE: usize = 256 * 1024 * 1024; enum SectionLabel { Known(SectionKind), @@ -499,7 +501,7 @@ pub enum Error { /// No items found of desired type NoItemsFound, - /// PEM section exceeds maximum allowed size of 64 MB + /// PEM section exceeds maximum allowed size of 256 MB SectionTooLarge, } diff --git a/tests/pem.rs b/tests/pem.rs index 1d940a6..ce0bc86 100644 --- a/tests/pem.rs +++ b/tests/pem.rs @@ -367,7 +367,7 @@ fn section_too_large() { let result = pem::from_buf(&mut buf_reader); assert!(matches!(result, Err(pem::Error::SectionTooLarge))); let reader = buf_reader.into_inner(); - assert!(reader.read < 68_000_000, "{}", reader.read); + assert!(reader.read < ((256 + 1) * 1024 * 1024), "{}", reader.read); } struct UnboundedReader {