diff --git a/libclamav_rust/src/alz.rs b/libclamav_rust/src/alz.rs index fef676a0db..a87c2511b3 100644 --- a/libclamav_rust/src/alz.rs +++ b/libclamav_rust/src/alz.rs @@ -358,7 +358,7 @@ impl AlzLocalFileHeader { data: buffer.to_vec(), }; - if 0 != extracted_file.data.len() { + if !extracted_file.data.is_empty() { files.push(extracted_file); } } diff --git a/libclamav_rust/src/cdiff.rs b/libclamav_rust/src/cdiff.rs index 3e3bf87a35..894b666c8f 100644 --- a/libclamav_rust/src/cdiff.rs +++ b/libclamav_rust/src/cdiff.rs @@ -788,8 +788,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { .map_err(|e| { InputError::ProcessingString(format!( "Failed to open destination file {:?} for MOVE command: {}", - &move_op.dst, - e.to_string() + &move_op.dst, e )) })?; @@ -801,7 +800,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { InputError::ProcessingString(format!( "Failed to create temp file in current directory {:?} for MOVE command: {}", std::env::current_dir(), - e.to_string() + e )) })?; let mut tmp_file = tmp_named_file.as_file(); @@ -810,8 +809,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { let mut src_reader = BufReader::new(File::open(&move_op.src).map_err(|e| { InputError::ProcessingString(format!( "Failed to open source file {:?}: {} for MOVE command", - &move_op.src, - e.to_string() + &move_op.src, e )) })?); @@ -824,8 +822,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { let n_read = src_reader.read_until(b'\n', &mut line).map_err(|e| { InputError::ProcessingString(format!( "Failed to read from source file {:?} for MOVE command: {}", - &move_op.src, - e.to_string() + &move_op.src, e )) })?; if n_read == 0 { @@ -860,7 +857,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { InputError::ProcessingString(format!( "Failed to write line to temp file {:?} for MOVE command: {}", tmp_named_file.path(), - e.to_string() + e )) })?; } @@ -880,8 +877,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { fs::remove_file(&move_op.src).map_err(|e| { InputError::ProcessingString(format!( "Failed to remove original source file {:?} for MOVE command: {}", - &move_op.src, - e.to_string() + &move_op.src, e )) })?; fs::rename(tmp_named_file.path(), &move_op.src).map_err(|e| { @@ -889,7 +885,7 @@ fn cmd_move(ctx: &mut Context, move_op: MoveOp) -> Result<(), InputError> { "Failed to rename temp file {:?} to {:?} for MOVE command: {}", tmp_named_file.path(), &move_op.src, - e.to_string() + e )) })?; @@ -911,8 +907,7 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { let mut src_reader = BufReader::new(File::open(&open_db).map_err(|e| { InputError::ProcessingString(format!( "Failed to open db file {:?} for CLOSE command: {}", - &open_db, - e.to_string() + &open_db, e )) })?); @@ -924,7 +919,7 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { InputError::ProcessingString(format!( "Failed to create temp file in current directory {:?} for CLOSE command: {}", std::env::current_dir(), - e.to_string() + e )) })?; let tmp_file = tmp_named_file.as_file(); @@ -937,7 +932,7 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { InputError::ProcessingString(format!( "Failed to read temp file {:?} for CLOSE command: {}", tmp_named_file.path(), - e.to_string() + e )) })?; if n_read == 0 { @@ -989,14 +984,14 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { InputError::ProcessingString(format!( "Failed to write line to temp file {:?} for CLOSE command: {}", tmp_named_file.path(), - e.to_string() + e )) })?; tmp_file.write_all(b"\n").map_err(|e| { InputError::ProcessingString(format!( "Failed to write new line to temp file {:?} for CLOSE command: {}", tmp_named_file.path(), - e.to_string() + e )) })?; } @@ -1035,14 +1030,12 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { fs::remove_file(tmpfile_path).map_err(|e| { InputError::ProcessingString(format!( "Failed to remove the temp file file {:?} for CLOSE command: {}", - tmpfile_path, - e.to_string() + tmpfile_path, e )) })?; return Err(InputError::ProcessingString(format!( "Failed to remove open db file {:?} for CLOSE command: {}", - &open_db, - e.to_string() + &open_db, e )) .into()); } @@ -1050,17 +1043,13 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { fs::remove_file(&tmpfile_path).map_err(|e| { InputError::ProcessingString(format!( "Failed to remove temp file {:?}: {} for CLOSE command", - &tmpfile_path, - e.to_string() + &tmpfile_path, e )) })?; return Err(InputError::ProcessingString(format!( "Failed to rename temp file {:?} to {:?} for CLOSE command: {}", - tmpfile_path, - &open_db, - e.to_string() - )) - .into()); + tmpfile_path, &open_db, e + ))); } } @@ -1073,15 +1062,13 @@ fn cmd_close(ctx: &mut Context) -> Result<(), InputError> { .map_err(|e| { InputError::ProcessingString(format!( "Failed to open db file {:?} for CLOSE command: {}", - open_db, - e.to_string() + open_db, e )) })?; db_file.write_all(&ctx.additions).map_err(|e| { InputError::ProcessingString(format!( "Failed to write add lines to db {:?} for CLOSE command: {}", - open_db, - e.to_string() + open_db, e )) })?; ctx.additions.clear(); @@ -1104,8 +1091,7 @@ fn cmd_unlink(ctx: &mut Context, unlink_op: UnlinkOp) -> Result<(), InputError> fs::remove_file(unlink_op.db_name).map_err(|e| { InputError::ProcessingString(format!( "Failed to remove db file {:?} for UNLINK command: {}", - unlink_op.db_name, - e.to_string() + unlink_op.db_name, e )) })?; @@ -1117,7 +1103,7 @@ fn process_line(ctx: &mut Context, line: &[u8]) -> Result<(), InputError> { let mut tokens = line.splitn(2, |b| *b == b' ' || *b == b'\n'); let cmd = tokens.next().ok_or(InputError::MissingCommand)?; let remainder_with_nl = tokens.next(); - let remainder = remainder_with_nl.and_then(|s| s.strip_suffix(&[b'\n'])); + let remainder = remainder_with_nl.and_then(|s| s.strip_suffix(b"\n")); // Call the appropriate command function match cmd { diff --git a/libclamav_rust/src/codesign.rs b/libclamav_rust/src/codesign.rs index 0667915dc5..3710553d7e 100644 --- a/libclamav_rust/src/codesign.rs +++ b/libclamav_rust/src/codesign.rs @@ -124,7 +124,7 @@ pub unsafe extern "C" fn codesign_sign_file( std::slice::from_raw_parts(intermediate_cert_paths_str, intermediate_cert_paths_len); // now convert the intermediate_cert_path_strs to a Vec<&Path> let intermediate_cert_paths: Vec = intermediate_cert_path_strs - .into_iter() + .iter() .filter_map(|&path_str| -> Option { let path_str = if path_str.is_null() { warn!("Intermiediate path string is NULL"); @@ -148,7 +148,7 @@ pub unsafe extern "C" fn codesign_sign_file( "Invalid intermediate certificate path: '{}' {}", path_str, e ); - return None; + None } } } else { @@ -173,7 +173,7 @@ pub unsafe extern "C" fn codesign_sign_file( match sign_file( &target_file_path, - &signature_file_path, + signature_file_path, &signing_cert_path, &intermediate_cert_paths, &signing_key_path, @@ -183,7 +183,7 @@ pub unsafe extern "C" fn codesign_sign_file( true } Err(e) => { - return ffi_error!(err = err, e); + ffi_error!(err = err, e) } } } @@ -220,21 +220,21 @@ where // Seek to the end of the file writer.seek(std::io::SeekFrom::End(0))?; // Write a newline before the signature - writer.write(b"\n")?; + writer.write_all(b"\n")?; writer } else { // Create the signature file if it doesn't exist. let mut writer = std::io::BufWriter::new(std::fs::File::create(signature_file_path)?); - writer.write(b"#clamsign-1.0\n")?; + writer.write_all(b"#clamsign-1.0\n")?; writer }; - writer.write(sig_bytes.as_bytes())?; + writer.write_all(sig_bytes.as_bytes())?; // Write a newline after the signature - writer.write(b"\n")?; + writer.write_all(b"\n")?; Ok(()) } @@ -316,7 +316,7 @@ pub unsafe extern "C" fn codesign_verify_file( true } Err(e) => { - return ffi_error!(err = err, e); + ffi_error!(err = err, e) } } } @@ -330,9 +330,9 @@ pub fn verify_signed_file( signature_file_path: &Path, certs_directory: &Path, ) -> Result { - let signature_file: File = File::open(&signature_file_path)?; + let signature_file: File = File::open(signature_file_path)?; - let mut signed_file: File = File::open(&signed_file_path)?; + let mut signed_file: File = File::open(signed_file_path)?; let mut file_data = Vec::::new(); let read_result = signed_file.read_to_end(&mut file_data); @@ -447,9 +447,9 @@ pub fn verify_signed_file( }; } - return Err(Error::CannotVerify( + Err(Error::CannotVerify( "Unable to verify any digital signatures".to_string(), - )); + )) } pub struct Signer { @@ -491,8 +491,7 @@ impl Signer { pub fn sign(&self, data: &[u8]) -> Result { let flags = Pkcs7Flags::DETACHED | Pkcs7Flags::BINARY; - Pkcs7::sign(&self.cert, &self.key, &self.certs, data, flags) - .map_err(|e| Error::OpenSSLError(e)) + Pkcs7::sign(&self.cert, &self.key, &self.certs, data, flags).map_err(Error::OpenSSLError) } } @@ -522,7 +521,7 @@ impl Verifier { // That doesn't mean the signature is invalid, only that we don't have the required public key to verify it. for cert in cert_stack { let serial = cert.serial_number().to_bn()?; - if top_level_signer == None { + if top_level_signer.is_none() { let signer = cert .subject_name() .entries() diff --git a/libclamav_rust/src/cvd.rs b/libclamav_rust/src/cvd.rs index bd4f24a06c..24cf28db87 100644 --- a/libclamav_rust/src/cvd.rs +++ b/libclamav_rust/src/cvd.rs @@ -18,7 +18,7 @@ * MA 02110-1301, USA. */ - use std::{ +use std::{ ffi::{CStr, CString}, fs::File, io::{prelude::*, BufReader}, @@ -78,34 +78,6 @@ pub struct CVD { } impl CVD { - pub fn new( - name: String, - time_creation: SystemTime, - version: u32, - num_sigs: u32, - min_flevel: u32, - rsa_dsig: Option, - md5: Option, - builder: String, - path: PathBuf, - is_compressed: bool, - ) -> Self { - let file = File::open(&path).unwrap(); - Self { - name, - time_creation, - version, - num_sigs, - min_flevel, - rsa_dsig, - md5, - builder, - file, - path, - is_compressed, - } - } - pub fn from_file(file_path: &Path) -> Result { let file = File::open(file_path) .map_err(|_| Error::Parse(format!("Failed to open file: {:?}", file_path)))?; @@ -124,7 +96,7 @@ impl CVD { .to_str() .ok_or_else(|| Error::Parse("Database file stem is not valid unicode".to_string()))?; let name = database_file_stem_str - .split(|c| c == '-' || c == '.') + .split(['-', '.']) .next() .ok_or_else(|| { Error::Parse("Failed to get database name from database file stem".to_string()) @@ -132,15 +104,17 @@ impl CVD { .to_string(); // read the 512 byte header - let mut header: [u8; 512] = [0; 512]; + let mut header: [u8; 512] = [0; 512]; reader .read_exact(&mut header) .map_err(|_| Error::Parse("File is smaller than 512-byte CVD header".to_string()))?; let mut maybe_copying: [u8; 7] = [0; 7]; - reader - .read_exact(&mut maybe_copying) - .map_err(|_| Error::Parse("Can't read first 7 bytes of the tar file following the header.".to_string()))?; + reader.read_exact(&mut maybe_copying).map_err(|_| { + Error::Parse( + "Can't read first 7 bytes of the tar file following the header.".to_string(), + ) + })?; let is_compressed = if &maybe_copying == b"COPYING" { // Able to read the contents of the first file, which must be COPYING. @@ -300,15 +274,13 @@ impl CVD { .map_err(|e| { Error::Parse(format!( "Failed to enumerate files in signature archive: {}", - e.to_string() + e )) })? // .filter_map(|e| e.ok()) - .for_each(|entry| -> () { + .for_each(|entry| { let mut entry = match entry { - Ok(entry) => { - entry - } + Ok(entry) => entry, Err(e) => { error!("Failed to get entry in signature archive: {}", e); return; @@ -367,7 +339,7 @@ impl CVD { debug!("MD5 hash: {}", calculated_md5); if let Some(md5) = &self.md5 { - if calculated_md5 != &md5[..] { + if calculated_md5 != md5[..] { warn!("MD5 hash does not match the expected hash"); return Err(Error::InvalidDigitalSignature( "MD5 hash does not match the expected hash".to_string(), @@ -427,7 +399,7 @@ impl CVD { .to_str() .ok_or_else(|| Error::Parse("Database file stem is not valid unicode".to_string()))?; let database_name = database_file_stem_str - .split(|c| c == '-' || c == '.') + .split(['-', '.']) .next() .ok_or_else(|| { Error::Parse("Failed to get database name from database file stem".to_string()) @@ -439,21 +411,21 @@ impl CVD { match codesign::verify_signed_file(&self.path, &signature_file_path, certs_directory) { Ok(signer) => { debug!("Successfully verified {:?} signed by {}", self.path, signer); - return Ok(signer); + Ok(signer) } Err(codesign::Error::InvalidDigitalSignature(m)) => { warn!( "Failed to verify {:?} with {:?}: Signature is invalid: {}", self.path, signature_file_path, m ); - return Err(Error::InvalidDigitalSignature(m)); + Err(Error::InvalidDigitalSignature(m)) } Err(e) => { debug!( "Failed to verify {:?} with {:?}: {}", self.path, signature_file_path, e ); - return Err(Error::CannotVerify(e.to_string())); + Err(Error::CannotVerify(e.to_string())) } } } @@ -558,18 +530,18 @@ pub unsafe extern "C" fn cvd_check( Ok(signer) => { let signer_cstr = std::ffi::CString::new(signer).unwrap(); *signer_name = signer_cstr.into_raw(); - return true; + true } Err(e) => { - return ffi_error!(err = err, e); + ffi_error!(err = err, e) } } } Err(e) => { - return ffi_error!( + ffi_error!( err = err, Error::CannotVerify(format!("Failed to parse CVD: {}", e)) - ); + ) } } } @@ -638,12 +610,12 @@ pub unsafe extern "C" fn cvd_open( }; match CVD::from_file(&cvd_file_path) { - Ok(cvd) => Box::into_raw(Box::::new(cvd)) as *mut CVD as sys::cvd_t, + Ok(cvd) => Box::into_raw(Box::::new(cvd)) as sys::cvd_t, Err(e) => { - return ffi_error_null!( + ffi_error_null!( err = err, Error::CannotVerify(format!("Failed to parse CVD: {}", e)) - ); + ) } } } @@ -691,7 +663,7 @@ pub unsafe extern "C" fn cvd_verify( true } Err(e) => { - return ffi_error!(err = err, e); + ffi_error!(err = err, e) } } } diff --git a/libclamav_rust/src/fuzzy_hash.rs b/libclamav_rust/src/fuzzy_hash.rs index 6d848370ae..cee06683c5 100644 --- a/libclamav_rust/src/fuzzy_hash.rs +++ b/libclamav_rust/src/fuzzy_hash.rs @@ -359,8 +359,8 @@ impl FuzzyHashMap { /// of the mean -- this change is required. /// /// 2) scipy.fftpack.dct behaves differently on twodimensional arrays than -/// single-dimensional arrays. -/// See https://docs.scipy.org/doc/scipy/reference/generated/scipy.fftpack.dct.html: +/// single-dimensional arrays. +/// See https://docs.scipy.org/doc/scipy/reference/generated/scipy.fftpack.dct.html: /// /// Note the optional "axis" argument: /// Axis along which the dct is computed; the default is over the last axis @@ -368,17 +368,17 @@ impl FuzzyHashMap { /// /// For the Python `imagehash` package: /// - The `phash_simple()` function is doing a DCT-2 transform on a 2-dimensional -/// 32x32 array which means, just on the 2nd axis (just the rows). +/// 32x32 array which means, just on the 2nd axis (just the rows). /// - The `phash()` function is doing a 2D DCT-2 transform, by running the DCT-2 on -/// both X and Y axis, which is the same as transposing before or after each -/// DCT-2 call. +/// both X and Y axis, which is the same as transposing before or after each +/// DCT-2 call. /// /// 3) I observed that the DCT2 results from Python are consistently 2x greater -/// than those from Rust. If I multiply every value by 2 after running the DCT, -/// then the results are the same. +/// than those from Rust. If I multiply every value by 2 after running the DCT, +/// then the results are the same. /// /// 4) We need to get a subset of the 2-D array representing the lower -/// frequencies of the image, the same way the Python implementation does it. +/// frequencies of the image, the same way the Python implementation does it. /// /// The way the python implementation does this is with this line: /// ```python diff --git a/libclamav_rust/src/scanners.rs b/libclamav_rust/src/scanners.rs index be8c52acd1..6efb68619d 100644 --- a/libclamav_rust/src/scanners.rs +++ b/libclamav_rust/src/scanners.rs @@ -45,7 +45,11 @@ use crate::{ /// Rust wrapper of libclamav's cli_magic_scan_buff() function. /// Use magic sigs to identify the file type and then scan it. -pub fn magic_scan(ctx: *mut cli_ctx, buf: &[u8], name: Option) -> cl_error_t { +/// +/// # Safety +/// +/// The ctx pointer must be valid. +pub unsafe fn magic_scan(ctx: *mut cli_ctx, buf: &[u8], name: Option) -> cl_error_t { let ptr = buf.as_ptr(); let len = buf.len(); @@ -59,10 +63,7 @@ pub fn magic_scan(ctx: *mut cli_ctx, buf: &[u8], name: Option) -> cl_err } // Convert name to a C string. - let name = match name { - Some(name) => name, - None => String::from(""), - }; + let name = name.unwrap_or_default(); let name_ptr: *mut c_char = match CString::new(name) { Ok(name_cstr) => { @@ -234,49 +235,46 @@ pub unsafe extern "C" fn scan_lha_lzh(ctx: *mut cli_ctx) -> cl_error_t { != cl_error_t_CL_SUCCESS { debug!("Extracted file '{filename}' would exceed size limits. Skipping."); + } else if !decoder.is_decoder_supported() { + debug!("err: unsupported compression method"); } else { - if !decoder.is_decoder_supported() { - debug!("err: unsupported compression method"); - } else { - // Read the file into a buffer. - let mut file_data: Vec = Vec::::new(); - - match decoder.read_to_end(&mut file_data) { - Ok(bytes_read) => { - if bytes_read > 0 { - debug!( + // Read the file into a buffer. + let mut file_data: Vec = Vec::::new(); + + match decoder.read_to_end(&mut file_data) { + Ok(bytes_read) => { + if bytes_read > 0 { + debug!( "Read {bytes_read} bytes from file {filename} in the LHA archive." ); - // Verify the CRC check *after* reading the file. - match decoder.crc_check() { - Ok(crc) => { - // CRC is valid. Very likely this is an LHA or LZH archive. - debug!("CRC check passed. Very likely this is an LHA or LZH archive. CRC: {crc}"); - } - Err(err) => { - // Error checking CRC. - debug!("An error occurred when checking the CRC of this LHA or LZH archive: {err}"); - - // Allow the scan to continue even with a CRC error, for now. - // break; - } + // Verify the CRC check *after* reading the file. + match decoder.crc_check() { + Ok(crc) => { + // CRC is valid. Very likely this is an LHA or LZH archive. + debug!("CRC check passed. Very likely this is an LHA or LZH archive. CRC: {crc}"); } + Err(err) => { + // Error checking CRC. + debug!("An error occurred when checking the CRC of this LHA or LZH archive: {err}"); - // Scan the file. - let ret = - magic_scan(ctx, &file_data, Some(filename.to_string())); - if ret != cl_error_t_CL_SUCCESS { - debug!("cl_scandesc_magic returned error: {}", ret); - return ret; + // Allow the scan to continue even with a CRC error, for now. + // break; } - } else { - debug!("Read zero-byte file."); } + + // Scan the file. + let ret = magic_scan(ctx, &file_data, Some(filename.to_string())); + if ret != cl_error_t_CL_SUCCESS { + debug!("cl_scandesc_magic returned error: {}", ret); + return ret; + } + } else { + debug!("Read zero-byte file."); } - err => { - debug!("Error reading file {err:?}"); - } + } + err => { + debug!("Error reading file {err:?}"); } } }