From ff79a327b7d08c5f31659a3af8b2db4957ebe0fd Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 11:48:54 +0200 Subject: [PATCH 1/8] Add pre-commit config, to be used with `pre-commit` or `prek` --- .pre-commit-config.yaml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..17ef8f0 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,40 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +fail_fast: true + +exclude: | + (?x)^( + .*/(assets)/.*| + )$ + +repos: + - repo: 'https://github.com/pre-commit/pre-commit-hooks' + rev: v6.0.0 + hooks: + - id: trailing-whitespace + #- id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + + - repo: local + hooks: + - id: cargo-fmt + name: cargo fmt + entry: cargo fmt -- + language: system + types: [rust] + pass_filenames: false # This makes it a lot faster + + - id: cargo-clippy + name: cargo clippy + language: system + types: [rust] + pass_filenames: false + entry: cargo clippy --all-targets --features validate,verify,verify-aws -- -D warnings + + - id: cargo-rdme + name: cargo rdme + language: system + types: [rust] + pass_filenames: false + entry: cargo rdme --intralinks-features validate,verify,verify-aws -c From e82656223bf64c4699dbd1863dc0182bd34f3954 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 11:50:45 +0200 Subject: [PATCH 2/8] CI: use `prek` to run pre-commit checks --- .github/workflows/rust.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 43f1d3c..0996326 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,6 +8,19 @@ on: - cron: "0 18 * * *" jobs: + pre_commit: + timeout-minutes: 5 + name: prek + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + # tools used in pre-commit hooks + - id: cargo-rdme + uses: rusticata/ci-action-rdme@v1 + # /tools + - id: prek + uses: rusticata/ci-action-prek@v1 + check: name: Check runs-on: ubuntu-latest From e48e04ca76c2f1d5501f8b1c725a52bce23761eb Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 14:55:44 +0200 Subject: [PATCH 3/8] examples: fix clippy warnings Fix warnings: - redundant reference in `print!` argument - this can be `std::io::Error::other(_)` --- examples/print-cert.rs | 6 +++--- examples/print-crl.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/print-cert.rs b/examples/print-cert.rs index aa41423..d1e287d 100644 --- a/examples/print-cert.rs +++ b/examples/print-cert.rs @@ -18,7 +18,7 @@ const VALIDATE_ERRORS_FATAL: bool = false; fn print_hex_dump(bytes: &[u8], max_len: usize) { let m = min(bytes.len(), max_len); - print!("{}", &bytes[..m].to_hex(16)); + print!("{}", bytes[..m].to_hex(16)); if bytes.len() > max_len { println!("... "); } @@ -208,7 +208,7 @@ fn print_x509_info(x509: &X509Certificate) -> io::Result<()> { } println!(); if VALIDATE_ERRORS_FATAL && !logger.errors().is_empty() { - return Err(io::Error::new(io::ErrorKind::Other, "validation failed")); + return Err(io::Error::other("validation failed")); } } #[cfg(not(feature = "validate"))] @@ -390,7 +390,7 @@ fn handle_certificate(file_name: &str, data: &[u8]) -> io::Result<()> { Err(e) => { let s = format!("Error while parsing {file_name}: {e}"); if PARSE_ERRORS_FATAL { - Err(io::Error::new(io::ErrorKind::Other, s)) + Err(io::Error::other(s)) } else { eprintln!("{s}"); Ok(()) diff --git a/examples/print-crl.rs b/examples/print-crl.rs index 5888de6..81c9b07 100644 --- a/examples/print-crl.rs +++ b/examples/print-crl.rs @@ -7,7 +7,7 @@ use x509_parser::prelude::*; fn print_hex_dump(bytes: &[u8], max_len: usize) { let m = min(bytes.len(), max_len); - print!("{}", &bytes[..m].to_hex(16)); + print!("{}", bytes[..m].to_hex(16)); if bytes.len() > max_len { println!("... "); } @@ -29,7 +29,7 @@ fn print_authority_key_identifier(aki: &AuthorityKeyIdentifier, level: usize) { } if let Some(serial) = &aki.authority_cert_serial { let s = format_serial(serial.as_raw_slice().unwrap()); - println!("{:indent$}serial: {}", "", &s, indent = level); + println!("{:indent$}serial: {}", "", s, indent = level); } } From bb1de965fb3ef2275873acd878e01066d18a90f0 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 15:08:24 +0200 Subject: [PATCH 4/8] Define list of clippy warnings in cargo manifest --- Cargo.toml | 11 +++++++++++ src/extensions/sct.rs | 1 + 2 files changed, 12 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 4bf77f5..36f86d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,3 +58,14 @@ time = { version="0.3.41", features=["formatting"] } [dev-dependencies] hex-literal = "0.4" +[lints.clippy] +#pedantic = { level = "warn", priority = -1 } +unwrap_used = "warn" +expect_used = "warn" +panic = "warn" +todo = "warn" +unimplemented = "warn" +unreachable = "warn" +dbg_macro = "warn" +#print_stdout = "warn" +#print_stderr = "warn" diff --git a/src/extensions/sct.rs b/src/extensions/sct.rs index 5e2f5c5..22563e9 100644 --- a/src/extensions/sct.rs +++ b/src/extensions/sct.rs @@ -97,6 +97,7 @@ pub(crate) fn parse_ct_signed_certificate_timestamp_content( } // Safety: cannot fail, take() returns exactly 32 bytes +#[expect(clippy::expect_used)] fn parse_log_id(i: &[u8]) -> IResult<&[u8], CtLogID<'_>, Error> { let (i, key_id) = take(32usize)(i)?; Ok(( From 82306a5250f03fc53d1532ba46d9c2775c0b3f65 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 15:18:34 +0200 Subject: [PATCH 5/8] Move rust and rustdoc lints to cargo manifest --- Cargo.toml | 12 ++++++++++++ src/lib.rs | 11 ----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 36f86d1..d1c7568 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,18 @@ time = { version="0.3.41", features=["formatting"] } [dev-dependencies] hex-literal = "0.4" +[lints.rust] +unsafe_code = "forbid" +#missing_docs = "warn" +unstable_features = "deny" +unused_import_braces = "deny" +unused_qualifications = "deny" +missing_debug_implementations = "warn" +unreachable_pub = "warn" + +[lints.rustdoc] +broken_intra_doc_links = "deny" + [lints.clippy] #pedantic = { level = "warn", priority = -1 } unwrap_used = "warn" diff --git a/src/lib.rs b/src/lib.rs index 58ccfad..e0e935c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,17 +133,6 @@ //! //! [RFC5280]: https://tools.ietf.org/html/rfc5280 -#![deny(/*missing_docs,*/ - unstable_features, - unused_import_braces, unused_qualifications)] -#![warn( - missing_debug_implementations, - /* missing_docs, - rust_2018_idioms,*/ - unreachable_pub -)] -#![forbid(unsafe_code)] -#![deny(rustdoc::broken_intra_doc_links)] #![doc(test( no_crate_inject, attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) From 1cf3ce8a26c7a1a1239cf7098e4f12c069027146 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 15:46:05 +0200 Subject: [PATCH 6/8] CI: set `cargo rdme` arguments when checking pre-commit --- .github/workflows/rust.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0996326..8cf410f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -16,7 +16,9 @@ jobs: - uses: actions/checkout@v6 # tools used in pre-commit hooks - id: cargo-rdme - uses: rusticata/ci-action-rdme@v1 + uses: rusticata/ci-action-rdme@v2 + with: + rdme-args: --intralinks-features validate,verify,verify-aws # /tools - id: prek uses: rusticata/ci-action-prek@v1 From f1b36339d06aa358677eaa99392fc4c19aff13e1 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 15:51:15 +0200 Subject: [PATCH 7/8] Clippy: allow unwrap/expect/panic in tests --- clippy.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 clippy.toml diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..7bada54 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,3 @@ +allow-unwrap-in-tests = true +allow-expect-in-tests = true +allow-panic-in-tests = true From f3087e6e2ac5f62af3b4d0f8f360d1b21c9797ba Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Thu, 6 Aug 2026 16:09:13 +0200 Subject: [PATCH 8/8] Fix clippy warnings and allow expect/unwrap/unimplemented in tests and some examples --- examples/print-cert.rs | 2 ++ examples/print-crl.rs | 3 +++ src/extensions/mod.rs | 1 + tests/readcrl.rs | 2 ++ tests/readcsr.rs | 22 ++++++++++++---------- tests/run_all_fuzz_files.rs | 1 + 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/examples/print-cert.rs b/examples/print-cert.rs index d1e287d..6de65fa 100644 --- a/examples/print-cert.rs +++ b/examples/print-cert.rs @@ -1,3 +1,5 @@ +#![allow(clippy::expect_used)] +#![allow(clippy::unwrap_used)] use asn1_rs::Any; use asn1_rs::Input; use asn1_rs::Oid; diff --git a/examples/print-crl.rs b/examples/print-crl.rs index 81c9b07..25ace7f 100644 --- a/examples/print-crl.rs +++ b/examples/print-crl.rs @@ -1,3 +1,6 @@ +#![allow(clippy::unimplemented)] +#![allow(clippy::unwrap_used)] +#![allow(clippy::expect_used)] use asn1_rs::Oid; use nom::HexDisplay; use std::cmp::min; diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index f561988..fb70727 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -713,6 +713,7 @@ mod tests { assert!(!ku.decipher_only()); } + #[expect(clippy::unreachable)] #[test] fn test_extensions1() { let crt = crate::parse_x509_certificate(include_bytes!("../../assets/extension1.der")) diff --git a/tests/readcrl.rs b/tests/readcrl.rs index 206d60d..76c6de7 100644 --- a/tests/readcrl.rs +++ b/tests/readcrl.rs @@ -1,3 +1,5 @@ +#![allow(clippy::expect_used)] +#![allow(clippy::panic)] use x509_parser::prelude::*; #[cfg(any( diff --git a/tests/readcsr.rs b/tests/readcsr.rs index f30f45f..88d7654 100644 --- a/tests/readcsr.rs +++ b/tests/readcsr.rs @@ -1,9 +1,10 @@ +#![allow(clippy::unreachable)] use asn1_rs::{oid, Oid, Set}; use oid_registry::{ OID_PKCS1_SHA256WITHRSA, OID_PKCS9_CHALLENGE_PASSWORD, OID_PKCS9_EXTENSION_REQUEST, OID_SIG_ECDSA_WITH_SHA256, OID_X509_COMMON_NAME, }; -use x509_parser::prelude::*; +use x509_parser::{pem::parse_x509_pem, prelude::*}; const CSR_DATA_EMPTY_ATTRIB: &[u8] = include_bytes!("../assets/csr-empty-attributes.csr"); const CSR_DATA: &[u8] = include_bytes!("../assets/test.csr"); @@ -25,7 +26,7 @@ fn read_csr_empty_attrib() { #[test] fn read_csr_with_san() { - let der = pem::parse_x509_pem(CSR_DATA).unwrap().1; + let der = parse_x509_pem(CSR_DATA).unwrap().1; let (rem, csr) = X509CertificationRequest::from_der(&der.contents).expect("could not parse CSR"); @@ -67,7 +68,7 @@ fn read_csr_with_san() { #[test] fn read_csr_with_challenge_password() { - let der = pem::parse_x509_pem(CSR_CHALLENGE_PASSWORD).unwrap().1; + let der = parse_x509_pem(CSR_CHALLENGE_PASSWORD).unwrap().1; let (rem, csr) = X509CertificationRequest::from_der(&der.contents) .expect("Could not parse CSR with challenge password"); @@ -117,7 +118,7 @@ fn read_csr_with_challenge_password() { #[test] fn test_iter_raw_values() { - let der = pem::parse_x509_pem(CSR_CHALLENGE_PASSWORD).unwrap().1; + let der = parse_x509_pem(CSR_CHALLENGE_PASSWORD).unwrap().1; let (_, csr) = X509CertificationRequest::from_der(&der.contents) .expect("Could not parse CSR with challenge password"); @@ -139,7 +140,7 @@ fn test_iter_raw_values() { // Verify raw DER: tag should be UTF8String (0x0C), not SET (0x31) assert_eq!( any_val.header.tag(), - x509_parser::asn1_rs::Tag::Utf8String, + asn1_rs::Tag::Utf8String, "iter_raw_values should yield individual values inside the SET, not the SET itself" ); let s = std::str::from_utf8(any_val.data.as_bytes2()) @@ -162,7 +163,7 @@ fn test_iter_raw_values() { // Verify raw DER: tag should be SEQUENCE (0x30), not SET (0x31) assert_eq!( any_val.header.tag(), - x509_parser::asn1_rs::Tag::Sequence, + asn1_rs::Tag::Sequence, "iter_raw_values should yield SET contents, not the SET envelope" ); } @@ -174,11 +175,11 @@ fn test_iter_raw_values() { ))] #[test] fn read_csr_verify() { - let pem = pem::parse_x509_pem(CSR_DATA).unwrap().1; + let pem = parse_x509_pem(CSR_DATA).unwrap().1; let (_, csr) = X509CertificationRequest::from_der(&pem.contents).expect("could not parse CSR"); csr.verify_signature().unwrap(); - let mut der = pem::parse_x509_pem(CSR_DATA).unwrap().1; + let mut der = parse_x509_pem(CSR_DATA).unwrap().1; assert_eq!(&der.contents[28..37], b"rusticata"); for (i, b) in b"foobarbaz".iter().enumerate() { der.contents[28 + i] = *b; @@ -192,14 +193,15 @@ fn read_csr_verify() { assert_eq!(csr.as_raw(), &der.contents); } +#[expect(clippy::unreachable)] #[test] fn read_csr_with_custom_extension() { - let der = pem::parse_x509_pem(CSR_CUSTOM_EXTENSION).unwrap().1; + let der = parse_x509_pem(CSR_CUSTOM_EXTENSION).unwrap().1; let (rem, csr) = X509CertificationRequest::from_der(&der.contents) .expect("Could not parse CSR with custom extension"); assert!(rem.is_empty()); - dbg!(csr.certification_request_info.attributes()); + //dbg!(csr.certification_request_info.attributes()); let cri = &csr.certification_request_info; assert_eq!(cri.version, X509Version(0)); assert_eq!(cri.attributes().len(), 1); diff --git a/tests/run_all_fuzz_files.rs b/tests/run_all_fuzz_files.rs index 96041b4..f9b3936 100644 --- a/tests/run_all_fuzz_files.rs +++ b/tests/run_all_fuzz_files.rs @@ -1,3 +1,4 @@ +#![allow(clippy::unwrap_used)] use std::fs::{self, DirEntry}; use x509_parser::parse_x509_certificate;