diff --git a/src/dc_strencode.rs b/src/dc_strencode.rs index e445b653b..b6d6d4e22 100644 --- a/src/dc_strencode.rs +++ b/src/dc_strencode.rs @@ -245,23 +245,18 @@ unsafe fn quote_word( // col = (*mmapstr).len as libc::c_int; cur = word; while i < size { - let mut do_quote_char: libc::c_int = 0; - match *cur as libc::c_int { - 44 | 58 | 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126 - | 61 | 63 | 95 => do_quote_char = 1i32, + let mut do_quote_char = false; + match *cur as u8 as char { + ',' | ':' | '!' | '"' | '#' | '$' | '@' | '[' | '\\' | ']' | '^' | '`' | '{' | '|' + | '}' | '~' | '=' | '?' | '_' => do_quote_char = true, _ => { - if *cur as libc::c_uchar as libc::c_int >= 128i32 { - do_quote_char = 1i32 + if *cur as u8 >= 128 { + do_quote_char = true; } } } - if 0 != do_quote_char { - snprintf( - hex.as_mut_ptr(), - 4, - b"=%2.2X\x00" as *const u8 as *const libc::c_char, - *cur as libc::c_uchar as libc::c_int, - ); + if do_quote_char { + print_hex(hex.as_mut_ptr(), cur); if mmap_string_append(mmapstr, hex.as_mut_ptr()).is_null() { return false; } @@ -716,6 +711,15 @@ pub unsafe fn dc_decode_ext_header(to_decode: *const libc::c_char) -> *mut libc: }; } +unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) { + assert!(!target.is_null()); + assert!(!cur.is_null()); + + let bytes = std::slice::from_raw_parts(cur as *const _, strlen(cur)); + let raw = to_cstring(format!("={}", &hex::encode_upper(bytes)[..2])); + libc::memcpy(target as *mut _, raw.as_ptr() as *const _, 4); +} + #[cfg(test)] mod tests { use super::*; @@ -882,4 +886,16 @@ mod tests { ); } } + + #[test] + fn test_print_hex() { + let mut hex: [libc::c_char; 4] = [0; 4]; + let cur = b"helloworld" as *const u8 as *const libc::c_char; + unsafe { print_hex(hex.as_mut_ptr(), cur) }; + assert_eq!(to_string(hex.as_ptr() as *const _), "=68"); + + let cur = b":" as *const u8 as *const libc::c_char; + unsafe { print_hex(hex.as_mut_ptr(), cur) }; + assert_eq!(to_string(hex.as_ptr() as *const _), "=3A"); + } } diff --git a/src/dc_tools.rs b/src/dc_tools.rs index 6385d15a6..9379607f7 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -243,28 +243,13 @@ pub unsafe fn dc_null_terminate( } pub unsafe fn dc_binary_to_uc_hex(buf: *const uint8_t, bytes: size_t) -> *mut libc::c_char { - let mut hex: *mut libc::c_char = 0 as *mut libc::c_char; - let mut i; - if !(buf.is_null() || bytes <= 0) { - hex = calloc( - ::std::mem::size_of::(), - bytes.wrapping_mul(2).wrapping_add(1), - ) as *mut libc::c_char; - if !hex.is_null() { - i = 0; - while i < bytes { - snprintf( - &mut *hex.offset((i * 2) as isize) as *mut libc::c_char, - 3, - b"%02X\x00" as *const u8 as *const libc::c_char, - *buf.offset(i as isize) as libc::c_int, - ); - i += 1 - } - } + if buf.is_null() || bytes == 0 { + return std::ptr::null_mut(); } - hex + let buf = std::slice::from_raw_parts(buf, bytes); + let raw = hex::encode_upper(buf); + strdup(to_cstring(raw).as_ptr()) } /* remove all \r characters from string */ @@ -1820,4 +1805,15 @@ mod tests { free(str as *mut libc::c_void); } } + + #[test] + fn test_dc_binary_to_uc_hex() { + let buf = vec![0, 1, 2, 3, 255]; + + let raw = unsafe { dc_binary_to_uc_hex(buf.as_ptr(), buf.len()) }; + let res = to_string(raw); + assert_eq!(res, "00010203FF"); + + unsafe { free(raw as *mut _) }; + } } diff --git a/src/x.rs b/src/x.rs index ac9703532..0d1643b1c 100644 --- a/src/x.rs +++ b/src/x.rs @@ -1,4 +1,5 @@ use crate::dc_strbuilder::dc_strbuilder_t; +use crate::dc_tools::*; use crate::types::*; pub use libc::{ @@ -8,16 +9,30 @@ pub use libc::{ }; pub unsafe fn strdup(s: *const libc::c_char) -> *mut libc::c_char { - let slen = libc::strlen(s); - let result = libc::malloc(slen + 1); + if s.is_null() { + return std::ptr::null_mut(); + } + + let slen = strlen(s); + let result = malloc(slen + 1); if result.is_null() { return std::ptr::null_mut(); } - libc::memcpy(result, s as *const _, slen + 1); + memcpy(result, s as *const _, slen + 1); result as *mut _ } +pub fn strndup(s: *const libc::c_char, n: libc::c_ulong) -> *mut libc::c_char { + if s.is_null() { + return std::ptr::null_mut(); + } + + let s_r = to_str(s); + let end = std::cmp::min(n as usize, s_r.len()); + unsafe { strdup(to_cstring(&s_r[..end]).as_ptr()) } +} + extern "C" { pub fn clock() -> libc::clock_t; pub fn qsort( @@ -29,7 +44,6 @@ extern "C" { >, ); pub fn pow(_: libc::c_double, _: libc::c_double) -> libc::c_double; - pub fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char; pub fn strftime( _: *mut libc::c_char, _: size_t, @@ -59,23 +73,12 @@ extern "C" { _: *const libc::c_char, ) -> !; - #[cfg(windows)] - pub(crate) fn snprintf( - s: *mut libc::c_char, - n: libc::size_t, - format: *const libc::c_char, - _: ... - ) -> libc::c_int; - // -- DC Methods pub fn dc_strbuilder_catf(_: *mut dc_strbuilder_t, format: *const libc::c_char, _: ...); pub fn dc_mprintf(format: *const libc::c_char, _: ...) -> *mut libc::c_char; } -#[cfg(not(windows))] -pub(crate) use libc::snprintf; - #[cfg(not(target_os = "macos"))] pub unsafe extern "C" fn __assert_rtn( a: *const libc::c_char, @@ -132,6 +135,7 @@ pub(crate) unsafe fn strncasecmp( #[cfg(test)] mod tests { use super::*; + use crate::dc_tools::to_string; #[test] fn test_atox() { @@ -140,4 +144,17 @@ mod tests { assert_eq!(atoi(b"\x00" as *const u8 as *const libc::c_char), 0); } } + + #[test] + fn test_strndup() { + unsafe { + let res = strndup(b"helloworld\x00" as *const u8 as *const libc::c_char, 4); + assert_eq!( + to_string(res), + to_string(b"hell\x00" as *const u8 as *const libc::c_char) + ); + assert_eq!(strlen(res), 4); + free(res as *mut _); + } + } }