Skip to content

Commit 897fc9f

Browse files
committed
Use CStr::from_bytes_with_nul for validation of appended bytes
1 parent ce6d252 commit 897fc9f

File tree

1 file changed

+10
-16
lines changed

1 file changed

+10
-16
lines changed

src/c_string.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::{
55
borrow::Borrow,
66
cmp::Ordering,
77
error::Error,
8-
ffi::{c_char, CStr},
8+
ffi::{c_char, CStr, FromBytesWithNulError},
99
fmt,
1010
ops::Deref,
1111
};
@@ -18,14 +18,6 @@ pub struct CString<const N: usize> {
1818
inner: Vec<u8, N>,
1919
}
2020

21-
/// Naive implementation for `memchr`.
22-
///
23-
/// TODO Consider using [the `memchr` crate](https://github.com/BurntSushi/memchr), which
24-
/// provides a heavily optimized `memchr` function.
25-
fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
26-
haystack.iter().position(|&byte| byte == needle)
27-
}
28-
2921
impl<const N: usize> CString<N> {
3022
/// Creates a new C-compatible string with a terminating nul byte.
3123
///
@@ -181,15 +173,17 @@ impl<const N: usize> CString<N> {
181173
return Err(CapacityError.into());
182174
}
183175

184-
match memchr(0, bytes) {
185-
Some(index) if index + 1 == bytes.len() => {
176+
match CStr::from_bytes_with_nul(bytes) {
177+
Ok(_) => {
186178
// SAFETY: A string is left in a valid state because appended bytes are nul-terminated.
187179
unsafe { self.extend_from_bytes_unchecked(bytes) }?;
188180

189181
Ok(())
190182
}
191-
Some(index) => Err(ExtendError::InteriorNulByte(index)),
192-
None => {
183+
Err(FromBytesWithNulError::InteriorNul { position }) => {
184+
Err(ExtendError::InteriorNul { position })
185+
}
186+
Err(FromBytesWithNulError::NotNulTerminated) => {
193187
// Because given bytes has no nul byte anywhere, we insert the bytes and
194188
// then add the nul byte terminator.
195189
//
@@ -346,7 +340,7 @@ pub enum ExtendError {
346340
/// The capacity of the [`CString`] is too small.
347341
Capacity(CapacityError),
348342
/// An invalid interior nul byte found in a given byte slice.
349-
InteriorNulByte(usize),
343+
InteriorNul { position: usize },
350344
}
351345

352346
impl Error for ExtendError {}
@@ -355,7 +349,7 @@ impl fmt::Display for ExtendError {
355349
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356350
match self {
357351
Self::Capacity(error) => write!(f, "{error}"),
358-
Self::InteriorNulByte(index) => write!(f, "interior nul byte at {index}"),
352+
Self::InteriorNul { position } => write!(f, "interior nul byte at {position}"),
359353
}
360354
}
361355
}
@@ -403,7 +397,7 @@ mod tests {
403397
// Call must fail since `w\0rld` contains an interior nul byte.
404398
assert!(matches!(
405399
c_string.extend_from_bytes(b"w\0rld"),
406-
Err(ExtendError::InteriorNulByte(1))
400+
Err(ExtendError::InteriorNul(1))
407401
));
408402

409403
// However, the call above _must not_ have invalidated the state of our CString

0 commit comments

Comments
 (0)