diff --git a/src/buffer.rs b/src/buffer.rs index 7003ac9..0ca67fd 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -20,28 +20,40 @@ use crate::Result; use crate::ffi::MM; /// Copies a Rust string to a buffer, adding a terminating zero. -pub fn rust_str_to_c_str>(mm: MM, s: S) -> *mut c_char { +pub fn rust_str_to_c_str>(mm: MM, s: S) + -> Result<*mut c_char> +{ let malloc = mm.malloc; let s = s.as_ref(); let bytes = s.as_bytes(); unsafe { let buf = malloc(bytes.len() + 1); + if buf.is_null() { + return Err(Error::OutOfMemory("rust_bytes_to_c_str_lossy".into(), + bytes.len() + 1)); + }; copy_nonoverlapping(bytes.as_ptr(), buf as *mut _, bytes.len()); *((buf as *mut u8).add(bytes.len())) = 0; // Terminate. - buf as *mut c_char + Ok(buf as *mut c_char) } } /// Copies a C string to a buffer, adding a terminating zero. /// /// Replaces embedded zeros with '_'. -pub fn rust_bytes_to_c_str_lossy>(mm: MM, s: S) -> *mut c_char { +pub fn rust_bytes_to_c_str_lossy>(mm: MM, s: S) + -> Result<*mut c_char> +{ let malloc = mm.malloc; let bytes = s.as_ref(); unsafe { let buf = malloc(bytes.len() + 1); + if buf.is_null() { + return Err(Error::OutOfMemory("rust_bytes_to_c_str_lossy".into(), + bytes.len() + 1)); + }; copy_nonoverlapping(bytes.as_ptr(), buf as *mut _, bytes.len()); // Replace embedded zeros. @@ -50,7 +62,7 @@ pub fn rust_bytes_to_c_str_lossy>(mm: MM, s: S) -> *mut c_char { bytes_mut.iter_mut().for_each(|b| if *b == 0 { *b = b'_' }); *((buf as *mut u8).add(bytes.len())) = 0; // Terminate. - buf as *mut c_char + Ok(buf as *mut c_char) } } diff --git a/src/lib.rs b/src/lib.rs index b670b09..50d5a32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -803,13 +803,13 @@ ffi!(fn pgp_decrypt_and_verify(session: *mut Session, }); if ! filename_ptr.is_null() { - unsafe { filename_ptr.as_mut() }.map(|p| { + if let Some(p) = unsafe { filename_ptr.as_mut() } { if let Some(filename) = h.filename.as_ref() { - *p = rust_bytes_to_c_str_lossy(mm, filename); + *p = rust_bytes_to_c_str_lossy(mm, filename)?; } else { *p = ptr::null_mut(); } - }); + }; } // ********************************** diff --git a/src/pep/identity.rs b/src/pep/identity.rs index d0cc63e..bbc7a42 100644 --- a/src/pep/identity.rs +++ b/src/pep/identity.rs @@ -104,10 +104,13 @@ impl PepIdentity { panic!("Out of memory allocating a PepIdentity"); }; let ident = unsafe { &mut *(buffer as *mut Self) }; - ident.address = rust_str_to_c_str(mm, &template.address); - ident.fpr = rust_str_to_c_str(mm, &template.fpr.to_hex()); + ident.address = rust_str_to_c_str(mm, &template.address) + .expect("Out of memory allocating ident.address"); + ident.fpr = rust_str_to_c_str(mm, &template.fpr.to_hex()) + .expect("Out of memory allocating ident.fpr"); if let Some(username) = template.username.as_ref() { - ident.username = rust_str_to_c_str(mm, username); + ident.username = rust_str_to_c_str(mm, username) + .expect("Out of memory allocating ident.username"); } ident } @@ -140,7 +143,11 @@ impl PepIdentity { /// Replaces the fingerprint. pub fn set_fingerprint(&mut self, mm: MM, fpr: Fingerprint) { unsafe { libc::free(self.fpr as *mut _) }; - self.fpr = rust_str_to_c_str(mm, fpr.to_hex()); + // Clear to avoid a dangling pointers if the following + // allocation fails. + self.fpr = ptr::null_mut(); + self.fpr = rust_str_to_c_str(mm, fpr.to_hex()) + .expect("Out of memory allocating fingerprint"); } /// Returns the username (in RFC 2822 speak: the display name). diff --git a/src/pep/stringlist.rs b/src/pep/stringlist.rs index ba1d29e..784467f 100644 --- a/src/pep/stringlist.rs +++ b/src/pep/stringlist.rs @@ -52,7 +52,8 @@ impl StringListItem { fn new>(mm: MM, value: S, next: *mut Self) -> &'static mut Self { let item = Self::empty(mm); - item.value = rust_str_to_c_str(mm, value); + item.value = rust_str_to_c_str(mm, value) + .expect("Out of memory allocating StringListItem"); item.next = next; item @@ -184,7 +185,8 @@ impl StringList { if item.value.is_null() { // 2. head is not NULL, but head.value is NULL. - item.value = rust_str_to_c_str(mm, value); + item.value = rust_str_to_c_str(mm, value) + .expect("Out of memory allocating StringList.value"); } else { // 3. neither head nor head.value are NULL. assert!(item.next.is_null());