From e749d2303093a397f90cdbf5bd5ab20edffcf2fc Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 25 Jul 2018 14:29:14 +0200 Subject: [PATCH] Solve stdin/out/err UB in a better way --- Cargo.lock | 1 + include/bits/stdio.h | 3 --- src/crt0/Cargo.toml | 1 + src/crt0/src/lib.rs | 6 ++++++ src/stdio/src/default.rs | 33 ++++++++++++------------------- src/stdio/src/lib.rs | 16 +++++++-------- src/unistd/src/getopt.rs | 8 ++++---- src/wchar/src/lib.rs | 2 +- tests/expected/unistd/stat.stderr | 0 tests/expected/unistd/stat.stdout | 4 ---- 10 files changed, 34 insertions(+), 40 deletions(-) delete mode 100644 tests/expected/unistd/stat.stderr delete mode 100644 tests/expected/unistd/stat.stdout diff --git a/Cargo.lock b/Cargo.lock index b5492d7c19..7e7ba2db35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,7 @@ name = "crt0" version = "0.1.0" dependencies = [ "platform 0.1.0", + "stdio 0.1.0", ] [[package]] diff --git a/include/bits/stdio.h b/include/bits/stdio.h index a4e2578d5d..b20ee2bd9b 100644 --- a/include/bits/stdio.h +++ b/include/bits/stdio.h @@ -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, ...); diff --git a/src/crt0/Cargo.toml b/src/crt0/Cargo.toml index 0b82f468c5..9133360068 100644 --- a/src/crt0/Cargo.toml +++ b/src/crt0/Cargo.toml @@ -9,3 +9,4 @@ crate-type = ["staticlib"] [dependencies] platform = { path = "../platform" } +stdio = { path = "../stdio" } diff --git a/src/crt0/src/lib.rs b/src/crt0/src/lib.rs index c9f1a84c1e..c9cc2739a4 100644 --- a/src/crt0/src/lib.rs +++ b/src/crt0/src/lib.rs @@ -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, diff --git a/src/stdio/src/default.rs b/src/stdio/src/default.rs index c9bb96f1ca..5928254178 100644 --- a/src/stdio/src/default.rs +++ b/src/stdio/src/default.rs @@ -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); +pub struct GlobalFile(UnsafeCell); 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(); diff --git a/src/stdio/src/lib.rs b/src/stdio/src/lib.rs index c2af6d3b61..ef75bc4f07 100644 --- a/src/stdio/src/lib.rs +++ b/src/stdio/src/lib.rs @@ -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] diff --git a/src/unistd/src/getopt.rs b/src/unistd/src/getopt.rs index 044d70c379..29d77b4df6 100644 --- a/src/unistd/src/getopt.rs +++ b/src/unistd/src/getopt.rs @@ -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) { diff --git a/src/wchar/src/lib.rs b/src/wchar/src/lib.rs index 02c679cd27..fdeb25becf 100644 --- a/src/wchar/src/lib.rs +++ b/src/wchar/src/lib.rs @@ -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] diff --git a/tests/expected/unistd/stat.stderr b/tests/expected/unistd/stat.stderr deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/expected/unistd/stat.stdout b/tests/expected/unistd/stat.stdout deleted file mode 100644 index 74f3a92e9e..0000000000 --- a/tests/expected/unistd/stat.stdout +++ /dev/null @@ -1,4 +0,0 @@ -144 -st_mode: 33188 -st_size: 383 -st_blksize: 4096