From 7919dc902d3664bb8600be884ec775f44fd37389 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 18 Apr 2022 09:00:38 -0400 Subject: [PATCH] fix(permissions): fallback to denied access if the permission prompt fails (#14235) --- runtime/permissions.rs | 57 +++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/runtime/permissions.rs b/runtime/permissions.rs index 095e67467c..be6c0c188d 100644 --- a/runtime/permissions.rs +++ b/runtime/permissions.rs @@ -1885,13 +1885,15 @@ fn permission_prompt(message: &str, name: &str) -> bool { }; #[cfg(unix)] - fn clear_stdin() { + fn clear_stdin() -> Result<(), AnyError> { let r = unsafe { libc::tcflush(0, libc::TCIFLUSH) }; assert_eq!(r, 0); + Ok(()) } #[cfg(not(unix))] - fn clear_stdin() { + fn clear_stdin() -> Result<(), AnyError> { + use deno_core::anyhow::bail; use winapi::shared::minwindef::TRUE; use winapi::shared::minwindef::UINT; use winapi::shared::minwindef::WORD; @@ -1911,31 +1913,34 @@ fn permission_prompt(message: &str, name: &str) -> bool { unsafe { let stdin = GetStdHandle(STD_INPUT_HANDLE); // emulate an enter key press to clear any line buffered console characters - emulate_enter_key_press(stdin); + emulate_enter_key_press(stdin)?; // read the buffered line or enter key press - read_stdin_line(); + read_stdin_line()?; // check if our emulated key press was executed - if is_input_buffer_empty(stdin) { + if is_input_buffer_empty(stdin)? { // if so, move the cursor up to prevent a blank line - move_cursor_up(); + move_cursor_up()?; } else { // the emulated key press is still pending, so a buffered line was read // and we can flush the emulated key press - flush_input_buffer(stdin); + flush_input_buffer(stdin)?; } } - unsafe fn flush_input_buffer(stdin: HANDLE) { + return Ok(()); + + unsafe fn flush_input_buffer(stdin: HANDLE) -> Result<(), AnyError> { let success = FlushConsoleInputBuffer(stdin); if success != TRUE { - panic!( - "Error flushing console input buffer: {}", + bail!( + "Could not flush the console input buffer: {}", std::io::Error::last_os_error() ) } + Ok(()) } - unsafe fn emulate_enter_key_press(stdin: HANDLE) { + unsafe fn emulate_enter_key_press(stdin: HANDLE) -> Result<(), AnyError> { // https://github.com/libuv/libuv/blob/a39009a5a9252a566ca0704d02df8dabc4ce328f/src/win/tty.c#L1121-L1131 let mut input_record: INPUT_RECORD = std::mem::zeroed(); input_record.EventType = KEY_EVENT; @@ -1951,42 +1956,48 @@ fn permission_prompt(message: &str, name: &str) -> bool { let success = WriteConsoleInputW(stdin, &input_record, 1, &mut record_written); if success != TRUE { - panic!( - "Error emulating enter key press: {}", + bail!( + "Could not emulate enter key press: {}", std::io::Error::last_os_error() - ) + ); } + Ok(()) } - unsafe fn is_input_buffer_empty(stdin: HANDLE) -> bool { + unsafe fn is_input_buffer_empty(stdin: HANDLE) -> Result { let mut buffer = Vec::with_capacity(1); let mut events_read = 0; let success = PeekConsoleInputW(stdin, buffer.as_mut_ptr(), 1, &mut events_read); if success != TRUE { - panic!( - "Error peeking console input buffer: {}", + bail!( + "Could not peek the console input buffer: {}", std::io::Error::last_os_error() ) } - events_read == 0 + Ok(events_read == 0) } - fn move_cursor_up() { + fn move_cursor_up() -> Result<(), AnyError> { use std::io::Write; - write!(std::io::stderr(), "\x1B[1A").expect("expected to move cursor up"); + write!(std::io::stderr(), "\x1B[1A")?; + Ok(()) } - fn read_stdin_line() { + fn read_stdin_line() -> Result<(), AnyError> { let mut input = String::new(); let stdin = std::io::stdin(); - stdin.read_line(&mut input).expect("expected to read line"); + stdin.read_line(&mut input)?; + Ok(()) } } // For security reasons we must consume everything in stdin so that previously // buffered data cannot effect the prompt. - clear_stdin(); + if let Err(err) = clear_stdin() { + eprintln!("Error clearing stdin for permission prompt. {:#}", err); + return false; // don't grant permission if this fails + } let opts = "[y/n (y = yes allow, n = no deny)] "; let msg = format!(