From 54e02fd6b5f1632ee1331d301d63ccd3fb8063cd Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Thu, 22 Sep 2016 12:25:59 -0600 Subject: [PATCH 1/2] Fixes #220: BumpAllocator overflow I also fixed a spelling error and replaced a tab with a space in the blog post where `allocate()` was created. --- blog/post/08-kernel-heap.md | 6 +++--- libs/bump_allocator/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blog/post/08-kernel-heap.md b/blog/post/08-kernel-heap.md index 77e29efa..181a7307 100644 --- a/blog/post/08-kernel-heap.md +++ b/blog/post/08-kernel-heap.md @@ -86,8 +86,8 @@ impl BumpAllocator { /// Allocates a block of memory with the given size and alignment. fn allocate(&mut self, size: usize, align: usize) -> Option<*mut u8> { - let alloc_start = align_up(self.next, align); - let alloc_end = alloc_start + size; + let alloc_start = align_up(self.next, align); + let alloc_end = alloc_start.saturating_add(size); if alloc_end <= self.heap_start + self.heap_size { self.next = alloc_end; @@ -99,7 +99,7 @@ impl BumpAllocator { } ``` -The `heap_start` and `heap_size` fields just contain the start address and size of our kernel heap. The `next` field contains the next free address and is increased after every allocation. To `allocate` a memory block we align the `next` address using the `align_up` function (decribed below). Then we add up the desired `size` and make sure that we don't exceed the end of the heap. If everything goes well, we update the `next` address and return a pointer to the start address of the allocation. Else, we return `None`. +The `heap_start` and `heap_size` fields just contain the start address and size of our kernel heap. The `next` field contains the next free address and is increased after every allocation. To `allocate` a memory block we align the `next` address using the `align_up` function (described below). Then we add up the desired `size` and make sure that we don't exceed the end of the heap. We use a saturating add so that the calling code cannot overflow `heap_start`, which would cause undefined behaviour. If everything goes well, we update the `next` address and return a pointer to the start address of the allocation. Else, we return `None`. Note that we need to add a feature flag at the beginning of the file, because we've marked the `new` function as `const`. [Const functions] are unstable, so we need to add the `#![feature(const_fn)]` flag. diff --git a/libs/bump_allocator/src/lib.rs b/libs/bump_allocator/src/lib.rs index 3868aecb..90ffe374 100644 --- a/libs/bump_allocator/src/lib.rs +++ b/libs/bump_allocator/src/lib.rs @@ -35,7 +35,7 @@ impl BumpAllocator { /// Allocates a block of memory with the given size and alignment. fn allocate(&mut self, size: usize, align: usize) -> Option<*mut u8> { let alloc_start = align_up(self.next, align); - let alloc_end = alloc_start + size; + let alloc_end = alloc_start.saturating_add(size); if alloc_end <= self.heap_start + self.heap_size { self.next = alloc_end; From 5b9a45674d8e77607d13748ce2af59a6261ede4a Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Thu, 22 Sep 2016 16:03:32 -0600 Subject: [PATCH 2/2] Minor wording change "so that the calling code cannot overflow `heap_start`" -> "so that `alloc_end` cannot overflow" --- blog/post/08-kernel-heap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/post/08-kernel-heap.md b/blog/post/08-kernel-heap.md index 181a7307..5180cf2d 100644 --- a/blog/post/08-kernel-heap.md +++ b/blog/post/08-kernel-heap.md @@ -99,7 +99,7 @@ impl BumpAllocator { } ``` -The `heap_start` and `heap_size` fields just contain the start address and size of our kernel heap. The `next` field contains the next free address and is increased after every allocation. To `allocate` a memory block we align the `next` address using the `align_up` function (described below). Then we add up the desired `size` and make sure that we don't exceed the end of the heap. We use a saturating add so that the calling code cannot overflow `heap_start`, which would cause undefined behaviour. If everything goes well, we update the `next` address and return a pointer to the start address of the allocation. Else, we return `None`. +The `heap_start` and `heap_size` fields just contain the start address and size of our kernel heap. The `next` field contains the next free address and is increased after every allocation. To `allocate` a memory block we align the `next` address using the `align_up` function (described below). Then we add up the desired `size` and make sure that we don't exceed the end of the heap. We use a saturating add so that the `alloc_end` cannot overflow, which would cause undefined behaviour. If everything goes well, we update the `next` address and return a pointer to the start address of the allocation. Else, we return `None`. Note that we need to add a feature flag at the beginning of the file, because we've marked the `new` function as `const`. [Const functions] are unstable, so we need to add the `#![feature(const_fn)]` flag.