Skip to content

Commit 211e411

Browse files
committed
rust: check literal does not contain NUL in c_str!
Suggested-by: Wedson Almeida Filho <[email protected]> Signed-off-by: Gary Guo <[email protected]>
1 parent 6bc199b commit 211e411

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

rust/kernel/str.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,36 @@ impl CStr {
9191
///
9292
/// The provided slice must be `NUL`-terminated, does not contain any
9393
/// interior `NUL` bytes.
94-
pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, CStrConvertError> {
94+
pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, CStrConvertError> {
9595
if bytes.is_empty() {
9696
return Err(CStrConvertError::NotNulTerminated);
9797
}
9898
if bytes[bytes.len() - 1] != 0 {
9999
return Err(CStrConvertError::NotNulTerminated);
100100
}
101-
if bytes[..bytes.len()].contains(&0) {
102-
return Err(CStrConvertError::InteriorNul);
101+
let mut i = 0;
102+
while i < bytes.len() - 1 {
103+
if bytes[i] == 0 {
104+
return Err(CStrConvertError::InteriorNul);
105+
}
106+
i += 1;
103107
}
104108
// SAFETY: We just checked that all properties hold.
105109
Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
106110
}
107111

112+
/// Creates a [`CStr`] from a `[u8]`, panic if input is not valid.
113+
///
114+
/// This function is only meant to be used by `c_str!` macro, so
115+
/// crates using `c_str!` macro don't have to enable `const_panic` feature.
116+
#[doc(hidden)]
117+
pub const fn from_bytes_with_nul_unwrap(bytes: &[u8]) -> &Self {
118+
match Self::from_bytes_with_nul(bytes) {
119+
Ok(v) => v,
120+
Err(_) => panic!("string contains interior NUL"),
121+
}
122+
}
123+
108124
/// Creates a [`CStr`] from a `[u8]` without performing any additional
109125
/// checks.
110126
///
@@ -220,10 +236,8 @@ where
220236
#[macro_export]
221237
macro_rules! c_str {
222238
($str:literal) => {{
223-
// FIXME: Check that `$str` does not contain interior `NUL`.
224239
const S: &str = concat!($str, "\0");
225-
const C: &$crate::str::CStr =
226-
{ unsafe { $crate::str::CStr::from_bytes_with_nul_unchecked(S.as_bytes()) } };
240+
const C: &$crate::str::CStr = $crate::str::CStr::from_bytes_with_nul_unwrap(S.as_bytes());
227241
C
228242
}};
229243
}

0 commit comments

Comments
 (0)