From 718dc53b87e47a54d486a2c273a21132a52aa599 Mon Sep 17 00:00:00 2001 From: sourceturner <126549-sourceturner@users.noreply.gitlab.redox-os.org> Date: Sun, 18 Jan 2026 21:25:10 +0100 Subject: [PATCH] Use unsafe blocks in wchar.h implementation --- src/header/wchar/mod.rs | 311 +++++++++++++++++++----------------- src/header/wchar/utf8.rs | 13 +- src/header/wchar/wprintf.rs | 5 +- src/header/wchar/wscanf.rs | 75 +++++---- 4 files changed, 223 insertions(+), 181 deletions(-) diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index 32909f8602..32236b5e6d 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -2,6 +2,9 @@ //! //! See . +// TODO: set this for entire crate when possible +#![deny(unsafe_op_in_unsafe_fn)] + use core::{char, ffi::VaList as va_list, mem, ptr, slice, usize}; use crate::{ @@ -49,7 +52,7 @@ pub unsafe extern "C" fn btowc(c: c_int) -> wint_t { let mut ps: mbstate_t = mbstate_t; let mut wc: wchar_t = 0; let saved_errno = platform::ERRNO.get(); - let status = mbrtowc(&mut wc, &c as *const c_char, 1, &mut ps); + let status = unsafe { mbrtowc(&mut wc, &c as *const c_char, 1, &mut ps) }; if status == usize::max_value() || status == usize::max_value() - 1 { platform::ERRNO.set(saved_errno); return WEOF; @@ -67,12 +70,14 @@ pub unsafe extern "C" fn fgetwc(stream: *mut FILE) -> wint_t { let mut wc: wchar_t = 0; loop { - let nread = fread( - buf[bytes_read..bytes_read + 1].as_mut_ptr() as *mut c_void, - 1, - 1, - stream, - ); + let nread = unsafe { + fread( + buf[bytes_read..bytes_read + 1].as_mut_ptr() as *mut c_void, + 1, + 1, + stream, + ) + }; if nread != 1 { ERRNO.set(EILSEQ); @@ -95,12 +100,14 @@ pub unsafe extern "C" fn fgetwc(stream: *mut FILE) -> wint_t { } } - mbrtowc( - &mut wc, - buf.as_ptr() as *const c_char, - encoded_length, - ptr::null_mut(), - ); + unsafe { + mbrtowc( + &mut wc, + buf.as_ptr() as *const c_char, + encoded_length, + ptr::null_mut(), + ) + }; wc as wint_t } @@ -111,15 +118,15 @@ pub unsafe extern "C" fn fgetws(ws: *mut wchar_t, n: c_int, stream: *mut FILE) - //TODO: lock let mut i = 0; while ((i + 1) as c_int) < n { - let wc = fgetwc(stream); + let wc = unsafe { fgetwc(stream) }; if wc == WEOF { return ptr::null_mut(); } - *ws.add(i) = wc as wchar_t; + unsafe { *ws.add(i) = wc as wchar_t }; i += 1; } while (i as c_int) < n { - *ws.add(i) = 0; + unsafe { *ws.add(i) = 0 }; i += 1; } ws @@ -132,10 +139,10 @@ pub unsafe extern "C" fn fputwc(wc: wchar_t, stream: *mut FILE) -> wint_t { static mut INTERNAL: mbstate_t = mbstate_t; let mut bytes: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize]; - let amount = wcrtomb(bytes.as_mut_ptr(), wc, &raw mut INTERNAL); + let amount = unsafe { wcrtomb(bytes.as_mut_ptr(), wc, &raw mut INTERNAL) }; for i in 0..amount { - fputc(bytes[i] as c_int, &mut *stream); + unsafe { fputc(bytes[i] as c_int, &mut *stream) }; } wc as wint_t @@ -146,11 +153,11 @@ pub unsafe extern "C" fn fputwc(wc: wchar_t, stream: *mut FILE) -> wint_t { pub unsafe extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE) -> c_int { let mut i = 0; loop { - let wc = *ws.add(i); + let wc = unsafe { *ws.add(i) }; if wc == 0 { return 0; } - if fputwc(wc, stream) == WEOF { + if unsafe { fputwc(wc, stream) } == WEOF { return -1; } i += 1; @@ -160,7 +167,7 @@ pub unsafe extern "C" fn fputws(ws: *const wchar_t, stream: *mut FILE) -> c_int /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn fwide(stream: *mut FILE, mode: c_int) -> c_int { - (*stream).try_set_orientation(mode) + unsafe { (*stream).try_set_orientation(mode) } } /// See . @@ -170,19 +177,19 @@ pub unsafe extern "C" fn fwscanf( format: *const wchar_t, mut __valist: ... ) -> c_int { - vfwscanf(stream, format, __valist.as_va_list()) + unsafe { vfwscanf(stream, format, __valist.as_va_list()) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn getwc(stream: *mut FILE) -> wint_t { - fgetwc(stream) + unsafe { fgetwc(stream) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn getwchar() -> wint_t { - fgetwc(stdin) + unsafe { fgetwc(stdin) } } /// See . @@ -196,7 +203,7 @@ pub unsafe extern "C" fn mbsinit(ps: *const mbstate_t) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn mbrlen(s: *const c_char, n: size_t, ps: *mut mbstate_t) -> size_t { static mut INTERNAL: mbstate_t = mbstate_t; - mbrtowc(ptr::null_mut(), s, n, &raw mut INTERNAL) + unsafe { mbrtowc(ptr::null_mut(), s, n, &raw mut INTERNAL) } } /// See . @@ -216,9 +223,9 @@ pub unsafe extern "C" fn mbrtowc( } if s.is_null() { let xs: [c_char; 1] = [0]; - utf8::mbrtowc(pwc, &xs[0] as *const c_char, 1, ps) + unsafe { utf8::mbrtowc(pwc, &xs[0] as *const c_char, 1, ps) } } else { - utf8::mbrtowc(pwc, s, n, ps) + unsafe { utf8::mbrtowc(pwc, s, n, ps) } } } @@ -239,31 +246,31 @@ pub unsafe extern "C" fn mbsnrtowcs( let ps = &raw mut INTERNAL; } - let mut src = *src_ptr; + let mut src = unsafe { *src_ptr }; let mut dst_offset: usize = 0; let mut src_offset: usize = 0; while (dst_ptr.is_null() || dst_offset < dst_len) && src_offset < src_len { - let ps_copy = *ps; + let ps_copy = unsafe { *ps }; let mut wc: wchar_t = 0; - let amount = mbrtowc(&mut wc, src.add(src_offset), src_len - src_offset, ps); + let amount = unsafe { mbrtowc(&mut wc, src.add(src_offset), src_len - src_offset, ps) }; // Stop in the event a decoding error occured. if amount == -1isize as usize { - *src_ptr = src.add(src_offset); + unsafe { *src_ptr = src.add(src_offset) }; return 1isize as usize; } // Stop decoding early in the event we encountered a partial character. if amount == -2isize as usize { - *ps = ps_copy; + unsafe { *ps = ps_copy }; break; } // Store the decoded wide character in the destination buffer. if !dst_ptr.is_null() { - *dst_ptr.add(dst_offset) = wc; + unsafe { *dst_ptr.add(dst_offset) = wc }; } // Stop decoding after decoding a null character and return a NULL @@ -279,7 +286,7 @@ pub unsafe extern "C" fn mbsnrtowcs( src_offset += amount; } - *src_ptr = src.add(src_offset); + unsafe { *src_ptr = src.add(src_offset) }; dst_offset } @@ -293,19 +300,19 @@ pub unsafe extern "C" fn mbsrtowcs( len: size_t, ps: *mut mbstate_t, ) -> size_t { - mbsnrtowcs(dst, src, size_t::max_value(), len, ps) + unsafe { mbsnrtowcs(dst, src, size_t::max_value(), len, ps) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn putwc(wc: wchar_t, stream: *mut FILE) -> wint_t { - fputwc(wc, &mut *stream) + unsafe { fputwc(wc, &mut *stream) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn putwchar(wc: wchar_t) -> wint_t { - fputwc(wc, &mut *stdout) + unsafe { fputwc(wc, &mut *stdout) } } /// See . @@ -316,7 +323,7 @@ pub unsafe extern "C" fn vswscanf( __valist: va_list, ) -> c_int { let reader = (s as *const wint_t).into(); - wscanf::scanf(reader, format, __valist) + unsafe { wscanf::scanf(reader, format, __valist) } } /// See . @@ -326,7 +333,7 @@ pub unsafe extern "C" fn swscanf( format: *const wchar_t, mut __valist: ... ) -> c_int { - vswscanf(s, format, __valist.as_va_list()) + unsafe { vswscanf(s, format, __valist.as_va_list()) } } /// See . @@ -340,7 +347,7 @@ pub unsafe extern "C" fn ungetwc(wc: wint_t, stream: &mut FILE) -> wint_t { static mut INTERNAL: mbstate_t = mbstate_t; let mut bytes: [c_char; MB_CUR_MAX as usize] = [0; MB_CUR_MAX as usize]; - let amount = wcrtomb(bytes.as_mut_ptr(), wc as wchar_t, &raw mut INTERNAL); + let amount = unsafe { wcrtomb(bytes.as_mut_ptr(), wc as wchar_t, &raw mut INTERNAL) }; if amount == usize::MAX { return WEOF; } @@ -352,7 +359,7 @@ pub unsafe extern "C" fn ungetwc(wc: wint_t, stream: &mut FILE) -> wint_t { If we called ungetc in the non-reversed order, we would get [167, 195] */ for i in 0..amount { - ungetc(bytes[amount - 1 - i] as c_int, &mut *stream); + unsafe { ungetc(bytes[amount - 1 - i] as c_int, &mut *stream) }; } wc @@ -365,12 +372,12 @@ pub unsafe extern "C" fn vfwprintf( format: *const wchar_t, arg: va_list, ) -> c_int { - let mut stream = (*stream).lock(); + let mut stream = unsafe { (*stream).lock() }; if let Err(_) = (*stream).try_set_wide_orientation_unlocked() { return -1; } - wprintf::wprintf(&mut *stream, WStr::from_ptr(format), arg) + unsafe { wprintf::wprintf(&mut *stream, WStr::from_ptr(format), arg) } } /// See . @@ -380,19 +387,19 @@ pub unsafe extern "C" fn fwprintf( format: *const wchar_t, mut __valist: ... ) -> c_int { - vfwprintf(stream, format, __valist.as_va_list()) + unsafe { vfwprintf(stream, format, __valist.as_va_list()) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vwprintf(format: *const wchar_t, arg: va_list) -> c_int { - vfwprintf(&mut *stdout, format, arg) + unsafe { vfwprintf(&mut *stdout, format, arg) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wprintf(format: *const wchar_t, mut __valist: ...) -> c_int { - vfwprintf(&mut *stdout, format, __valist.as_va_list()) + unsafe { vfwprintf(&mut *stdout, format, __valist.as_va_list()) } } /// See . @@ -417,19 +424,19 @@ pub unsafe extern "C" fn swprintf( format: *const wchar_t, mut __valist: ... ) -> c_int { - vswprintf(s, n, format, __valist.as_va_list()) + unsafe { vswprintf(s, n, format, __valist.as_va_list()) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcpcpy(d: *mut wchar_t, s: *const wchar_t) -> *mut wchar_t { - return (wcscpy(d, s)).offset(wcslen(s) as isize); + return unsafe { (wcscpy(d, s)).offset(wcslen(s) as isize) }; } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcpncpy(d: *mut wchar_t, s: *const wchar_t, n: size_t) -> *mut wchar_t { - return (wcsncpy(d, s, n)).offset(wcsnlen(s, n) as isize); + return unsafe { (wcsncpy(d, s, n)).offset(wcsnlen(s, n) as isize) }; } /// See . @@ -444,22 +451,22 @@ pub unsafe extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t (s, wc) }; - utf8::wcrtomb(s_cpy, wc_cpy, ps) + unsafe { utf8::wcrtomb(s_cpy, wc_cpy, ps) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t { - let l = wcslen(s); + let l = unsafe { wcslen(s) }; - let d = malloc((l + 1) * mem::size_of::()) as *mut wchar_t; + let d = unsafe { malloc((l + 1) * mem::size_of::()) } as *mut wchar_t; if d.is_null() { ERRNO.set(ENOMEM); return ptr::null_mut(); } - wmemcpy(d, s, l + 1) + unsafe { wmemcpy(d, s, l + 1) } } /// See . @@ -474,13 +481,13 @@ pub unsafe extern "C" fn wcsrtombs( if st.is_null() { st = &mut mbs; } - wcsnrtombs(s, ws, size_t::MAX, n, st) + unsafe { wcsnrtombs(s, ws, size_t::MAX, n, st) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcscat(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t { - wcsncat(ws1, ws2, usize::MAX) + unsafe { wcsncat(ws1, ws2, usize::MAX) } } /// See . @@ -506,14 +513,14 @@ pub unsafe extern "C" fn wcschr(ws: *const wchar_t, wc: wchar_t) -> *mut wchar_t /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcscmp(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int { - wcsncmp(ws1, ws2, usize::MAX) + unsafe { wcsncmp(ws1, ws2, usize::MAX) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcscoll(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int { //TODO: locale comparison - wcscmp(ws1, ws2) + unsafe { wcscmp(ws1, ws2) } } /// See . @@ -521,8 +528,8 @@ pub unsafe extern "C" fn wcscoll(ws1: *const wchar_t, ws2: *const wchar_t) -> c_ pub unsafe extern "C" fn wcscpy(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t { let mut i = 0; loop { - let wc = *ws2.add(i); - *ws1.add(i) = wc; + let wc = unsafe { *ws2.add(i) }; + unsafe { *ws1.add(i) = wc }; i += 1; if wc == 0 { return ws1; @@ -532,8 +539,8 @@ pub unsafe extern "C" fn wcscpy(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut unsafe fn inner_wcsspn(mut wcs: *const wchar_t, set: *const wchar_t, reject: bool) -> size_t { let mut count = 0; - while (*wcs) != 0 && wcschr(set, *wcs).is_null() == reject { - wcs = wcs.add(1); + while unsafe { *wcs } != 0 && unsafe { wcschr(set, *wcs).is_null() } == reject { + wcs = unsafe { wcs.add(1) }; count += 1; } count @@ -542,7 +549,7 @@ unsafe fn inner_wcsspn(mut wcs: *const wchar_t, set: *const wchar_t, reject: boo /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcscspn(wcs: *const wchar_t, set: *const wchar_t) -> size_t { - inner_wcsspn(wcs, set, true) + unsafe { inner_wcsspn(wcs, set, true) } } /// See . @@ -569,18 +576,18 @@ pub unsafe extern "C" fn wcsncat( ws2: *const wchar_t, n: size_t, ) -> *mut wchar_t { - let len = wcslen(ws1); - let dest = ws1.add(len); + let len = unsafe { wcslen(ws1) }; + let dest = unsafe { ws1.add(len) }; let mut i = 0; while i < n { - let wc = *ws2.add(i); + let wc = unsafe { *ws2.add(i) }; if wc == 0 { break; } - *dest.add(i) = wc; + unsafe { *dest.add(i) = wc }; i += 1; } - *dest.add(i) = 0; + unsafe { *dest.add(i) = 0 }; ws1 } @@ -588,8 +595,8 @@ pub unsafe extern "C" fn wcsncat( #[unsafe(no_mangle)] pub unsafe extern "C" fn wcsncmp(ws1: *const wchar_t, ws2: *const wchar_t, n: size_t) -> c_int { for i in 0..n { - let wc1 = *ws1.add(i); - let wc2 = *ws2.add(i); + let wc1 = unsafe { *ws1.add(i) }; + let wc2 = unsafe { *ws2.add(i) }; if wc1 != wc2 { return wc1 - wc2; } else if wc1 == 0 { @@ -608,15 +615,15 @@ pub unsafe extern "C" fn wcsncpy( ) -> *mut wchar_t { let mut i = 0; while i < n { - let wc = *ws2.add(i); - *ws1.add(i) = wc; + let wc = unsafe { *ws2.add(i) }; + unsafe { *ws1.add(i) = wc }; i += 1; if wc == 0 { break; } } while i < n { - *ws1.add(i) = 0; + unsafe { *ws1.add(i) = 0 }; i += 1; } ws1 @@ -628,12 +635,12 @@ pub unsafe extern "C" fn wcsnlen(mut s: *const wchar_t, maxlen: size_t) -> size_ let mut len = 0; while len < maxlen { - if *s == 0 { + if unsafe { *s } == 0 { break; } len = len + 1; - s = s.offset(1); + s = unsafe { s.offset(1) }; } return len; @@ -660,7 +667,7 @@ pub unsafe extern "C" fn wcsnrtombs( while read < nwc { buf.fill(0); - let ret = wcrtomb(buf.as_mut_ptr(), **src, ps); + let ret = unsafe { wcrtomb(buf.as_mut_ptr(), **src, ps) }; if ret == size_t::MAX { ERRNO.set(EILSEQ); @@ -672,16 +679,16 @@ pub unsafe extern "C" fn wcsnrtombs( } if !dest.is_null() { - ptr::copy_nonoverlapping(buf.as_ptr(), dest, ret); - dest = dest.add(ret); + unsafe { ptr::copy_nonoverlapping(buf.as_ptr(), dest, ret) }; + dest = unsafe { dest.add(ret) }; } - if **src == '\0' as wchar_t { - *src = ptr::null(); + if unsafe { **src } == '\0' as wchar_t { + unsafe { *src = ptr::null() }; return written; } - *src = (*src).add(1); + unsafe { *src = (*src).add(1) }; read += 1; written += ret; } @@ -691,8 +698,8 @@ pub unsafe extern "C" fn wcsnrtombs( /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcspbrk(mut wcs: *const wchar_t, set: *const wchar_t) -> *mut wchar_t { - wcs = wcs.add(wcscspn(wcs, set)); - if *wcs == 0 { + wcs = unsafe { wcs.add(wcscspn(wcs, set)) }; + if unsafe { *wcs } == 0 { ptr::null_mut() } else { // Once again, C wants us to transmute a const pointer to a @@ -707,9 +714,9 @@ pub unsafe extern "C" fn wcsrchr(ws1: *const wchar_t, wc: wchar_t) -> *mut wchar let mut last_matching_wc = 0 as *const wchar_t; let mut i = 0; - while *ws1.add(i) != 0 { - if *ws1.add(i) == wc { - last_matching_wc = ws1.add(i); + while unsafe { *ws1.add(i) } != 0 { + if unsafe { *ws1.add(i) } == wc { + last_matching_wc = unsafe { ws1.add(i) }; } i += 1; } @@ -720,24 +727,24 @@ pub unsafe extern "C" fn wcsrchr(ws1: *const wchar_t, wc: wchar_t) -> *mut wchar /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcsspn(wcs: *const wchar_t, set: *const wchar_t) -> size_t { - inner_wcsspn(wcs, set, false) + unsafe { inner_wcsspn(wcs, set, false) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t { // Get length of ws2, not including null terminator - let ws2_len = wcslen(ws2); + let ws2_len = unsafe { wcslen(ws2) }; // The standard says that we must return ws1 if ws2 has length 0 if ws2_len == 0 { ws1 as *mut wchar_t } else { - let ws1_len = wcslen(ws1); + let ws1_len = unsafe { wcslen(ws1) }; // Construct slices without null terminator - let ws1_slice = slice::from_raw_parts(ws1, ws1_len); - let ws2_slice = slice::from_raw_parts(ws2, ws2_len); + let ws1_slice = unsafe { slice::from_raw_parts(ws1, ws1_len) }; + let ws2_slice = unsafe { slice::from_raw_parts(ws2, ws2_len) }; /* Sliding ws2-sized window iterator on ws1. The iterator * returns None if ws2 is longer than ws1. */ @@ -746,7 +753,7 @@ pub unsafe extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mu /* Find the first offset into ws1 where the window is equal to * the ws2 contents. Return null pointer if no match is found. */ match ws1_windows.position(|ws1_window| ws1_window == ws2_slice) { - Some(pos) => ws1.add(pos) as *mut wchar_t, + Some(pos) => unsafe { ws1.add(pos) as *mut wchar_t }, None => ptr::null_mut(), } } @@ -754,8 +761,8 @@ pub unsafe extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mu macro_rules! skipws { ($ptr:expr) => { - while isspace(*$ptr) != 0 { - $ptr = $ptr.add(1); + while isspace(unsafe { *$ptr }) != 0 { + $ptr = unsafe { $ptr.add(1) }; } }; } @@ -766,37 +773,38 @@ pub unsafe extern "C" fn wcstod(mut ptr: *const wchar_t, end: *mut *mut wchar_t) const RADIX: u32 = 10; skipws!(ptr); - let negative = *ptr == '-' as wchar_t; + let negative = unsafe { *ptr } == '-' as wchar_t; if negative { - ptr = ptr.add(1); + ptr = unsafe { ptr.add(1) }; } let mut result: c_double = 0.0; - while let Some(digit) = char::from_u32(*ptr as _).and_then(|c| c.to_digit(RADIX)) { + while let Some(digit) = char::from_u32(unsafe { *ptr } as _).and_then(|c| c.to_digit(RADIX)) { result *= 10.0; if negative { result -= digit as c_double; } else { result += digit as c_double; } - ptr = ptr.add(1); + ptr = unsafe { ptr.add(1) }; } - if *ptr == '.' as wchar_t { - ptr = ptr.add(1); + if unsafe { *ptr } == '.' as wchar_t { + ptr = unsafe { ptr.add(1) }; let mut scale = 1.0; - while let Some(digit) = char::from_u32(*ptr as _).and_then(|c| c.to_digit(RADIX)) { + while let Some(digit) = char::from_u32(unsafe { *ptr } as _).and_then(|c| c.to_digit(RADIX)) + { scale /= 10.0; if negative { result -= digit as c_double * scale; } else { result += digit as c_double * scale; } - ptr = ptr.add(1); + ptr = unsafe { ptr.add(1) }; } } if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -810,29 +818,29 @@ pub unsafe extern "C" fn wcstok( ) -> *mut wchar_t { // Choose starting position if wcs.is_null() { - if (*state).is_null() { + if (unsafe { *state }).is_null() { // There was no next token return ptr::null_mut(); } - wcs = *state; + wcs = unsafe { *state }; } // Advance past any delimiters - wcs = wcs.add(wcsspn(wcs, delim)); + wcs = unsafe { wcs.add(wcsspn(wcs, delim)) }; // Check end - if *wcs == 0 { - *state = ptr::null_mut(); + if unsafe { *wcs } == 0 { + unsafe { *state = ptr::null_mut() }; return ptr::null_mut(); } // Advance *to* any delimiters - let end = wcspbrk(wcs, delim); + let end = unsafe { wcspbrk(wcs, delim) }; if end.is_null() { - *state = ptr::null_mut(); + unsafe { *state = ptr::null_mut() }; } else { - *end = 0; - *state = end.add(1); + unsafe { *end = 0 }; + unsafe { *state = end.add(1) }; } wcs } @@ -845,19 +853,26 @@ macro_rules! strtou_impl { let mut base = $base; if (base == 16 || base == 0) - && *$ptr == '0' as wchar_t - && (*$ptr.add(1) == 'x' as wchar_t || *$ptr.add(1) == 'X' as wchar_t) + && unsafe { *$ptr } == '0' as wchar_t + && (unsafe { *$ptr.add(1) } == 'x' as wchar_t + || unsafe { *$ptr.add(1) } == 'X' as wchar_t) { - $ptr = $ptr.add(2); + $ptr = unsafe { $ptr.add(2) }; base = 16; } if base == 0 { - base = if *$ptr == '0' as wchar_t { 8 } else { 10 }; + base = if unsafe { *$ptr } == '0' as wchar_t { + 8 + } else { + 10 + }; }; let mut result: $type = 0; - while let Some(digit) = char::from_u32(*$ptr as u32).and_then(|c| c.to_digit(base as u32)) { + while let Some(digit) = + char::from_u32(unsafe { *$ptr } as u32).and_then(|c| c.to_digit(base as u32)) + { let new = result.checked_mul(base as $type).and_then(|result| { if $negative { result.checked_sub(digit as $type) @@ -873,16 +888,16 @@ macro_rules! strtou_impl { } }; - $ptr = $ptr.add(1); + $ptr = unsafe { $ptr.add(1) }; } result }}; } macro_rules! strto_impl { ($type:ident, $ptr:expr, $base:expr) => {{ - let negative = *$ptr == '-' as wchar_t; + let negative = unsafe { *$ptr } == '-' as wchar_t; if negative { - $ptr = $ptr.add(1); + $ptr = unsafe { $ptr.add(1) }; } strtou_impl!($type, $ptr, $base, negative) }}; @@ -898,7 +913,7 @@ pub unsafe extern "C" fn wcstol( skipws!(ptr); let result = strto_impl!(c_long, ptr, base); if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -913,7 +928,7 @@ pub unsafe extern "C" fn wcstoll( skipws!(ptr); let result = strto_impl!(c_longlong, ptr, base); if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -928,7 +943,7 @@ pub unsafe extern "C" fn wcstoimax( skipws!(ptr); let result = strto_impl!(intmax_t, ptr, base); if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -943,7 +958,7 @@ pub unsafe extern "C" fn wcstoul( skipws!(ptr); let result = strtou_impl!(c_ulong, ptr, base); if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -958,7 +973,7 @@ pub unsafe extern "C" fn wcstoull( skipws!(ptr); let result = strtou_impl!(c_ulonglong, ptr, base); if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -973,7 +988,7 @@ pub unsafe extern "C" fn wcstoumax( skipws!(ptr); let result = strtou_impl!(uintmax_t, ptr, base); if !end.is_null() { - *end = ptr as *mut _; + unsafe { *end = ptr as *mut _ }; } result } @@ -984,7 +999,7 @@ pub unsafe extern "C" fn wcstoumax( /// Encouraged to use `wcsstr` instead, which this implementation simply forwards to. #[unsafe(no_mangle)] pub unsafe extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t { - wcsstr(ws1, ws2) + unsafe { wcsstr(ws1, ws2) } } /// See . @@ -992,7 +1007,7 @@ pub unsafe extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mu pub unsafe extern "C" fn wcswidth(pwcs: *const wchar_t, n: size_t) -> c_int { let mut total_width = 0; for i in 0..n { - let wc_width = wcwidth(*pwcs.add(i)); + let wc_width = wcwidth(unsafe { *pwcs.add(i) }); if wc_width < 0 { return -1; } @@ -1029,8 +1044,8 @@ pub extern "C" fn wcwidth(wc: wchar_t) -> c_int { #[unsafe(no_mangle)] pub unsafe extern "C" fn wmemchr(ws: *const wchar_t, wc: wchar_t, n: size_t) -> *mut wchar_t { for i in 0..n { - if *ws.add(i) == wc { - return ws.add(i) as *mut wchar_t; + if unsafe { *ws.add(i) } == wc { + return unsafe { ws.add(i) } as *mut wchar_t; } } ptr::null_mut() @@ -1040,8 +1055,8 @@ pub unsafe extern "C" fn wmemchr(ws: *const wchar_t, wc: wchar_t, n: size_t) -> #[unsafe(no_mangle)] pub unsafe extern "C" fn wmemcmp(ws1: *const wchar_t, ws2: *const wchar_t, n: size_t) -> c_int { for i in 0..n { - let wc1 = *ws1.add(i); - let wc2 = *ws2.add(i); + let wc1 = unsafe { *ws1.add(i) }; + let wc2 = unsafe { *ws2.add(i) }; if wc1 != wc2 { return wc1 - wc2; } @@ -1056,11 +1071,13 @@ pub unsafe extern "C" fn wmemcpy( ws2: *const wchar_t, n: size_t, ) -> *mut wchar_t { - string::memcpy( - ws1 as *mut c_void, - ws2 as *const c_void, - n * mem::size_of::(), - ) as *mut wchar_t + (unsafe { + string::memcpy( + ws1 as *mut c_void, + ws2 as *const c_void, + n * mem::size_of::(), + ) + }) as *mut wchar_t } /// See . @@ -1070,18 +1087,20 @@ pub unsafe extern "C" fn wmemmove( ws2: *const wchar_t, n: size_t, ) -> *mut wchar_t { - string::memmove( - ws1 as *mut c_void, - ws2 as *const c_void, - n * mem::size_of::(), - ) as *mut wchar_t + (unsafe { + string::memmove( + ws1 as *mut c_void, + ws2 as *const c_void, + n * mem::size_of::(), + ) + }) as *mut wchar_t } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wmemset(ws: *mut wchar_t, wc: wchar_t, n: size_t) -> *mut wchar_t { for i in 0..n { - *ws.add(i) = wc; + unsafe { *ws.add(i) = wc }; } ws } @@ -1093,26 +1112,26 @@ pub unsafe extern "C" fn vfwscanf( format: *const wchar_t, __valist: va_list, ) -> c_int { - let mut file = (*stream).lock(); + let mut file = unsafe { (*stream).lock() }; if let Err(_) = file.try_set_byte_orientation_unlocked() { return -1; } let f: &mut FILE = &mut *file; let reader: LookAheadReader = f.into(); - wscanf::scanf(reader, format, __valist) + unsafe { wscanf::scanf(reader, format, __valist) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn vwscanf(format: *const wchar_t, __valist: va_list) -> c_int { - vfwscanf(stdin, format, __valist) + unsafe { vfwscanf(stdin, format, __valist) } } /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wscanf(format: *const wchar_t, mut __valist: ...) -> c_int { - vfwscanf(stdin, format, __valist.as_va_list()) + unsafe { vfwscanf(stdin, format, __valist.as_va_list()) } } /// See . diff --git a/src/header/wchar/utf8.rs b/src/header/wchar/utf8.rs index c55aa930d7..31d1a8aba3 100644 --- a/src/header/wchar/utf8.rs +++ b/src/header/wchar/utf8.rs @@ -1,6 +1,9 @@ //UTF implementation parts for wchar.h. //Partially ported from the Sortix libc +// TODO: set this for entire crate when possible +#![deny(unsafe_op_in_unsafe_fn)] + use core::{char, slice, str, usize}; use crate::{ @@ -42,17 +45,17 @@ fn utf8_char_width(b: u8) -> usize { //It's guaranteed that we don't have any nullpointers here pub unsafe fn mbrtowc(pwc: *mut wchar_t, s: *const c_char, n: usize, ps: *mut mbstate_t) -> usize { - let size = utf8_char_width(*s as u8); + let size = utf8_char_width(unsafe { *s } as u8); if size > n { platform::ERRNO.set(errno::EILSEQ); return -2isize as usize; } if size == 0 { platform::ERRNO.set(errno::EILSEQ); - return -1isize as usize; + return unsafe { -1isize as usize }; } - let slice = slice::from_raw_parts(s as *const u8, size); + let slice = unsafe { slice::from_raw_parts(s as *const u8, size) }; let decoded = str::from_utf8(slice); if decoded.is_err() { platform::ERRNO.set(errno::EILSEQ); @@ -64,7 +67,7 @@ pub unsafe fn mbrtowc(pwc: *mut wchar_t, s: *const c_char, n: usize, ps: *mut mb let result: wchar_t = wc.chars().next().unwrap() as wchar_t; if !pwc.is_null() { - *pwc = result; + unsafe { *pwc = result }; } if result != 0 { size } else { 0 } @@ -81,7 +84,7 @@ pub unsafe fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> usize let c = dc.unwrap(); let size = c.len_utf8(); - let slice = slice::from_raw_parts_mut(s as *mut u8, size); + let slice = unsafe { slice::from_raw_parts_mut(s as *mut u8, size) }; c.encode_utf8(slice); diff --git a/src/header/wchar/wprintf.rs b/src/header/wchar/wprintf.rs index 1925a0369b..539585dc2f 100644 --- a/src/header/wchar/wprintf.rs +++ b/src/header/wchar/wprintf.rs @@ -1,3 +1,6 @@ +// TODO: set this for entire crate when possible +#![deny(unsafe_op_in_unsafe_fn)] + // TODO: reuse more code with the thin printf impl use crate::{ c_str::{self, WStr}, @@ -9,5 +12,5 @@ use core::ffi::VaList; use crate::platform::{self, types::*}; pub unsafe fn wprintf(w: impl Write, format: WStr, ap: VaList) -> c_int { - inner_printf::(w, format, ap).unwrap_or(-1) + unsafe { inner_printf::(w, format, ap).unwrap_or(-1) } } diff --git a/src/header/wchar/wscanf.rs b/src/header/wchar/wscanf.rs index e001322704..e284a6631a 100644 --- a/src/header/wchar/wscanf.rs +++ b/src/header/wchar/wscanf.rs @@ -1,3 +1,6 @@ +// TODO: set this for entire crate when possible +#![deny(unsafe_op_in_unsafe_fn)] + use super::lookaheadreader::LookAheadReader; use crate::platform::types::*; use alloc::{string::String, vec::Vec}; @@ -23,8 +26,8 @@ enum CharKind { /// Helper function for progressing a C string unsafe fn next_char(string: &mut *const wchar_t) -> Result { - let c = **string as wint_t; - *string = string.offset(1); + let c = unsafe { **string } as wint_t; + *string = unsafe { string.offset(1) }; if c == 0 { Err(-1) } else { Ok(c) } } @@ -79,8 +82,8 @@ unsafe fn inner_scanf( } } - while *format != 0 { - let mut c = next_char(&mut format)?; + while unsafe { *format } != 0 { + let mut c = unsafe { next_char(&mut format) }?; if c as u8 == b' ' { maybe_read!(noreset); @@ -99,18 +102,18 @@ unsafe fn inner_scanf( } r.commit(); } else { - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; let mut ignore = false; if c as u8 == b'*' { ignore = true; - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; } let mut width = String::new(); while c as u8 >= b'0' && c as u8 <= b'9' { width.push(wc_as_char!(c)); - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; } let mut width = if width.is_empty() { None @@ -156,7 +159,7 @@ unsafe fn inner_scanf( _ => break, } - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; } if c as u8 != b'n' { @@ -254,7 +257,7 @@ unsafe fn inner_scanf( n.parse::<$type>().map_err(|_| 0)? }; if !ignore { - *ap.arg::<*mut $type>() = n; + unsafe { *ap.arg::<*mut $type>() = n }; matched += 1; } }}; @@ -274,7 +277,7 @@ unsafe fn inner_scanf( $type::from_str_radix(&n, radix).map_err(|_| 0)? }; if !ignore { - *ap.arg::<*mut $final>() = n as $final; + unsafe { *ap.arg::<*mut $final>() = n as $final }; matched += 1; } }}; @@ -358,15 +361,18 @@ unsafe fn inner_scanf( } } - let mut ptr: Option<*mut $type> = - if ignore { None } else { Some(ap.arg()) }; + let mut ptr: Option<*mut $type> = if ignore { + None + } else { + Some(unsafe { ap.arg() }) + }; while width.map(|w| w > 0).unwrap_or(true) && !(wc_as_char!(wchar)).is_whitespace() { if let Some(ref mut ptr) = ptr { - **ptr = wchar as $type; - *ptr = ptr.offset(1); + unsafe { **ptr = wchar as $type }; + *ptr = unsafe { ptr.offset(1) }; } width = width.map(|w| w - 1); if width.map(|w| w > 0).unwrap_or(true) && !read!() { @@ -384,21 +390,28 @@ unsafe fn inner_scanf( } if c_kind == CharKind::Ascii { - parse_string_type!(c_char); + unsafe { + parse_string_type!(c_char); + } } else { - parse_string_type!(wchar_t); + unsafe { + parse_string_type!(wchar_t); + } } } b'c' => { macro_rules! parse_char_type { ($type:ident) => { - let ptr: Option<*mut $type> = - if ignore { None } else { Some(ap.arg()) }; + let ptr: Option<*mut $type> = if ignore { + None + } else { + Some(unsafe { ap.arg() }) + }; for i in 0..width.unwrap_or(1) { if let Some(ptr) = ptr { - *ptr.add(i) = wchar as $type; + unsafe { *ptr.add(i) = wchar as $type }; } width = width.map(|w| w - 1); if width.map(|w| w > 0).unwrap_or(true) && !read!() { @@ -422,11 +435,11 @@ unsafe fn inner_scanf( } b'[' => { - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; let mut matches = Vec::new(); let invert = if c as u8 == b'^' { - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; true } else { false @@ -436,12 +449,12 @@ unsafe fn inner_scanf( loop { matches.push(c); prev = c; - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; if c as u8 == b'-' { if prev as u8 == b']' { continue; } - c = next_char(&mut format)?; + c = unsafe { next_char(&mut format) }?; if c as u8 == b']' { matches.push('-' as wint_t); break; @@ -456,7 +469,11 @@ unsafe fn inner_scanf( } } - let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) }; + let mut ptr: Option<*mut c_char> = if ignore { + None + } else { + Some(unsafe { ap.arg() }) + }; // While we haven't used up all the width, and it matches let mut data_stored = false; @@ -464,8 +481,8 @@ unsafe fn inner_scanf( && !invert == matches.contains(&wchar) { if let Some(ref mut ptr) = ptr { - **ptr = wchar as c_char; - *ptr = ptr.offset(1); + unsafe { **ptr = wchar as c_char }; + *ptr = unsafe { ptr.offset(1) }; data_stored = true; } r.commit(); @@ -480,13 +497,13 @@ unsafe fn inner_scanf( } if data_stored { - *ptr.unwrap() = 0; + unsafe { *ptr.unwrap() = 0 }; matched += 1; } } b'n' => { if !ignore { - *ap.arg::<*mut c_int>() = count as c_int; + unsafe { *ap.arg::<*mut c_int>() = count as c_int }; } } _ => return Err(-1), @@ -507,7 +524,7 @@ unsafe fn inner_scanf( } pub unsafe fn scanf(r: LookAheadReader, format: *const wchar_t, ap: va_list) -> c_int { - match inner_scanf(r, format, ap) { + match unsafe { inner_scanf(r, format, ap) } { Ok(n) => n, Err(n) => n, }