From b26213731c7a459f54ed80eabd0cfe584ca7d01e Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Wed, 8 Aug 2018 13:25:26 +0200 Subject: [PATCH] Don't forget to lock stdout when printfing --- src/platform/src/lib.rs | 34 +++++++++++++++-------------- src/stdio/src/lib.rs | 48 ++++++++++++++++++++++++++--------------- src/stdio/src/scanf.rs | 12 +++++++---- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs index 1921a024..37964737 100644 --- a/src/platform/src/lib.rs +++ b/src/platform/src/lib.rs @@ -129,12 +129,12 @@ impl<'a, W: Write> Write for &'a mut W { } pub trait Read { - fn read_u8(&mut self, byte: &mut u8) -> bool; + fn read_u8(&mut self) -> Result<Option<u8>, ()>; } impl<'a, R: Read> Read for &'a mut R { - fn read_u8(&mut self, byte: &mut u8) -> bool { - (**self).read_u8(byte) + fn read_u8(&mut self) -> Result<Option<u8>, ()> { + (**self).read_u8() } } @@ -169,11 +169,13 @@ impl FileReader { } impl Read for FileReader { - fn read_u8(&mut self, byte: &mut u8) -> bool { - let mut buf = [*byte]; - let n = self.read(&mut buf); - *byte = buf[0]; - n > 0 + fn read_u8(&mut self) -> Result<Option<u8>, ()> { + let mut buf = [0]; + match self.read(&mut buf) { + 0 => Ok(None), + n if n < 0 => Err(()), + _ => Ok(Some(buf[0])) + } } } @@ -241,13 +243,13 @@ impl Write for UnsafeStringWriter { pub struct StringReader<'a>(pub &'a [u8]); impl<'a> Read for StringReader<'a> { - fn read_u8(&mut self, byte: &mut u8) -> bool { + fn read_u8(&mut self) -> Result<Option<u8>, ()> { if self.0.is_empty() { - false + Ok(None) } else { - *byte = self.0[0]; + let byte = self.0[0]; self.0 = &self.0[1..]; - true + Ok(Some(byte)) } } } @@ -255,14 +257,14 @@ impl<'a> Read for StringReader<'a> { pub struct UnsafeStringReader(pub *const u8); impl Read for UnsafeStringReader { - fn read_u8(&mut self, byte: &mut u8) -> bool { + fn read_u8(&mut self) -> Result<Option<u8>, ()> { unsafe { if *self.0 == 0 { - false + Ok(None) } else { - *byte = *self.0; + let byte = *self.0; self.0 = self.0.offset(1); - true + Ok(Some(byte)) } } } diff --git a/src/stdio/src/lib.rs b/src/stdio/src/lib.rs index e9b25a8f..993a88ff 100644 --- a/src/stdio/src/lib.rs +++ b/src/stdio/src/lib.rs @@ -16,7 +16,7 @@ extern crate string; extern crate va_list as vl; use core::fmt::Write as WriteFmt; -use core::fmt::{self, Error, Result}; +use core::fmt::{self, Error}; use core::sync::atomic::{AtomicBool, Ordering}; use core::{ptr, str}; @@ -171,38 +171,52 @@ impl FILE { pub fn seek(&self, off: off_t, whence: c_int) -> off_t { platform::lseek(self.fd, off, whence) } + + pub fn lock(&mut self) -> LockGuard { + flockfile(self); + LockGuard(self) + } +} + +pub struct LockGuard<'a>(&'a mut FILE); +impl<'a> Drop for LockGuard<'a> { + fn drop(&mut self) { + funlockfile(self.0); + } } -impl fmt::Write for FILE { - fn write_str(&mut self, s: &str) -> Result { - if !self.can_write() { + +impl<'a> fmt::Write for LockGuard<'a> { + fn write_str(&mut self, s: &str) -> fmt::Result { + if !self.0.can_write() { return Err(Error); } let s = s.as_bytes(); - if self.write(s) != s.len() { + if self.0.write(s) != s.len() { Err(Error) } else { Ok(()) } } } -impl Write for FILE { - fn write_u8(&mut self, byte: u8) -> Result { - if !self.can_write() { +impl<'a> Write for LockGuard<'a> { + fn write_u8(&mut self, byte: u8) -> fmt::Result { + if !self.0.can_write() { return Err(Error); } - if self.write(&[byte]) != 1 { + if self.0.write(&[byte]) != 1 { Err(Error) } else { Ok(()) } } } -impl Read for FILE { - fn read_u8(&mut self, byte: &mut u8) -> bool { - let mut buf = [*byte]; - let n = self.read(&mut buf); - *byte = buf[0]; - n > 0 +impl<'a> Read for LockGuard<'a> { + fn read_u8(&mut self) -> Result<Option<u8>, ()> { + let mut buf = [0]; + match self.0.read(&mut buf) { + 0 => Ok(None), + _ => Ok(Some(buf[0])) + } } } @@ -913,7 +927,7 @@ pub extern "C" fn ungetc(c: c_int, stream: &mut FILE) -> c_int { #[no_mangle] pub unsafe extern "C" fn vfprintf(file: &mut FILE, format: *const c_char, ap: va_list) -> c_int { - printf::printf(file, format, ap) + printf::printf(file.lock(), format, ap) } #[no_mangle] @@ -942,7 +956,7 @@ pub unsafe extern "C" fn vsprintf(s: *mut c_char, format: *const c_char, ap: va_ #[no_mangle] pub unsafe extern "C" fn vfscanf(file: &mut FILE, format: *const c_char, ap: va_list) -> c_int { - scanf::scanf(file, format, ap) + scanf::scanf(file.lock(), format, ap) } #[no_mangle] diff --git a/src/stdio/src/scanf.rs b/src/stdio/src/scanf.rs index 2a1ae921..2652c141 100644 --- a/src/stdio/src/scanf.rs +++ b/src/stdio/src/scanf.rs @@ -39,11 +39,15 @@ unsafe fn inner_scanf<R: Read>( macro_rules! read { () => {{ - let n = r.read_u8(&mut byte); - if n { - count += 1; + match r.read_u8() { + Ok(Some(b)) => { + byte = b; + count += 1; + true + }, + Ok(None) => false, + Err(()) => return Err(-1) } - n }}; } -- GitLab