From e3998212eda8d8f51523dfbe24df3638a4a8c9d1 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 1 Oct 2025 11:50:08 +0100 Subject: [PATCH] Fix string data conversion in ErrorStack::put() --- boring/src/error.rs | 56 +++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/boring/src/error.rs b/boring/src/error.rs index 60d8d4f5..5c1ad40b 100644 --- a/boring/src/error.rs +++ b/boring/src/error.rs @@ -20,6 +20,7 @@ use openssl_macros::corresponds; use std::borrow::Cow; use std::error; use std::ffi::CStr; +use std::ffi::CString; use std::fmt; use std::io; use std::ptr; @@ -58,7 +59,7 @@ impl ErrorStack { /// Used to report errors from the Rust crate #[cold] pub(crate) fn internal_error(err: impl error::Error) -> Self { - Self(vec![Error::new_internal(err.to_string())]) + Self(vec![Error::new_internal(Data::String(err.to_string()))]) } /// Empties the current thread's error queue. @@ -122,7 +123,14 @@ pub struct Error { code: c_uint, file: *const c_char, line: c_uint, - data: Option>, + data: Data, +} + +#[derive(Clone)] +enum Data { + None, + CString(CString), + String(String), } unsafe impl Sync for Error {} @@ -148,11 +156,9 @@ impl Error { // The memory referenced by data is only valid until that slot is overwritten // in the error stack, so we'll need to copy it off if it's dynamic let data = if flags & ffi::ERR_FLAG_STRING != 0 { - Some(Cow::Owned( - CStr::from_ptr(data.cast()).to_string_lossy().into_owned(), - )) + Data::CString(CStr::from_ptr(data.cast()).to_owned()) } else { - None + Data::None }; Some(Error { code, @@ -176,22 +182,8 @@ impl Error { self.file, self.line, ); - let ptr = match self.data { - Some(Cow::Borrowed(data)) => Some(data.as_ptr() as *mut c_char), - Some(Cow::Owned(ref data)) => { - let ptr = ffi::OPENSSL_malloc((data.len() + 1) as _) as *mut c_char; - if ptr.is_null() { - None - } else { - ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len()); - *ptr.add(data.len()) = 0; - Some(ptr) - } - } - None => None, - }; - if let Some(ptr) = ptr { - ffi::ERR_add_error_data(1, ptr); + if let Some(cstr) = self.data_cstr() { + ffi::ERR_set_error_data(cstr.as_ptr().cast_mut(), ffi::ERR_FLAG_STRING); } } } @@ -297,15 +289,29 @@ impl Error { /// Returns additional data describing the error. #[must_use] pub fn data(&self) -> Option<&str> { - self.data.as_deref() + match &self.data { + Data::None => None, + Data::CString(cstring) => cstring.to_str().ok(), + Data::String(s) => Some(s), + } } - fn new_internal(msg: String) -> Self { + #[must_use] + fn data_cstr(&self) -> Option> { + let s = match &self.data { + Data::None => return None, + Data::CString(cstr) => return Some(Cow::Borrowed(cstr)), + Data::String(s) => s.as_str(), + }; + CString::new(s).ok().map(Cow::Owned) + } + + fn new_internal(msg: Data) -> Self { Self { code: ffi::ERR_PACK(ffi::ERR_LIB_NONE.0 as _, 0, 0) as _, file: BORING_INTERNAL.as_ptr(), line: 0, - data: Some(msg.into()), + data: msg, } }