Solve stdin/out/err UB in a better way
This commit is contained in:
Generated
+1
@@ -80,6 +80,7 @@ name = "crt0"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"platform 0.1.0",
|
||||
"stdio 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
|
||||
#define EOF (-1)
|
||||
#define BUFSIZ 1024
|
||||
#define stdin __stdin()
|
||||
#define stdout __stdout()
|
||||
#define stderr __stderr()
|
||||
|
||||
int fprintf(FILE * stream, const char * fmt, ...);
|
||||
int printf(const char * fmt, ...);
|
||||
|
||||
@@ -9,3 +9,4 @@ crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
platform = { path = "../platform" }
|
||||
stdio = { path = "../stdio" }
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
extern crate alloc;
|
||||
extern crate platform;
|
||||
extern crate stdio;
|
||||
|
||||
use alloc::Vec;
|
||||
use core::ptr;
|
||||
@@ -89,6 +90,11 @@ pub unsafe extern "C" fn _start_rust(sp: &'static Stack) -> ! {
|
||||
platform::inner_environ.push(ptr::null_mut());
|
||||
platform::environ = platform::inner_environ.as_mut_ptr();
|
||||
|
||||
// Initialize stdin/stdout/stderr, see https://github.com/rust-lang/rust/issues/51718
|
||||
stdio::stdin = stdio::default_stdin.get();
|
||||
stdio::stdout = stdio::default_stdout.get();
|
||||
stdio::stderr = stdio::default_stderr.get();
|
||||
|
||||
platform::exit(main(
|
||||
argc,
|
||||
argv as *const *const c_char,
|
||||
|
||||
+13
-20
@@ -1,37 +1,23 @@
|
||||
use super::{constants, BUFSIZ, FILE, UNGET};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::ptr;
|
||||
use core::sync::atomic::AtomicBool;
|
||||
|
||||
struct GlobalFile(UnsafeCell<FILE>);
|
||||
pub struct GlobalFile(UnsafeCell<FILE>);
|
||||
impl GlobalFile {
|
||||
const fn new(file: FILE) -> Self {
|
||||
GlobalFile(UnsafeCell::new(file))
|
||||
}
|
||||
fn get(&self) -> *mut FILE {
|
||||
pub fn get(&self) -> *mut FILE {
|
||||
self.0.get()
|
||||
}
|
||||
}
|
||||
// statics need to be Sync
|
||||
unsafe impl Sync for GlobalFile {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __stdin() -> *mut FILE {
|
||||
default_stdin.get()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __stdout() -> *mut FILE {
|
||||
default_stdout.get()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __stderr() -> *mut FILE {
|
||||
default_stderr.get()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
#[allow(non_upper_case_globals)]
|
||||
static ref default_stdin: GlobalFile = GlobalFile::new(FILE {
|
||||
pub static ref default_stdin: GlobalFile = GlobalFile::new(FILE {
|
||||
flags: constants::F_PERM | constants::F_NOWR,
|
||||
read: None,
|
||||
write: None,
|
||||
@@ -43,7 +29,7 @@ lazy_static! {
|
||||
});
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
static ref default_stdout: GlobalFile = GlobalFile::new(FILE {
|
||||
pub static ref default_stdout: GlobalFile = GlobalFile::new(FILE {
|
||||
flags: constants::F_PERM | constants::F_NORD,
|
||||
read: None,
|
||||
write: None,
|
||||
@@ -55,7 +41,7 @@ lazy_static! {
|
||||
});
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
static ref default_stderr: GlobalFile = GlobalFile::new(FILE {
|
||||
pub static ref default_stderr: GlobalFile = GlobalFile::new(FILE {
|
||||
flags: constants::F_PERM | constants::F_NORD,
|
||||
read: None,
|
||||
write: None,
|
||||
@@ -66,3 +52,10 @@ lazy_static! {
|
||||
lock: AtomicBool::new(false),
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut stdin: *mut FILE = ptr::null_mut();
|
||||
#[no_mangle]
|
||||
pub static mut stdout: *mut FILE = ptr::null_mut();
|
||||
#[no_mangle]
|
||||
pub static mut stderr: *mut FILE = ptr::null_mut();
|
||||
|
||||
@@ -643,7 +643,7 @@ pub extern "C" fn getc(stream: &mut FILE) -> c_int {
|
||||
/// Get a single char from `stdin`
|
||||
#[no_mangle]
|
||||
pub extern "C" fn getchar() -> c_int {
|
||||
fgetc(unsafe { &mut *__stdin() })
|
||||
fgetc(unsafe { &mut *stdin })
|
||||
}
|
||||
|
||||
/// Get a char from a stream without locking the stream
|
||||
@@ -676,14 +676,14 @@ pub extern "C" fn getc_unlocked(stream: &mut FILE) -> c_int {
|
||||
/// Get a char from `stdin` without locking `stdin`
|
||||
#[no_mangle]
|
||||
pub extern "C" fn getchar_unlocked() -> c_int {
|
||||
getc_unlocked(unsafe { &mut *__stdin() })
|
||||
getc_unlocked(unsafe { &mut *stdin })
|
||||
}
|
||||
|
||||
/// Get a string from `stdin`
|
||||
#[no_mangle]
|
||||
pub extern "C" fn gets(s: *mut c_char) -> *mut c_char {
|
||||
use core::i32;
|
||||
fgets(s, i32::MAX, unsafe { &mut *__stdin() })
|
||||
fgets(s, i32::MAX, unsafe { &mut *stdin })
|
||||
}
|
||||
|
||||
/// Get an integer from `stream`
|
||||
@@ -740,7 +740,7 @@ pub extern "C" fn putc(c: c_int, stream: &mut FILE) -> c_int {
|
||||
/// Put a character `c` into `stdout`
|
||||
#[no_mangle]
|
||||
pub extern "C" fn putchar(c: c_int) -> c_int {
|
||||
fputc(c, unsafe { &mut *__stdout() })
|
||||
fputc(c, unsafe { &mut *stdout })
|
||||
}
|
||||
|
||||
/// Put a character `c` into `stream` without locking `stream`
|
||||
@@ -768,13 +768,13 @@ pub extern "C" fn putc_unlocked(c: c_int, stream: &mut FILE) -> c_int {
|
||||
/// Put a character `c` into `stdout` without locking `stdout`
|
||||
#[no_mangle]
|
||||
pub extern "C" fn putchar_unlocked(c: c_int) -> c_int {
|
||||
putc_unlocked(c, unsafe { &mut *__stdout() })
|
||||
putc_unlocked(c, unsafe { &mut *stdout })
|
||||
}
|
||||
|
||||
/// Put a string `s` into `stdout`
|
||||
#[no_mangle]
|
||||
pub extern "C" fn puts(s: *const c_char) -> c_int {
|
||||
let ret = (fputs(s, unsafe { &mut *__stdout() }) > 0) || (putchar_unlocked(b'\n' as c_int) > 0);
|
||||
let ret = (fputs(s, unsafe { &mut *stdout }) > 0) || (putchar_unlocked(b'\n' as c_int) > 0);
|
||||
if ret {
|
||||
0
|
||||
} else {
|
||||
@@ -918,7 +918,7 @@ pub unsafe extern "C" fn vfprintf(file: &mut FILE, format: *const c_char, ap: va
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn vprintf(format: *const c_char, ap: va_list) -> c_int {
|
||||
vfprintf(&mut *__stdout(), format, ap)
|
||||
vfprintf(&mut *stdout, format, ap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -947,7 +947,7 @@ pub unsafe extern "C" fn vfscanf(file: &mut FILE, format: *const c_char, ap: va_
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn vscanf(format: *const c_char, ap: va_list) -> c_int {
|
||||
vfscanf(&mut *__stdin(), format, ap)
|
||||
vfscanf(&mut *stdin, format, ap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -70,10 +70,10 @@ unsafe fn parse_arg(
|
||||
|
||||
let print_error = |desc: &[u8]| {
|
||||
// NOTE: we don't use fprintf to get around the usage of va_list
|
||||
stdio::fputs(*argv as _, &mut *stdio::__stderr());
|
||||
stdio::fputs(desc.as_ptr() as _, &mut *stdio::__stderr());
|
||||
stdio::fputc(*current_arg as _, &mut *stdio::__stderr());
|
||||
stdio::fputc(b'\n' as _, &mut *stdio::__stderr());
|
||||
stdio::fputs(*argv as _, &mut *stdio::stderr);
|
||||
stdio::fputs(desc.as_ptr() as _, &mut *stdio::stderr);
|
||||
stdio::fputc(*current_arg as _, &mut *stdio::stderr);
|
||||
stdio::fputc(b'\n' as _, &mut *stdio::stderr);
|
||||
};
|
||||
|
||||
match find_option(*current_arg, optstring) {
|
||||
|
||||
@@ -203,7 +203,7 @@ pub unsafe extern "C" fn putwc(wc: wchar_t, stream: *mut FILE) -> wint_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn putwchar(wc: wchar_t) -> wint_t {
|
||||
fputwc(wc, &mut *__stdout())
|
||||
fputwc(wc, &mut *stdout)
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
144
|
||||
st_mode: 33188
|
||||
st_size: 383
|
||||
st_blksize: 4096
|
||||
Reference in New Issue
Block a user