diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 43f1d3c..8cf410f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,6 +8,21 @@ 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@v2 + with: + rdme-args: --intralinks-features validate,verify,verify-aws + # /tools + - id: prek + uses: rusticata/ci-action-prek@v1 + check: name: Check runs-on: ubuntu-latest 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 diff --git a/Cargo.toml b/Cargo.toml index 4bf77f5..d1c7568 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,3 +58,26 @@ 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" +expect_used = "warn" +panic = "warn" +todo = "warn" +unimplemented = "warn" +unreachable = "warn" +dbg_macro = "warn" +#print_stdout = "warn" +#print_stderr = "warn" 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 diff --git a/examples/print-cert.rs b/examples/print-cert.rs index aa41423..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; @@ -18,7 +20,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 +210,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 +392,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..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; @@ -7,7 +10,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 +32,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); } } 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/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(( 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)) 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;