From 2f4e57f87af72f3c14ec6dc48557d88f54ee3b24 Mon Sep 17 00:00:00 2001
From: jD91mZM2 <me@krake.one>
Date: Wed, 26 Jun 2019 21:20:48 +0200
Subject: [PATCH] Fix data race inside puts(...) & add dbg!() macro

---
 src/header/stdio/mod.rs | 23 ++++++++++++++---------
 src/macros.rs           | 19 +++++++++++++++++++
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
index dd1fad2fe..7059ad05c 100644
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -61,7 +61,6 @@ impl<'a> DerefMut for Buffer<'a> {
 
 /// This struct gets exposed to the C API.
 pub struct FILE {
-    // Can't use spin crate because *_unlocked functions are things in C :(
     lock: Mutex<()>,
 
     file: File,
@@ -417,8 +416,10 @@ pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
 /// Insert a string into a stream
 #[no_mangle]
 pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
-    let len = strlen(s);
-    (fwrite(s as *const c_void, 1, len, stream) == len) as c_int - 1
+    let mut stream = (*stream).lock();
+    let buf = slice::from_raw_parts(s as *mut u8, strlen(s));
+
+    if stream.write_all(&buf).is_ok() { 0 } else { -1 }
 }
 
 /// Read `nitems` of size `size` into `ptr` from `stream`
@@ -577,7 +578,7 @@ pub unsafe extern "C" fn fwrite(
         return 0;
     }
     let mut stream = (*stream).lock();
-    let buf = slice::from_raw_parts_mut(ptr as *mut u8, size as usize * nitems as usize);
+    let buf = slice::from_raw_parts(ptr as *const u8, size as usize * nitems as usize);
     let mut written = 0;
     while written < buf.len() {
         match stream.write(&buf[written..]) {
@@ -798,12 +799,16 @@ pub unsafe extern "C" fn putchar_unlocked(c: c_int) -> c_int {
 /// Put a string `s` into `stdout`
 #[no_mangle]
 pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
-    let ret = (fputs(s, stdout) > 0) || (putchar_unlocked(b'\n' as c_int) > 0);
-    if ret {
-        0
-    } else {
-        -1
+    let mut stream = (&mut *stdout).lock();
+    let buf = slice::from_raw_parts(s as *mut u8, strlen(s));
+
+    if stream.write_all(&buf).is_err() {
+        return -1;
     }
+    if stream.write(&[b'\n']).is_err() {
+        return -1;
+    }
+    0
 }
 
 /// Put an integer `w` into `stream`
diff --git a/src/macros.rs b/src/macros.rs
index e9ca07c16..f870522b9 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -42,6 +42,25 @@ macro_rules! eprintln {
     ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
 }
 
+/// Lifted from libstd
+#[macro_export]
+macro_rules! dbg {
+    () => {
+        eprintln!("[{}:{}]", file!(), line!());
+    };
+    ($val:expr) => {
+        // Use of `match` here is intentional because it affects the lifetimes
+        // of temporaries - https://stackoverflow.com/a/48732525/1063961
+        match $val {
+            tmp => {
+                eprintln!("[{}:{}] {} = {:#?}",
+                    file!(), line!(), stringify!($val), &tmp);
+                tmp
+            }
+        }
+    }
+}
+
 #[macro_export]
 #[cfg(not(feature = "trace"))]
 macro_rules! trace {
-- 
GitLab