From 2c86cfa5947f4daea25c7c058c4108dbbfcb96a0 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sun, 8 Jan 2023 23:38:31 -0300 Subject: [PATCH] Avoid segmentation fault when failing to decode entry If operating system doesn't has support for the required locale, `ffi::archive_entry_pathname(...)` returns NULL and we need to error out accordingly. Fixes: #100 Signed-off-by: Otavio Salvador --- CHANGES.md | 2 ++ src/lib.rs | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dc77f9c..9e3fcd5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,8 +5,10 @@ ## [Unreleased] - ReleaseDate * Add illumos compilation support [#99] +* Fix segmentation when failing to decode entry [#100] [#99]: https://github.com/OSSystems/compress-tools-rs/pull/99 +[#100]: https://github.com/OSSystems/compress-tools-rs/issues/100 ## [0.14.0] - 2022-11-20 diff --git a/src/lib.rs b/src/lib.rs index 7068d34..306aa68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,7 +131,7 @@ where } let _utf8_guard = ffi::WindowsUTF8LocaleGuard::new(); - let cstr = CStr::from_ptr(ffi::archive_entry_pathname(entry)); + let cstr = libarchive_entry_pathname(entry)?; let file_name = decode(cstr.to_bytes())?; file_list.push(file_name); } @@ -246,7 +246,7 @@ where } let _utf8_guard = ffi::WindowsUTF8LocaleGuard::new(); - let cstr = CStr::from_ptr(ffi::archive_entry_pathname(entry)); + let cstr = libarchive_entry_pathname(entry)?; let target_path = CString::new( dest.join(sanitize_destination_path(Path::new(&decode( cstr.to_bytes(), @@ -356,7 +356,7 @@ where } let _utf8_guard = ffi::WindowsUTF8LocaleGuard::new(); - let cstr = CStr::from_ptr(ffi::archive_entry_pathname(entry)); + let cstr = libarchive_entry_pathname(entry)?; let file_name = decode(cstr.to_bytes())?; if file_name == path { break; @@ -580,6 +580,19 @@ fn libarchive_copy_data( } } +fn libarchive_entry_pathname<'a>(entry: *mut ffi::archive_entry) -> Result<&'a CStr> { + let pathname = unsafe { ffi::archive_entry_pathname(entry) }; + if pathname.is_null() { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "archive entry has unreadable filename.".to_string(), + ) + .into()); + } + + Ok(unsafe { CStr::from_ptr(pathname) }) +} + unsafe fn libarchive_write_data_block( archive_reader: *mut ffi::archive, mut target: W,