Skip to content

Commit 65d1676

Browse files
committed
Clear buffer before recursive panics
Add some docstrings Signed-off-by: adamperlin <[email protected]>
1 parent 7ab4735 commit 65d1676

File tree

2 files changed

+36
-23
lines changed

2 files changed

+36
-23
lines changed

src/hyperlight_common/src/fixed_buf.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use core::fmt;
22
use core::result::Result;
33
use core::ffi::{CStr, FromBytesUntilNulError};
44

5+
/// FixedStringBuf is a buffer that can hold a fixed-size string.
6+
/// It is meant to be used with a slice that the user has pre-allocated
7+
/// to avoid extra allocations during string formatting.
58
pub struct FixedStringBuf<'a> {
69
pub buf: &'a mut [u8],
710
pub pos: usize,
@@ -10,7 +13,7 @@ pub struct FixedStringBuf<'a> {
1013
impl<'a> fmt::Write for FixedStringBuf<'a> {
1114
fn write_str(&mut self, s: &str) -> fmt::Result {
1215
// we always reserve 1 byte for the null terminator,
13-
// as the buffer must be convertible to a CStr.
16+
// as the buffer must be convertible to CStr.
1417
let buf_end = self.buf.len() - 1;
1518
if self.pos + s.len() > buf_end {
1619
return Err(fmt::Error)
@@ -35,10 +38,17 @@ impl <'a> FixedStringBuf<'a> {
3538
}
3639
}
3740

41+
pub fn reset(&mut self) {
42+
self.pos = 0;
43+
}
44+
45+
/// Null terminates the underlying buffer,
46+
/// and converts to a CStr which borrows the underlying buffer's slice.
3847
pub fn as_c_str(&mut self) -> Result<&CStr, FromBytesUntilNulError> {
39-
// null terminate buffer.
48+
// null terminate the buffer.
4049
// we are guaranteed to have enough space since we always reserve one extra
41-
// byte for null in write_str
50+
// byte for null in write_str, and assert buf.len() > 0 in the constructor.
51+
assert!(self.buf.len() > 0 && self.pos < self.buf.len());
4252
self.buf[self.pos] = 0;
4353
CStr::from_bytes_until_nul(&self.buf[..self.pos + 1])
4454
}

src/hyperlight_guest_bin/src/lib.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use hyperlight_guest::exit::{abort_with_code_and_message, halt};
3636
use hyperlight_guest::guest_handle::handle::GuestHandle;
3737
use hyperlight_guest_tracing::{trace, trace_function};
3838
use log::LevelFilter;
39-
use spin::{Once};
39+
use spin::{Once, Mutex, MutexGuard};
4040

4141
// === Modules ===
4242
#[cfg(target_arch = "x86_64")]
@@ -144,34 +144,37 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
144144
_panic_handler(info)
145145
}
146146

147-
148147
static mut PANIC_MSG: [u8; 512] = [0u8; 512];
149148

150149
#[allow(static_mut_refs)]
151-
static mut PANIC_BUF: FixedStringBuf = FixedStringBuf{
150+
static PANIC_BUF: Mutex<FixedStringBuf> = Mutex::new(FixedStringBuf{
152151
buf: unsafe { &mut PANIC_MSG },
153152
pos: 0,
154-
};
155-
153+
});
156154

157155
#[inline(always)]
158-
#[allow(static_mut_refs)]
159156
fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
160-
let panic_buf: &mut FixedStringBuf = unsafe { &mut PANIC_BUF };
161-
write!(panic_buf, "{}", info).expect("panic: message format failed");
162-
163-
// create a CStr from the underlying array in panic_buf.
164-
// Note that we do NOT use CString here to avoid allocating
165-
let c_string = panic_buf.as_c_str().expect("panic: failed to convert to CStr");
166-
unsafe { abort_with_code_and_message(&[ErrorCode::UnknownError as u8], c_string.as_ptr()) }
167-
}
168-
169-
fn _panic_handler_old(info: &core::panic::PanicInfo) {
170-
let msg = info.to_string();
171-
let c_string = alloc::ffi::CString::new(msg)
172-
.unwrap_or_else(|_| alloc::ffi::CString::new("panic (invalid utf8)").unwrap());
157+
let mut panic_buf_guard: MutexGuard<'_, FixedStringBuf<'static>> = PANIC_BUF.lock();
158+
let write_res = write!(panic_buf_guard, "{}", info);
159+
if let Err(_) = write_res {
160+
// reset the buffer to ensure there is space
161+
// for the new panic message below
162+
panic_buf_guard.reset();
163+
panic!("panic: message format failed");
164+
}
173165

174-
unsafe { abort_with_code_and_message(&[ErrorCode::UnknownError as u8], c_string.as_ptr()) }
166+
// create a CStr from the underlying array in PANIC_BUF using the as_cstr method.
167+
// this wraps CStr::from_bytes_until_nul which takes a borrowed byte slice
168+
// and does not allocate.
169+
let c_string_res = panic_buf_guard.as_c_str();
170+
if let Err(_) = c_string_res {
171+
// reset the buffer here as well, to ensure there is space
172+
// in the buffer to write the new panic message below.
173+
panic_buf_guard.reset();
174+
panic!("panic: failed to convert to CStr");
175+
}
176+
177+
unsafe { abort_with_code_and_message(&[ErrorCode::UnknownError as u8], c_string_res.unwrap().as_ptr()) }
175178
}
176179

177180
// === Entrypoint ===

0 commit comments

Comments
 (0)