Skip to content

Commit 6622dc5

Browse files
authored
Bug fixes (#752)
* Fix overflow by alignment * Bug fix: Ensure bytes_free is the total The bytes freed was not added to the total, but overrode it. This meant it never fired. This commit fixes that.
1 parent 5f7baef commit 6622dc5

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

src/snmalloc/mem/corealloc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ namespace snmalloc
800800
meta->as_key_tweak(),
801801
domesticate);
802802

803-
bytes_freed = objsize * length;
803+
bytes_freed += objsize * length;
804804

805805
// Update the head and the next pointer in the free list.
806806
meta->free_queue.append_segment(

src/snmalloc/mem/sizeclasstable.h

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,6 @@ namespace snmalloc
129129

130130
using sizeclass_compress_t = uint8_t;
131131

132-
constexpr SNMALLOC_FAST_PATH static size_t
133-
aligned_size(size_t alignment, size_t size)
134-
{
135-
// Client responsible for checking alignment is not zero
136-
SNMALLOC_ASSERT(alignment != 0);
137-
// Client responsible for checking alignment is a power of two
138-
SNMALLOC_ASSERT(bits::is_pow2(alignment));
139-
140-
return ((alignment - 1) | (size - 1)) + 1;
141-
}
142-
143132
/**
144133
* This structure contains the fields required for fast paths for sizeclasses.
145134
*/
@@ -535,4 +524,43 @@ namespace snmalloc
535524
return 1;
536525
return bits::one_at_bit(bits::ctz(rsize));
537526
}
527+
528+
constexpr SNMALLOC_FAST_PATH static size_t
529+
aligned_size(size_t alignment, size_t size)
530+
{
531+
// Client responsible for checking alignment is not zero
532+
SNMALLOC_ASSERT(alignment != 0);
533+
// Client responsible for checking alignment is a power of two
534+
SNMALLOC_ASSERT(bits::is_pow2(alignment));
535+
536+
// There are a class of corner cases to consider
537+
// alignment = 0x8
538+
// size = 0xfff...fff7
539+
// for this result will be 0. This should fail an allocation, so we need to
540+
// check for this overflow.
541+
// However,
542+
// alignment = 0x8
543+
// size = 0x0
544+
// will also result in 0, but this should be allowed to allocate.
545+
// So we need to check for overflow, and return SIZE_MAX in this first case,
546+
// and 0 in the second.
547+
size_t result = ((alignment - 1) | (size - 1)) + 1;
548+
// The following code is designed to fuse well with a subsequent
549+
// sizeclass calculation. We use the same fast path constant to
550+
// move the case where result==0 to the slow path, and then check for which
551+
// case we are in.
552+
constexpr size_t SmallSizeClassUpperBound =
553+
sizeclass_to_size(NUM_SMALL_SIZECLASSES - 1) - 1;
554+
if (SNMALLOC_LIKELY((result - 1) < SmallSizeClassUpperBound))
555+
return result;
556+
557+
// We are in the slow path, so we need to check for overflow.
558+
if (SNMALLOC_UNLIKELY(result == 0))
559+
{
560+
// Check for overflow and return the maximum size.
561+
if (SNMALLOC_UNLIKELY(result < size))
562+
return SIZE_MAX;
563+
}
564+
return result;
565+
}
538566
} // namespace snmalloc

src/test/func/malloc/malloc.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ constexpr int SUCCESS = 0;
1515
void check_result(size_t size, size_t align, void* p, int err, bool null)
1616
{
1717
bool failed = false;
18-
EXPECT(
19-
(errno == err) || (err == SUCCESS),
20-
"Expected error: {} but got {}",
21-
err,
22-
errno);
18+
EXPECT((errno == err), "Expected error: {} but got {}", err, errno);
2319
if (null)
2420
{
2521
EXPECT(p == nullptr, "Expected null but got {}", p);
@@ -307,6 +303,9 @@ int main(int argc, char** argv)
307303
for (size_t align = sizeof(uintptr_t); align < MAX_SMALL_SIZECLASS_SIZE * 8;
308304
align <<= 1)
309305
{
306+
// Check overflow with alignment taking it round to 0.
307+
test_memalign(1 - align, align, ENOMEM, true);
308+
310309
for (smallsizeclass_t sc = 0; sc < NUM_SMALL_SIZECLASSES - 6; sc++)
311310
{
312311
const size_t size = sizeclass_to_size(sc);

0 commit comments

Comments
 (0)