From e712314f31b55d84b689732cc6def8015e74c514 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 3 Dec 2024 08:57:42 -0500 Subject: [PATCH] terminal: PageList.reset has to zero arena memory to avoid reuse Fixes #2877 As the comment in the diff states, we rely on `mmap` to zero our memory. When we reset we are reusing previously allocated memory so we won't hit an `mmap`. We need to zero the memory ourselves. This is pretty slow if there is a lot of memory but in every case except allocation failures, we expect there to be only a few pages allocated. --- src/terminal/PageList.zig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index aec0af278..01e7ed71d 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -378,6 +378,25 @@ pub fn reset(self: *PageList) void { .retain_with_limit = page_count * NodePool.item_size, }); + // Our page pool relies on mmap to zero our page memory. Since we're + // retaining a certain amount of memory, it won't use mmap and won't + // be zeroed. This block zeroes out all the memory in the pool arena. + { + // Note: we only have to do this for the page pool because the + // nodes are always fully overwritten on each allocation. + const page_arena = &self.pool.pages.arena; + var it = page_arena.state.buffer_list.first; + while (it) |node| : (it = node.next) { + // The fully allocated buffer + const alloc_buf = @as([*]u8, @ptrCast(node))[0..node.data]; + + // The buffer minus our header + const BufNode = @TypeOf(page_arena.state.buffer_list).Node; + const data_buf = alloc_buf[@sizeOf(BufNode)..]; + @memset(data_buf, 0); + } + } + // Initialize our pages. This should not be able to fail since // we retained the capacity for the minimum number of pages we need. self.pages, self.page_size = initPages(