Use unsafe blocks in string.h implementation

This commit is contained in:
sourceturner
2026-01-16 22:15:53 +01:00
committed by sourceturner
parent b3f7db83cf
commit f72ecfd8dc
+94 -91
View File
@@ -54,7 +54,7 @@ pub unsafe extern "C" fn memchr(
needle: c_int,
len: size_t,
) -> *mut c_void {
let haystack = slice::from_raw_parts(haystack as *const u8, len as usize);
let haystack = unsafe { slice::from_raw_parts(haystack as *const u8, len as usize) };
match memchr::memchr(needle as u8, haystack) {
Some(index) => haystack[index..].as_ptr() as *mut c_void,
@@ -71,28 +71,28 @@ pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: usize)
for _ in 0..div {
// SAFETY: `s1` and `s2` are `*const c_void`, which only guarantees byte
// alignment. Hence `a` and `b` may be unaligned.
if a.read_unaligned() != b.read_unaligned() {
if unsafe { a.read_unaligned() } != unsafe { b.read_unaligned() } {
for i in 0..mem::size_of::<usize>() {
let c = *(a.cast::<u8>()).add(i);
let d = *(b.cast::<u8>()).add(i);
let c = unsafe { *(a.cast::<u8>()).add(i) };
let d = unsafe { *(b.cast::<u8>()).add(i) };
if c != d {
return c as c_int - d as c_int;
}
}
unreachable!()
}
a = a.offset(1);
b = b.offset(1);
a = unsafe { a.offset(1) };
b = unsafe { b.offset(1) };
}
let mut a = a.cast::<u8>();
let mut b = b.cast::<u8>();
for _ in 0..rem {
if *a != *b {
return *a as c_int - *b as c_int;
if unsafe { *a } != unsafe { *b } {
return unsafe { *a } as c_int - unsafe { *b } as c_int;
}
a = a.offset(1);
b = b.offset(1);
a = unsafe { a.offset(1) };
b = unsafe { b.offset(1) };
}
0
}
@@ -108,7 +108,7 @@ pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: usize)
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memcpy(s1: *mut c_void, s2: *const c_void, n: size_t) -> *mut c_void {
for i in 0..n {
*(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
unsafe { *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i) };
}
s1
}
@@ -158,13 +158,13 @@ pub unsafe extern "C" fn memmove(s1: *mut c_void, s2: *const c_void, n: size_t)
let mut i = n;
while i != 0 {
i -= 1;
*(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
unsafe { *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i) };
}
} else {
// copy from beginning
let mut i = 0;
while i < n {
*(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
unsafe { *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i) };
i += 1;
}
}
@@ -178,7 +178,7 @@ pub unsafe extern "C" fn memrchr(
needle: c_int,
len: size_t,
) -> *mut c_void {
let haystack = slice::from_raw_parts(haystack as *const u8, len as usize);
let haystack = unsafe { slice::from_raw_parts(haystack as *const u8, len as usize) };
match memchr::memrchr(needle as u8, haystack) {
Some(index) => haystack[index..].as_ptr() as *mut c_void,
@@ -190,7 +190,7 @@ pub unsafe extern "C" fn memrchr(
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: size_t) -> *mut c_void {
for i in 0..n {
*(s as *mut u8).add(i) = c as u8;
unsafe { *(s as *mut u8).add(i) = c as u8 };
}
s
}
@@ -199,14 +199,14 @@ pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: size_t) -> *mut c_v
#[unsafe(no_mangle)]
pub unsafe extern "C" fn stpcpy(mut s1: *mut c_char, mut s2: *const c_char) -> *mut c_char {
loop {
*s1 = *s2;
unsafe { *s1 = *s2 };
if *s1 == 0 {
if unsafe { *s1 } == 0 {
break;
}
s1 = s1.add(1);
s2 = s2.add(1);
s1 = unsafe { s1.add(1) };
s2 = unsafe { s2.add(1) };
}
s1
@@ -220,18 +220,18 @@ pub unsafe extern "C" fn stpncpy(
mut n: size_t,
) -> *mut c_char {
while n > 0 {
*s1 = *s2;
unsafe { *s1 = *s2 };
if *s1 == 0 {
if unsafe { *s1 } == 0 {
break;
}
n -= 1;
s1 = s1.add(1);
s2 = s2.add(1);
s1 = unsafe { s1.add(1) };
s2 = unsafe { s2.add(1) };
}
memset(s1.cast(), 0, n);
unsafe { memset(s1.cast(), 0, n) };
s1
}
@@ -239,13 +239,13 @@ pub unsafe extern "C" fn stpncpy(
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man3/strstr.3.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcasestr(haystack: *const c_char, needle: *const c_char) -> *mut c_char {
inner_strstr(haystack, needle, !32)
unsafe { inner_strstr(haystack, needle, !32) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
strncat(s1, s2, usize::MAX)
unsafe { strncat(s1, s2, usize::MAX) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strchr.html>.
@@ -275,13 +275,13 @@ pub unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char {
pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
let mut s = s.cast_mut();
loop {
if *s == c as _ {
if unsafe { *s } == c as _ {
break;
}
if *s == 0 {
if unsafe { *s } == 0 {
break;
}
s = s.add(1);
s = unsafe { s.add(1) };
}
s
}
@@ -289,14 +289,14 @@ pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcmp.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcmp(s1: *const c_char, s2: *const c_char) -> c_int {
strncmp(s1, s2, usize::MAX)
unsafe { strncmp(s1, s2, usize::MAX) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcoll.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcoll(s1: *const c_char, s2: *const c_char) -> c_int {
// relibc has no locale stuff (yet)
strcmp(s1, s2)
unsafe { strcmp(s1, s2) }
}
// TODO: strcoll_l
@@ -324,18 +324,18 @@ pub unsafe fn inner_strspn(s1: *const c_char, s2: *const c_char, cmp: bool) -> s
let mut set = BitSet256::new();
while *s2 != 0 {
set.insert(*s2 as usize);
s2 = s2.offset(1);
while unsafe { *s2 } != 0 {
set.insert(unsafe { *s2 } as usize);
s2 = unsafe { s2.offset(1) };
}
let mut i = 0;
while *s1 != 0 {
if set.contains(*s1 as usize) != cmp {
while unsafe { *s1 } != 0 {
if set.contains(unsafe { *s1 } as usize) != cmp {
break;
}
i += 1;
s1 = s1.offset(1);
s1 = unsafe { s1.offset(1) };
}
i
}
@@ -343,13 +343,13 @@ pub unsafe fn inner_strspn(s1: *const c_char, s2: *const c_char, cmp: bool) -> s
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcspn.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcspn(s1: *const c_char, s2: *const c_char) -> size_t {
inner_strspn(s1, s2, false)
unsafe { inner_strspn(s1, s2, false) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strdup.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strdup(s1: *const c_char) -> *mut c_char {
strndup(s1, usize::MAX)
unsafe { strndup(s1, usize::MAX) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strerror.html>.
@@ -358,17 +358,16 @@ pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
use core::fmt::Write;
static strerror_buf: RawCell<[u8; STRERROR_MAX]> = RawCell::new([0; STRERROR_MAX]);
let mut w = platform::StringWriter(
strerror_buf.unsafe_mut().as_mut_ptr(),
strerror_buf.unsafe_ref().len(),
);
let mut w = platform::StringWriter(unsafe { strerror_buf.unsafe_mut().as_mut_ptr() }, unsafe {
strerror_buf.unsafe_ref().len()
});
let _ = match STR_ERROR.get(errnum as usize) {
Some(e) => w.write_str(e),
None => w.write_fmt(format_args!("Unknown error {}", errnum)),
};
strerror_buf.unsafe_mut().as_mut_ptr() as *mut c_char
(unsafe { strerror_buf.unsafe_mut().as_mut_ptr() }) as *mut c_char
}
// TODO: strerror_l
@@ -376,17 +375,17 @@ pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strerror.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
let msg = strerror(errnum);
let len = strlen(msg);
let msg = unsafe { strerror(errnum) };
let len = unsafe { strlen(msg) };
if len >= buflen {
if buflen != 0 {
memcpy(buf as *mut c_void, msg as *const c_void, buflen - 1);
*buf.add(buflen - 1) = 0;
unsafe { memcpy(buf as *mut c_void, msg as *const c_void, buflen - 1) };
unsafe { *buf.add(buflen - 1) = 0 };
}
return ERANGE as c_int;
}
memcpy(buf as *mut c_void, msg as *const c_void, len + 1);
unsafe { memcpy(buf as *mut c_void, msg as *const c_void, len + 1) };
0
}
@@ -402,18 +401,18 @@ pub unsafe extern "C" fn strlcat(dst: *mut c_char, src: *const c_char, dstsize:
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strsep(str_: *mut *mut c_char, sep: *const c_char) -> *mut c_char {
let s = *str_;
let s = unsafe { *str_ };
if s.is_null() {
return ptr::null_mut();
}
let mut end = s.add(strcspn(s, sep));
if *end != 0 {
*end = 0;
end = end.add(1);
let mut end = unsafe { s.add(strcspn(s, sep)) };
if unsafe { *end } != 0 {
unsafe { *end = 0 };
end = unsafe { end.add(1) };
} else {
end = ptr::null_mut();
}
*str_ = end;
unsafe { *str_ = end };
s
}
@@ -452,18 +451,18 @@ pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strncat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strncat(s1: *mut c_char, s2: *const c_char, n: size_t) -> *mut c_char {
let len = strlen(s1.cast());
let len = unsafe { strlen(s1.cast()) };
let mut i = 0;
while i < n {
let b = *s2.add(i);
let b = unsafe { *s2.add(i) };
if b == 0 {
break;
}
*s1.add(len + i) = b;
unsafe { *s1.add(len + i) = b };
i += 1;
}
*s1.add(len + i) = 0;
unsafe { *s1.add(len + i) = 0 };
s1
}
@@ -473,8 +472,8 @@ pub unsafe extern "C" fn strncat(s1: *mut c_char, s2: *const c_char, n: size_t)
pub unsafe extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int {
for i in 0..n {
// These must be cast as u8 to have correct comparisons
let a = *s1.add(i) as u8;
let b = *s2.add(i) as u8;
let a = unsafe { *s1.add(i) } as u8;
let b = unsafe { *s2.add(i) } as u8;
if a != b || a == 0 {
return (a as c_int) - (b as c_int);
}
@@ -486,25 +485,25 @@ pub unsafe extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: size_t
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strncpy.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strncpy(s1: *mut c_char, s2: *const c_char, n: size_t) -> *mut c_char {
stpncpy(s1, s2, n);
unsafe { stpncpy(s1, s2, n) };
s1
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strdup.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strndup(s1: *const c_char, size: size_t) -> *mut c_char {
let len = strnlen(s1, size);
let len = unsafe { strnlen(s1, size) };
// the "+ 1" is to account for the NUL byte
let buffer = platform::alloc(len + 1) as *mut c_char;
let buffer = unsafe { platform::alloc(len + 1) } as *mut c_char;
if buffer.is_null() {
platform::ERRNO.set(ENOMEM as c_int);
} else {
//memcpy(buffer, s1, len)
for i in 0..len {
*buffer.add(i) = *s1.add(i);
unsafe { *buffer.add(i) = *s1.add(i) };
}
*buffer.add(len) = 0;
unsafe { *buffer.add(len) = 0 };
}
buffer
@@ -519,14 +518,18 @@ pub unsafe extern "C" fn strnlen(s: *const c_char, size: size_t) -> size_t {
/// Non-POSIX, see <https://en.cppreference.com/w/c/string/byte/strlen>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strnlen_s(s: *const c_char, size: size_t) -> size_t {
if s.is_null() { 0 } else { strnlen(s, size) }
if s.is_null() {
0
} else {
unsafe { strnlen(s, size) }
}
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strpbrk.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strpbrk(s1: *const c_char, s2: *const c_char) -> *mut c_char {
let p = s1.add(strcspn(s1, s2));
if *p != 0 {
let p = unsafe { s1.add(strcspn(s1, s2)) };
if unsafe { *p } != 0 {
p as *mut c_char
} else {
ptr::null_mut()
@@ -536,12 +539,12 @@ pub unsafe extern "C" fn strpbrk(s1: *const c_char, s2: *const c_char) -> *mut c
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strrchr.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strrchr(s: *const c_char, c: c_int) -> *mut c_char {
let len = strlen(s) as isize;
let len = unsafe { strlen(s) } as isize;
let c = c as c_char;
let mut i = len - 1;
while i >= 0 {
if *s.offset(i) == c {
return s.offset(i) as *mut c_char;
if unsafe { *s.offset(i) } == c {
return unsafe { s.offset(i) } as *mut c_char;
}
i -= 1;
}
@@ -560,7 +563,7 @@ pub unsafe extern "C" fn strsignal(sig: c_int) -> *mut c_char {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strspn.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strspn(s1: *const c_char, s2: *const c_char) -> size_t {
inner_strspn(s1, s2, true)
unsafe { inner_strspn(s1, s2, true) }
}
unsafe fn inner_strstr(
@@ -568,21 +571,21 @@ unsafe fn inner_strstr(
needle: *const c_char,
mask: c_char,
) -> *mut c_char {
while *haystack != 0 {
while unsafe { *haystack } != 0 {
let mut i = 0;
loop {
if *needle.offset(i) == 0 {
if unsafe { *needle.offset(i) } == 0 {
// We reached the end of the needle, everything matches this far
return haystack as *mut c_char;
}
if *haystack.offset(i) & mask != *needle.offset(i) & mask {
if unsafe { *haystack.offset(i) } & mask != unsafe { *needle.offset(i) } & mask {
break;
}
i += 1;
}
haystack = haystack.offset(1);
haystack = unsafe { haystack.offset(1) };
}
ptr::null_mut()
}
@@ -590,14 +593,14 @@ unsafe fn inner_strstr(
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strstr.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strstr(haystack: *const c_char, needle: *const c_char) -> *mut c_char {
inner_strstr(haystack, needle, !0)
unsafe { inner_strstr(haystack, needle, !0) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtok.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strtok(s1: *mut c_char, delimiter: *const c_char) -> *mut c_char {
static mut HAYSTACK: *mut c_char = ptr::null_mut();
strtok_r(s1, delimiter, &raw mut HAYSTACK)
unsafe { strtok_r(s1, delimiter, &raw mut HAYSTACK) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtok.html>.
@@ -610,28 +613,28 @@ pub unsafe extern "C" fn strtok_r(
// musl returns null if both s and lasts are null, it sets s to lasts otherwise
let mut haystack = s;
if haystack.is_null() {
if (*lasts).is_null() {
if (unsafe { *lasts }).is_null() {
return ptr::null_mut();
}
haystack = *lasts;
haystack = unsafe { *lasts };
}
// Skip past any extra delimiter left over from previous call
haystack = haystack.add(strspn(haystack, delimiter));
if *haystack == 0 {
*lasts = haystack;
haystack = unsafe { haystack.add(strspn(haystack, delimiter)) };
if unsafe { *haystack } == 0 {
unsafe { *lasts = haystack };
return ptr::null_mut();
}
// Build token by injecting null byte into delimiter
let token = haystack;
haystack = strpbrk(token, delimiter);
haystack = unsafe { strpbrk(token, delimiter) };
if !haystack.is_null() {
haystack.write(0);
haystack = haystack.add(1);
*lasts = haystack;
unsafe { haystack.write(0) };
haystack = unsafe { haystack.add(1) };
unsafe { *lasts = haystack };
} else {
*lasts = token.add(strlen(token));
unsafe { *lasts = token.add(strlen(token)) };
}
token
@@ -641,9 +644,9 @@ pub unsafe extern "C" fn strtok_r(
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strxfrm(s1: *mut c_char, s2: *const c_char, n: size_t) -> size_t {
// relibc has no locale stuff (yet)
let len = strlen(s2);
let len = unsafe { strlen(s2) };
if len < n {
strcpy(s1, s2);
unsafe { strcpy(s1, s2) };
}
len
}