diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index eea7a5b4f..68b6102b6 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -536,15 +536,8 @@ scratch_alloc_bytes_non_zeroed :: proc( // we don't need to be so strict about every byte. aligned_size += alignment - 1 } - if aligned_size <= len(s.data) { - offset := uintptr(0) - if s.curr_offset+aligned_size <= len(s.data) { - offset = uintptr(s.curr_offset) - } else { - // The allocation will cause an overflow past the boundary of the - // space available, so reset to the starting offset. - offset = 0 - } + if s.curr_offset+aligned_size <= len(s.data) { + offset := uintptr(s.curr_offset) start := uintptr(raw_data(s.data)) ptr := rawptr(offset+start) // We keep track of the original base pointer without extra alignment diff --git a/tests/issues/run.bat b/tests/issues/run.bat index f1a1c48c0..2f42e3e21 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -34,6 +34,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style -ignore-unused ..\..\..\odin build ..\test_issue_6401.odin %COMMON% 2>&1 | find /c "Error:" | findstr /x "3" || exit /b ..\..\..\odin test ..\test_pr_6470.odin %COMMON% || exit /b ..\..\..\odin test ..\test_pr_6470.odin -define:TEST_EXPECT_FAILURE=true %COMMON% 2>&1 | find /c "Error:" | findstr /x "1" || exit /b +..\..\..\odin test ..\test_pr_6476.odin %COMMON% || exit /b @echo off diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 996007cd7..8a7800cd7 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -37,6 +37,8 @@ $ODIN test ../test_issue_6068.odin $COMMON $ODIN test ../test_issue_6101.odin $COMMON $ODIN test ../test_issue_6165.odin $COMMON $ODIN test ../test_issue_6396.odin $COMMON +$ODIN test ../test_pr_6476.odin $COMMON + if [[ $($ODIN build ../test_issue_6240.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]] ; then echo "SUCCESSFUL 1/1" else diff --git a/tests/issues/test_pr_6476.odin b/tests/issues/test_pr_6476.odin new file mode 100644 index 000000000..b63aec674 --- /dev/null +++ b/tests/issues/test_pr_6476.odin @@ -0,0 +1,35 @@ +package test_issues + +import "core:testing" +import "core:mem" + +// Test for a problem encountered with the scratch allocator. +// Say you have a scratch allocator with an arena size of N. +// If you make an allocation whose size is <= N but greater than +// the amount of free space left in the arena, the allocator +// will return a slice of memory from the start of the arena, +// overlapping previous allocations. (the expected +// behavior is it satisfies the request with the backup allocator) + +@test +test_scratch_smash :: proc(t: ^testing.T) { + // setup + frAlloc: mem.Scratch + err := mem.scratch_init(&frAlloc, 1 * mem.Kilobyte) + testing.expect(t, err == nil) + + talloc := mem.scratch_allocator(&frAlloc) + defer mem.scratch_destroy(&frAlloc) + + // First allocation fits in arena. + a1 := make([]byte, 512, talloc) + + // Second allocation does not fit in the free space, but is + // <= the arena size. + a2 := make([]byte, 1024, talloc) + + // Should be true, but bug in scratch allocator returns space + // overlapping a1 when allocating a2. + testing.expect(t, &a1[0] != &a2[0]) +} +