From b11f0719763741090f927630671c076b07d68022 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 26 Sep 2018 11:00:11 -0400 Subject: [PATCH] Rewrite android logging to use checked slices. --- ports/libsimpleservo/src/jniapi.rs | 81 ++++++++++++++++-------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/ports/libsimpleservo/src/jniapi.rs b/ports/libsimpleservo/src/jniapi.rs index 85b9b1e7952a..70a656527270 100644 --- a/ports/libsimpleservo/src/jniapi.rs +++ b/ports/libsimpleservo/src/jniapi.rs @@ -14,7 +14,6 @@ use libc::{pipe, dup2, read}; use log::Level; use std; use std::borrow::Cow; -use std::ffi::CString; use std::os::raw::{c_char, c_int, c_void}; use std::sync::{Arc, Mutex}; use std::thread; @@ -466,51 +465,57 @@ fn redirect_stdout_to_logcat() { // Then we spawn a thread whose only job is to read from the other side of the // pipe and redirect to the logs. let _detached = thread::spawn(move || { - unsafe { - let mut buf: Vec = Vec::with_capacity(512); - let mut cursor = 0_usize; - - // TODO: shouldn't use Rust stdlib - let tag = CString::new("simpleservo").unwrap(); - let tag = tag.as_ptr(); - - loop { - let result = read(descriptor, buf.as_mut_ptr().offset(cursor as isize) as *mut _, - buf.capacity() - 1 - cursor); - - let len = if result == 0 { - return; - } else if result < 0 { - return; /* TODO: report problem */ - } else { - result as usize + cursor - }; + const BUF_LENGTH: usize = 512; + let mut buf = vec![b'\0' as c_char; BUF_LENGTH]; + + // Always keep at least one null terminator + const BUF_AVAILABLE: usize = BUF_LENGTH - 1; + let buf = &mut buf[..BUF_AVAILABLE]; - buf.set_len(len); + let mut cursor = 0_usize; - if let Some(last_newline_pos) = buf.iter().rposition(|&c| c == b'\n' as c_char) { - buf[last_newline_pos] = b'\0' as c_char; + let tag = b"simpleservo\0".as_ptr() as _; + + loop { + let result = { + let read_into = &mut buf[cursor..]; + unsafe { + read(descriptor, read_into.as_mut_ptr() as *mut _, read_into.len()) + } + }; + + let end = if result == 0 { + return; + } else if result < 0 { + return; /* TODO: report problem */ + } else { + result as usize + cursor + }; + + if let Some(last_newline_pos) = buf.iter().rposition(|&c| c == b'\n' as c_char) { + buf[last_newline_pos] = b'\0' as c_char; + unsafe { __android_log_write(3, tag, buf.as_ptr()); - if last_newline_pos < buf.len() - 1 { - let last_newline_pos = last_newline_pos + 1; - cursor = buf.len() - last_newline_pos; - debug_assert!(cursor < buf.capacity()); - for j in 0..cursor as usize { - buf[j] = buf[last_newline_pos + j]; - } - buf[cursor] = b'\0' as c_char; - buf.set_len(cursor + 1); - } else { - cursor = 0; + } + if last_newline_pos < buf.len() - 1 { + let pos_after_newline = last_newline_pos + 1; + let len_not_logged_yet = buf[pos_after_newline..].len(); + for j in 0..len_not_logged_yet as usize { + buf[j] = buf[pos_after_newline + j]; } + cursor = len_not_logged_yet; } else { - cursor = buf.len(); + cursor = 0; } - if cursor == buf.capacity() - 1 { + } else if cursor == BUF_AVAILABLE { + // No newline found but the buffer is full, flush it anyway. + // `buf.as_ptr()` is null-terminated by BUF_LENGTH being 1 less than BUF_AVAILABLE. + unsafe { __android_log_write(3, tag, buf.as_ptr()); - buf.set_len(0); - cursor = 0; } + cursor = 0; + } else { + cursor = end; } } });