fix(renderer.Loop): prevent read buffer overflow on very large escape sequences
This commit is contained in:
		
							parent
							
								
									d9a4e5e38d
								
							
						
					
					
						commit
						c9debbabf4
					
				
					 1 changed files with 36 additions and 36 deletions
				
			
		| 
						 | 
				
			
			@ -407,11 +407,7 @@ const Loop = struct {
 | 
			
		|||
    /// spawns the input thread to read input from the tty
 | 
			
		||||
    pub fn start(self: *Loop) !void {
 | 
			
		||||
        if (self.thread) |_| return;
 | 
			
		||||
        self.thread = try std.Thread.spawn(.{}, Loop.ttyRun, .{
 | 
			
		||||
            self,
 | 
			
		||||
            &self.vaxis.unicode.grapheme_data,
 | 
			
		||||
            self.vaxis.opts.system_clipboard_allocator,
 | 
			
		||||
        });
 | 
			
		||||
        self.thread = try std.Thread.spawn(.{}, Loop.ttyRun, .{self});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// stops reading from the tty.
 | 
			
		||||
| 
						 | 
				
			
			@ -444,12 +440,7 @@ const Loop = struct {
 | 
			
		|||
        self.pid.send(.{ "VXS", std.mem.asBytes(&event) }) catch @panic("send VXS event failed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// read input from the tty. This is run in a separate thread
 | 
			
		||||
    fn ttyRun(
 | 
			
		||||
        self: *Loop,
 | 
			
		||||
        grapheme_data: *const vaxis.grapheme.GraphemeData,
 | 
			
		||||
        paste_allocator: ?std.mem.Allocator,
 | 
			
		||||
    ) !void {
 | 
			
		||||
    fn ttyRun(self: *Loop) !void {
 | 
			
		||||
        switch (builtin.os.tag) {
 | 
			
		||||
            .windows => {
 | 
			
		||||
                while (!self.should_quit) {
 | 
			
		||||
| 
						 | 
				
			
			@ -457,41 +448,50 @@ const Loop = struct {
 | 
			
		|||
                }
 | 
			
		||||
            },
 | 
			
		||||
            else => {
 | 
			
		||||
                // get our initial winsize
 | 
			
		||||
                const winsize = try vaxis.Tty.getWinsize(self.tty.fd);
 | 
			
		||||
                if (@hasField(Event, "winsize")) {
 | 
			
		||||
                    self.postEvent(.{ .winsize = winsize });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var parser: vaxis.Parser = .{
 | 
			
		||||
                    .grapheme_data = grapheme_data,
 | 
			
		||||
                    .grapheme_data = &self.vaxis.unicode.grapheme_data,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                // initialize the read buffer
 | 
			
		||||
                var buf: [1024]u8 = undefined;
 | 
			
		||||
                var read_start: usize = 0;
 | 
			
		||||
                // read loop
 | 
			
		||||
                while (!self.should_quit) {
 | 
			
		||||
                    const n = try self.tty.read(buf[read_start..]);
 | 
			
		||||
                    var seq_start: usize = 0;
 | 
			
		||||
                    while (seq_start < n) {
 | 
			
		||||
                        const result = try parser.parse(buf[seq_start..n], paste_allocator);
 | 
			
		||||
                        if (result.n == 0) {
 | 
			
		||||
                            // copy the read to the beginning. We don't use memcpy because
 | 
			
		||||
                            // this could be overlapping, and it's also rare
 | 
			
		||||
                            const initial_start = seq_start;
 | 
			
		||||
                            while (seq_start < n) : (seq_start += 1) {
 | 
			
		||||
                                buf[seq_start - initial_start] = buf[seq_start];
 | 
			
		||||
                            }
 | 
			
		||||
                            read_start = seq_start - initial_start + 1;
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        read_start = 0;
 | 
			
		||||
                        seq_start += result.n;
 | 
			
		||||
                const a = self.vaxis.opts.system_clipboard_allocator orelse @panic("no tty allocator");
 | 
			
		||||
 | 
			
		||||
                        const event = result.event orelse continue;
 | 
			
		||||
                        self.postEvent(event);
 | 
			
		||||
                var buf = try a.alloc(u8, 512);
 | 
			
		||||
                defer a.free(buf);
 | 
			
		||||
                var n: usize = 0;
 | 
			
		||||
                var need_read = false;
 | 
			
		||||
 | 
			
		||||
                while (!self.should_quit) {
 | 
			
		||||
                    if (n >= buf.len) {
 | 
			
		||||
                        const buf_grow = try a.alloc(u8, buf.len * 2);
 | 
			
		||||
                        @memcpy(buf_grow[0..buf.len], buf);
 | 
			
		||||
                        a.free(buf);
 | 
			
		||||
                        buf = buf_grow;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (n == 0 or need_read) {
 | 
			
		||||
                        const n_ = try self.tty.read(buf[n..]);
 | 
			
		||||
                        n = n + n_;
 | 
			
		||||
                        need_read = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    const result = try parser.parse(buf[0..n], a);
 | 
			
		||||
                    if (result.n == 0) {
 | 
			
		||||
                        need_read = true;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (result.n < n) {
 | 
			
		||||
                        const buf_move = try a.alloc(u8, buf.len);
 | 
			
		||||
                        @memcpy(buf_move[0 .. n - result.n], buf[result.n..n]);
 | 
			
		||||
                        a.free(buf);
 | 
			
		||||
                        buf = buf_move;
 | 
			
		||||
                        n = n - result.n;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        n = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                    const event = result.event orelse continue;
 | 
			
		||||
                    self.postEvent(event);
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue