mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(permissions): fallback to denied access if the permission prompt fails (#14235)
This commit is contained in:
parent
9c5928b5aa
commit
7919dc902d
1 changed files with 34 additions and 23 deletions
|
@ -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<bool, AnyError> {
|
||||
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!(
|
||||
|
|
Loading…
Reference in a new issue