Repository: microsoft/edit
File: src/tui.rs (Rust)

Code before:
        // which will become `arena_next` and get reset. It's safe to reset and reuse its memory.
        mem::swap(&mut self.arena_prev, &mut self.arena_next);
        unsafe { self.arena_next.reset(0) };

        // In the input handler below we transformed a mouse up into a release event.
        // Now, a frame later, we must reset it back to none, to stop it from triggering things.
        // Same for Scroll events.
        if self.mouse_state > InputMouseState::Right {
            self.mouse_down_position = Point::MIN;
            self.mouse_down_node_path.clear();
            self.left_mouse_down_target = 0;
            self.mouse_state = InputMouseState::None;
            self.mouse_is_drag = false;
        }

        if self.scroll_to_focused() {
            self.needs_more_settling();
        }

        let now = std::time::Instant::now();
        let mut input_text = None;
        let mut input_keyboard = None;
        let mut input_mouse_modifiers = kbmod::NONE;
        let mut input_mouse_click = 0;
        let mut input_scroll_delta = Point { x: 0, y: 0 };
        let input_consumed = input.is_none();

        match input {
            None => {}
            Some(Input::Resize(resize)) => {
                assert!(resize.width > 0 && resize.height > 0);
                assert!(resize.width < 32768 && resize.height < 32768);
                self.size = resize;
            }
            Some(Input::Text(text)) => {
                input_text = Some(text);
                // TODO: the .len()==1 check causes us to ignore keyboard inputs that are faster than we process them.
                // For instance, imagine the user presses "A" twice and we happen to read it in a single chunk.
                // This causes us to ignore the keyboard input here. We need a way to inform the caller over
                // how much of the input text we actually processed in a single frame. Or perhaps we could use
                // the needs_settling logic?
                if !text.bracketed && text.text.len() == 1 {
                    let ch = text.text.as_bytes()[0];
                    input_keyboard = InputKey::from_ascii(ch as char)
                }
            }
            Some(Input::Keyboard(keyboard)) => {
                input_keyboard = Some(keyboard);
            }
            Some(Input::Mouse(mouse)) => {
                let mut next_state = mouse.state;

Review comment (security):
An extra fix I smuggled in, as described in the comment. Found during testing by manually injecting a lone Escape followed by another character within the same input payload.

Code after:
        // which will become `arena_next` and get reset. It's safe to reset and reuse its memory.
        mem::swap(&mut self.arena_prev, &mut self.arena_next);
        unsafe { self.arena_next.reset(0) };

        // In the input handler below we transformed a mouse up into a release event.
        // Now, a frame later, we must reset it back to none, to stop it from triggering things.
        // Same for Scroll events.
        if self.mouse_state > InputMouseState::Right {
            self.mouse_down_position = Point::MIN;
            self.mouse_down_node_path.clear();
            self.left_mouse_down_target = 0;
            self.mouse_state = InputMouseState::None;
            self.mouse_is_drag = false;
        }

        let now = std::time::Instant::now();
        let mut input_text = None;
        let mut input_keyboard = None;
        let mut input_mouse_modifiers = kbmod::NONE;
        let mut input_mouse_click = 0;
        let mut input_scroll_delta = Point { x: 0, y: 0 };
        // `input_consumed` should be `true` if we're in the settling phase which is indicated by
        // `self.needs_settling() == true`. However, there's a possibility for it being true from
        // a previous frame, and we do have fresh new input. In that case want `input_consumed`
        // to be false of course which is ensured by checking for `input.is_none()`.
        let input_consumed = self.needs_settling() && input.is_none();

        if self.scroll_to_focused() {
            self.needs_more_settling();
        }

        match input {
            None => {}
            Some(Input::Resize(resize)) => {
                assert!(resize.width > 0 && resize.height > 0);
                assert!(resize.width < 32768 && resize.height < 32768);
                self.size = resize;
            }
            Some(Input::Text(text)) => {
                input_text = Some(text);
                // TODO: the .len()==1 check causes us to ignore keyboard inputs that are faster than we process them.
                // For instance, imagine the user presses "A" twice and we happen to read it in a single chunk.
                // This causes us to ignore the keyboard input here. We need a way to inform the caller over
                // how much of the input text we actually processed in a single frame. Or perhaps we could use
                // the needs_settling logic?
                if !text.bracketed && text.text.len() == 1 {
                    let ch = text.text.as_bytes()[0];
                    input_keyboard = InputKey::from_ascii(ch as char)
                }
            }
            Some(Input::Keyboard(keyboard)) => {