From 96bfb178b0f23f4c4f2be3104c5c014b0da8abd6 Mon Sep 17 00:00:00 2001 From: *Nix Fanboy <63163893+nix-enthusiast@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:15:29 +0300 Subject: [PATCH] String Conversion Revamp - String/&str to C char logic is revamped --- README.md | 2 +- media/banner/UniLDD Banner.png | Bin media/emblems/UniLDD-%100.png | Bin media/emblems/UniLDD-%400.png | Bin src/archive.rs | 13 ++++---- src/coff.rs | 14 ++++---- src/debug.rs | 17 ++++------ src/elf.rs | 18 ++++++----- src/impls.rs | 57 ++++++++++++++++++++------------- src/lib.rs | 22 +++++++------ src/mach.rs | 36 +++++++++++---------- src/pe.rs | 18 ++++++----- src/structs.rs | 3 -- src/types.rs | 0 14 files changed, 107 insertions(+), 93 deletions(-) mode change 100755 => 100644 media/banner/UniLDD Banner.png mode change 100755 => 100644 media/emblems/UniLDD-%100.png mode change 100755 => 100644 media/emblems/UniLDD-%400.png mode change 100755 => 100644 src/archive.rs mode change 100755 => 100644 src/coff.rs mode change 100755 => 100644 src/elf.rs mode change 100755 => 100644 src/impls.rs mode change 100755 => 100644 src/lib.rs mode change 100755 => 100644 src/mach.rs mode change 100755 => 100644 src/pe.rs mode change 100755 => 100644 src/structs.rs mode change 100755 => 100644 src/types.rs diff --git a/README.md b/README.md index 08bd7c4..0687444 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Basically: `cp header/unildd.h /my/amazing/project/` ### License -This library is licensed with [BSD-3 Clause License](https://choosealicense.com/licenses/bsd-3-clause/) +This library is licensed under [BSD-3 Clause License](https://choosealicense.com/licenses/bsd-3-clause/) The resources used to make this library are cited as comments in the respective source files which they were used. diff --git a/media/banner/UniLDD Banner.png b/media/banner/UniLDD Banner.png old mode 100755 new mode 100644 diff --git a/media/emblems/UniLDD-%100.png b/media/emblems/UniLDD-%100.png old mode 100755 new mode 100644 diff --git a/media/emblems/UniLDD-%400.png b/media/emblems/UniLDD-%400.png old mode 100755 new mode 100644 diff --git a/src/archive.rs b/src/archive.rs old mode 100755 new mode 100644 index 8d45f0d..d801fca --- a/src/archive.rs +++ b/src/archive.rs @@ -1,9 +1,10 @@ use crate::{ - debug::{debug_objects, find_error_type, merge_members}, + debug::{debug_objects, merge_members}, parse_objects, - structs::{CharVec, Debugging, ParsingError, StringPtr, ULDDObj, ULDDObjResult}, + structs::{CharVec, Debugging, ParsingError, ULDDObj, ULDDObjResult}, }; use goblin::archive::Archive; +use crate::impls::{ErrorToInt, StringToCString}; pub(crate) fn parse_archive<'a>( file_name: &'a str, @@ -25,13 +26,13 @@ pub(crate) fn parse_archive<'a>( error)).print(debugging); return objects.push(ULDDObjResult { error: ParsingError { - code: find_error_type(&error), - explanation: StringPtr::from(error.to_string()).0, + code: error.to_int(), + explanation: error.to_c_string(), }, obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), - file_type: StringPtr::from("Archive").0, + file_type: "Archive".to_c_string(), ..Default::default() }, }); diff --git a/src/coff.rs b/src/coff.rs old mode 100755 new mode 100644 index 701645c..7bf7fd3 --- a/src/coff.rs +++ b/src/coff.rs @@ -1,6 +1,6 @@ use crate::{ debug::debug_objects, - structs::{CharVec, ParsingError, StringPtr, ULDDObj, ULDDObjResult}, + structs::{CharVec, ParsingError, ULDDObj, ULDDObjResult}, types::PE_ARCH, }; use goblin::pe::{ @@ -8,6 +8,8 @@ use goblin::pe::{ Coff, }; use std::ptr::null_mut; +use crate::debug::option_to_c_string; +use crate::impls::StringToCString; pub(crate) fn parse_coff( file_name: &str, @@ -19,17 +21,17 @@ pub(crate) fn parse_coff( let is_64 = coff.header.characteristics & IMAGE_FILE_32BIT_MACHINE != IMAGE_FILE_32BIT_MACHINE; let is_stripped = coff.header.characteristics & IMAGE_FILE_DEBUG_STRIPPED == IMAGE_FILE_DEBUG_STRIPPED; - let cpu_type = StringPtr::from(PE_ARCH.get(&coff.header.machine)).0; + let cpu_type = option_to_c_string(PE_ARCH.get(&coff.header.machine)); debug_objects(file_name, member_names, "a COFF binary", debugging); ULDDObjResult { error: ParsingError::default(), obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), - executable_format: StringPtr::from("COFF").0, + executable_format: "COFF".to_c_string(), is_64, - os_type: StringPtr::from("Windows").0, - file_type: StringPtr::from("Windows object file").0, + os_type: "Windows".to_c_string(), + file_type: "Windows object file".to_c_string(), is_stripped, cpu_type, cpu_subtype: null_mut(), diff --git a/src/debug.rs b/src/debug.rs index 0e00ab0..6e3c111 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,16 +1,11 @@ -use goblin::error::Error as ObjectError; - +use std::ffi::c_char; +use std::fmt::Display; +use std::ptr::null_mut; +use crate::impls::StringToCString; use crate::structs::Debugging; -pub(crate) fn find_error_type(error: &ObjectError) -> i64 { - match error { - ObjectError::Malformed(_) => -1, - ObjectError::BadMagic(_) => -2, - ObjectError::Scroll(_) => -3, - ObjectError::BufferTooShort(_, _) => -4, - ObjectError::IO(_) => -5, - _ => -6, - } +pub(crate) fn option_to_c_string(option: Option) -> *mut c_char where T: Display { + option.map(|v| v.to_c_string()).unwrap_or(null_mut()) } pub(crate) fn merge_members(member_names: &mut [&str]) -> String { diff --git a/src/elf.rs b/src/elf.rs old mode 100755 new mode 100644 index 51e9f38..599909a --- a/src/elf.rs +++ b/src/elf.rs @@ -2,10 +2,12 @@ use std::ptr::null_mut; use crate::{ debug::debug_objects, - structs::{CharVec, ParsingError, StringPtr, ULDDObj, ULDDObjResult}, + structs::{CharVec, ParsingError, ULDDObj, ULDDObjResult}, types::{ElfFileType, ElfOS, E_MACHINE, E_TYPE}, }; use goblin::elf::Elf; +use crate::debug::option_to_c_string; +use crate::impls::StringToCString; fn find_os_from_strtab_elf(elf: &Elf<'_>, pat: &[&str]) -> bool { [ @@ -59,7 +61,7 @@ fn find_os_elf(elf: &Elf<'_>, os_abi: u8) -> (ElfOS, *mut i8) { } }; - (os, StringPtr::from(os.to_string()).0) + (os, os.to_c_string()) } fn find_linux_vdso(e_machine: u16, bit_type: bool) -> Option<&'static str> { @@ -105,21 +107,21 @@ pub(crate) fn parse_elf( debugging: bool, ) -> ULDDObjResult { let mut elf = elf; - let cpu_type = StringPtr::from(E_MACHINE.get(&elf.header.e_machine)).0; + let cpu_type = option_to_c_string(E_MACHINE.get(&elf.header.e_machine)); let file_type = match E_TYPE.get(&elf.header.e_type) { _ if elf.header.e_type == 0x03 && elf.interpreter.is_some() => { - StringPtr::from(ElfFileType::Executable.to_string()).0 + ElfFileType::Executable.to_c_string() } - rest => StringPtr::from(rest).0, + rest => option_to_c_string(rest), }; - let interpreter = StringPtr::from(elf.interpreter).0; + let interpreter = option_to_c_string(elf.interpreter); debug_objects(file_name, member_names, "an ELF binary", debugging); ULDDObjResult { error: ParsingError::default(), obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), - executable_format: StringPtr::from("ELF").0, + executable_format: "ELF".to_c_string(), is_64: elf.is_64, os_type: find_os_elf(&elf, os_abi).1, file_type, diff --git a/src/impls.rs b/src/impls.rs old mode 100755 new mode 100644 index 9e4b11f..7c7f7e0 --- a/src/impls.rs +++ b/src/impls.rs @@ -1,10 +1,23 @@ use crate::{ - structs::{CharVec, Debugging, ParsingError, StringPtr, ULDDObj}, + structs::{CharVec, Debugging, ParsingError, ULDDObj}, ULDDObjResult, ULDDObjResultVec, }; use anstream::{eprintln as a_eprintln, println as a_println}; use owo_colors::OwoColorize; -use std::{fmt::Display, mem::ManuallyDrop, ptr::null_mut, ffi::{c_char, CString}}; +use std::{ + ffi::{c_char, CString}, + fmt::Display, + mem::ManuallyDrop, + ptr::null_mut, +}; + +pub trait StringToCString { + fn to_c_string(self) -> *mut c_char; +} + +pub trait ErrorToInt { + fn to_int(&self) -> i64; +} impl From> for CharVec { fn from(value: Vec<*mut c_char>) -> Self { @@ -52,7 +65,7 @@ impl From> for CharVec { CString::from_vec_unchecked(item.to_string().into_bytes()).into_raw() }) .collect(); - + CharVec::from(vector) } } @@ -65,14 +78,17 @@ impl From<&mut Vec<&str>> for CharVec { CString::from_vec_unchecked(item.to_string().into_bytes()).into_raw() }) .collect(); - + CharVec::from(vector) } } -impl From for StringPtr { - fn from(value: String) -> Self { - let mut value = value; +impl StringToCString for T +where + T: Display, +{ + fn to_c_string(self) -> *mut c_char { + let mut value = self.to_string(); value.push('\0'); let c_string = match CString::from_vec_with_nul(value.into_bytes()) { Ok(string) => string, @@ -81,25 +97,20 @@ impl From for StringPtr { panic!("{}", error) } }; - StringPtr(c_string.into_raw()) + c_string.into_raw() } } -impl From<&str> for StringPtr { - fn from(value: &str) -> Self { - StringPtr::from(value.to_owned()) - } -} - -impl From> for StringPtr -where - T: Display, -{ - fn from(value: Option) -> Self { - let Some(t) = value else { - return StringPtr(null_mut()); - }; - StringPtr::from(t.to_string()) +impl ErrorToInt for goblin::error::Error { + fn to_int(&self) -> i64 { + match self { + goblin::error::Error::Malformed(_) => -1, + goblin::error::Error::BadMagic(_) => -2, + goblin::error::Error::Scroll(_) => -3, + goblin::error::Error::BufferTooShort(_, _) => -4, + goblin::error::Error::IO(_) => -5, + _ => -6, + } } } diff --git a/src/lib.rs b/src/lib.rs old mode 100755 new mode 100644 index c8ee01a..1300220 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ //! use archive::parse_archive; use coff::parse_coff; -use debug::{find_error_type, merge_members}; +use debug::merge_members; use elf::parse_elf; use goblin::Object; use mach::parse_mach; @@ -38,8 +38,10 @@ use owo_colors::OwoColorize; use pe::parse_pe; use std::ffi::{c_char, CStr, CString}; use structs::{ - CharVec, Debugging, ParsingError, StringPtr, ULDDObj, ULDDObjResult, ULDDObjResultVec, + CharVec, Debugging, ParsingError, ULDDObj, ULDDObjResult, ULDDObjResultVec, }; +use crate::impls::{ErrorToInt, StringToCString}; + #[doc(hidden)] pub mod archive; #[doc(hidden)] @@ -101,10 +103,10 @@ fn parse_objects<'a>( objects.push(ULDDObjResult { error: ParsingError { code: magic_number as i64, - explanation: StringPtr::from(msg).0, + explanation: msg.to_c_string(), }, obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), ..Default::default() }, @@ -128,10 +130,10 @@ fn parse_objects<'a>( objects.push(ULDDObjResult { error: ParsingError { code: -7, - explanation: StringPtr::from(msg).0, + explanation: msg.to_c_string(), }, obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), ..Default::default() }, @@ -149,11 +151,11 @@ fn parse_objects<'a>( objects.push(ULDDObjResult { error: ParsingError { - code: find_error_type(&error), - explanation: StringPtr::from(error.to_string()).0, + code: error.to_int(), + explanation: error.to_c_string(), }, obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), ..Default::default() }, @@ -225,7 +227,7 @@ unsafe fn drop_c_string(ptr: *mut i8) { /// /// # Safety /// -/// This function is designed for deallocating [`ULDDObjResultVec`] created by rust. Trying to deallocating [`ULDDObjResultVec`] created by other languages may result with errors. +/// This function is designed for deallocating [`ULDDObjResultVec`] created by rust. Trying to deallocate [`ULDDObjResultVec`] created by other languages may result with errors. /// /// It is null pointer-safe. /// diff --git a/src/mach.rs b/src/mach.rs old mode 100755 new mode 100644 index ec57d7b..539c82e --- a/src/mach.rs +++ b/src/mach.rs @@ -1,6 +1,6 @@ use crate::{ - debug::{debug_objects, find_error_type, merge_members}, - structs::{CharVec, Debugging, ParsingError, StringPtr, ULDDObj, ULDDObjResult}, + debug::{debug_objects, merge_members}, + structs::{CharVec, Debugging, ParsingError, ULDDObj, ULDDObjResult}, types::{ MachOCpuType, MachOOs, MACH_O_ARM_CPU_SUBTYPE, MACH_O_CPUTYPE, MACH_O_FILE_TYPE, MACH_O_X86_CPU_SUBTYPE, @@ -8,6 +8,8 @@ use crate::{ }; use goblin::mach::{load_command::CommandVariant::BuildVersion, Mach, MachO}; use std::ptr::null_mut; +use crate::debug::option_to_c_string; +use crate::impls::{ErrorToInt, StringToCString}; fn find_os_mach(mach: &MachO<'_>) -> *mut i8 { for lc in &mach.load_commands { @@ -27,7 +29,7 @@ fn find_os_mach(mach: &MachO<'_>) -> *mut i8 { 0x0C => MachOOs::AppleVisionProSimulator, _ => return null_mut(), }; - return StringPtr::from(os.to_string()).0; + return os.to_c_string(); } } @@ -100,13 +102,13 @@ pub(crate) fn parse_mach<'a>( return objects.push(ULDDObjResult { error: ParsingError { - code: find_error_type(&error), - explanation: StringPtr::from(error.to_string()).0, + code: error.to_int(), + explanation: error.to_c_string(), }, obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), - executable_format: StringPtr::from("Mach-O").0, + executable_format: "Mach-O".to_c_string(), ..Default::default() }, }); @@ -129,13 +131,13 @@ pub(crate) fn parse_mach<'a>( error)).print(debugging); objects.push(ULDDObjResult { error: ParsingError { - code: find_error_type(&error), - explanation: StringPtr::from(error.to_string()).0, + code: error.to_int(), + explanation: error.to_c_string(), }, obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names.clone()), - executable_format: StringPtr::from("Mach-O").0, + executable_format: "Mach-O".to_c_string(), ..Default::default() }, }) @@ -156,22 +158,22 @@ fn parse_mach_o( debugging: bool, ) -> ULDDObjResult { let mut mach_o = mach_o; - let file_type = StringPtr::from(MACH_O_FILE_TYPE.get(&mach_o.header.filetype)).0; + let file_type = option_to_c_string(MACH_O_FILE_TYPE.get(&mach_o.header.filetype)); let (cpu_type, cpu_subtype) = { if let Some(mach_o_cpu_type) = MACH_O_CPUTYPE.get(&mach_o.header.cputype) { let mach_o_cpu_subtype = { match mach_o_cpu_type { MachOCpuType::ARM | MachOCpuType::ARM64 => { - StringPtr::from(MACH_O_ARM_CPU_SUBTYPE.get(&mach_o.header.cpusubtype)).0 + option_to_c_string(MACH_O_ARM_CPU_SUBTYPE.get(&mach_o.header.cpusubtype)) } MachOCpuType::X86 | MachOCpuType::X86_64 => { - StringPtr::from(MACH_O_X86_CPU_SUBTYPE.get(&mach_o.header.cpusubtype)).0 + option_to_c_string(MACH_O_X86_CPU_SUBTYPE.get(&mach_o.header.cpusubtype)) } _ => null_mut(), } }; ( - StringPtr::from(mach_o_cpu_type.to_string()).0, + mach_o_cpu_type.to_c_string(), mach_o_cpu_subtype, ) } else { @@ -190,9 +192,9 @@ fn parse_mach_o( ULDDObjResult { error: ParsingError::default(), obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), - executable_format: StringPtr::from("Mach-O").0, + executable_format: "Mach-O".to_c_string(), is_64: mach_o.is_64, os_type: find_os_mach(&mach_o), file_type, diff --git a/src/pe.rs b/src/pe.rs old mode 100755 new mode 100644 index 37ad564..8933805 --- a/src/pe.rs +++ b/src/pe.rs @@ -1,10 +1,12 @@ use crate::{ debug::debug_objects, - structs::{CharVec, ParsingError, StringPtr, ULDDObj, ULDDObjResult}, + structs::{CharVec, ParsingError, ULDDObj, ULDDObjResult}, types::{PeOS, PeSubsystem, PE_ARCH, PE_SUBSYSTEM}, }; use goblin::pe::{characteristic::IMAGE_FILE_DEBUG_STRIPPED, PE}; use std::ptr::null_mut; +use crate::debug::option_to_c_string; +use crate::impls::StringToCString; fn find_os_pe(pe: &PE<'_>) -> *mut i8 { let Some(optional_header) = pe @@ -32,7 +34,7 @@ fn find_os_pe(pe: &PE<'_>) -> *mut i8 { PeSubsystem::Unknown => return null_mut(), }; - StringPtr::from(os.to_string()).0 + os.to_c_string() } pub(crate) fn parse_pe( @@ -43,7 +45,7 @@ pub(crate) fn parse_pe( ) -> ULDDObjResult { let is_stripped = pe.header.coff_header.characteristics & IMAGE_FILE_DEBUG_STRIPPED == IMAGE_FILE_DEBUG_STRIPPED; - let cpu_type = StringPtr::from(PE_ARCH.get(&pe.header.coff_header.machine)).0; + let cpu_type = option_to_c_string(PE_ARCH.get(&pe.header.coff_header.machine)); let file_type = pe .header .optional_header @@ -57,27 +59,27 @@ pub(crate) fn parse_pe( .windows_fields .minor_operating_system_version; let linker_version = format!("{}.{}", linker_major_version, linker_minor_version); - StringPtr::from(linker_version).0 + linker_version.to_c_string() } else { null_mut() } }; let executable_format = if pe.is_64 { debug_objects(file_name, member_names, "a PE32+ binary", debugging); - StringPtr::from("PE32+").0 + "PE32+".to_c_string() } else { debug_objects(file_name, member_names, "a PE32 binary", debugging); - StringPtr::from("PE32").0 + "PE32".to_c_string() }; ULDDObjResult { error: ParsingError::default(), obj: ULDDObj { - file_name: StringPtr::from(file_name).0, + file_name: file_name.to_c_string(), member_name: CharVec::from(member_names), executable_format, is_64: pe.is_64, os_type: find_os_pe(&pe), - file_type: StringPtr::from(file_type).0, + file_type: option_to_c_string(file_type), is_stripped, cpu_type, cpu_subtype: null_mut(), diff --git a/src/structs.rs b/src/structs.rs old mode 100755 new mode 100644 index e41ad1b..40d0d75 --- a/src/structs.rs +++ b/src/structs.rs @@ -99,9 +99,6 @@ pub struct ULDDObjResultVec { pub vec: *mut ULDDObjResult, } -#[doc(hidden)] -pub struct StringPtr(pub *mut i8); - #[doc(hidden)] pub(crate) enum Debugging { Info(String), diff --git a/src/types.rs b/src/types.rs old mode 100755 new mode 100644