Skip to content

Commit b898b81

Browse files
committed
fix(sys): crash when getting &str from empty ngx_str_t
A zero-length `ngx_str_t` is still valid, but the data pointer is not guaranteed to be valid or initialized in that case.
1 parent e6077eb commit b898b81

File tree

1 file changed

+35
-4
lines changed

1 file changed

+35
-4
lines changed

nginx-sys/src/lib.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,50 @@ pub unsafe fn str_to_uchar(pool: *mut ngx_pool_t, data: &str) -> *mut u_char {
7575
}
7676

7777
impl ngx_str_t {
78+
/// Returns the contents of this `ngx_str_t` as a byte slice.
79+
///
80+
/// The returned slice will **not** contain the optional nul terminator that `ngx_str_t.data`
81+
/// may have.
82+
#[inline]
83+
pub fn as_bytes(&self) -> &[u8] {
84+
if self.is_empty() {
85+
&[]
86+
} else {
87+
// SAFETY: `ngx_str_t` with non-zero len must contain a valid correctly aligned pointer
88+
unsafe { slice::from_raw_parts(self.data, self.len) }
89+
}
90+
}
91+
92+
/// Returns the contents of this `ngx_str_t` as a mutable byte slice.
93+
#[inline]
94+
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
95+
if self.is_empty() {
96+
&mut []
97+
} else {
98+
// SAFETY: `ngx_str_t` with non-zero len must contain a valid correctly aligned pointer
99+
unsafe { slice::from_raw_parts_mut(self.data, self.len) }
100+
}
101+
}
102+
103+
/// Returns `true` if the string has a length of 0.
104+
#[inline]
105+
pub fn is_empty(&self) -> bool {
106+
self.len == 0
107+
}
108+
78109
/// Convert the nginx string to a string slice (`&str`).
79110
///
80111
/// # Safety
81112
/// This function is marked as unsafe because it involves raw pointer manipulation.
82113
/// It assumes that the underlying `data` pointer is valid and points to a valid UTF-8 encoded string.
83114
///
115+
/// # Panics
116+
/// This function panics if the `ngx_str_t` is not valid UTF-8.
117+
///
84118
/// # Returns
85119
/// A string slice (`&str`) representing the nginx string.
86120
pub fn to_str(&self) -> &str {
87-
unsafe {
88-
let slice = slice::from_raw_parts(self.data, self.len);
89-
return std::str::from_utf8(slice).unwrap();
90-
}
121+
std::str::from_utf8(self.as_bytes()).unwrap()
91122
}
92123

93124
/// Create an `ngx_str_t` instance from a `String`.

0 commit comments

Comments
 (0)