request2size can cause unintentional overflow in the program
just4you
just4you_jongun@protonmail.com
Tue Nov 11 12:09:23 GMT 2025
// demo
#include <stdio.h>
#define INTERNAL_SIZE_T size_t
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size;
INTERNAL_SIZE_T mchunk_size;
struct malloc_chunk* fd;
struct malloc_chunk* bk;
struct malloc_chunk* fd_nextsize;
struct malloc_chunk* bk_nextsize;
};
#define SIZE_SZ (sizeof (INTERNAL_SIZE_T))
#define CHUNK_HDR_SZ (2 * SIZE_SZ)
#define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) ? __alignof__ (long double) : 2 * SIZE_SZ)
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
#define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
#define MIN_CHUNK_SIZE (offsetof(struct malloc_chunk, fd_nextsize))
#define MINSIZE (unsigned long)(((MIN_CHUNK_SIZE + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
#define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
#define ALLOC_LEN_A 0x36
#define ALLOC_LEN_B 0x39
static void request2size_run(int alloc_size)
{
int real_size, usable_size;
real_size = (int) request2size(alloc_size);
printf("actual size obtained = 0x%x\n", real_size);
usable_size = real_size - CHUNK_HDR_SZ;
printf("actual usable size = 0x%x\n", real_size);
if (usable_size < alloc_size) {
printf("when alloc size 0x%x, marco [request2size] gave us an incorrect value\n", alloc_size);
}
else {
printf("alloc size 0x%x succeed, has enough space to use\n", alloc_size);
}
}
int main(void)
{
printf("a demo used to expose the dangers of request2size\n");
request2size_run(ALLOC_LEN_A);
request2size_run(ALLOC_LEN_B);
return 0;
}
/* stdout:a demo used to expose the dangers of request2size
actual size obtained = 0x40
actual usable size = 0x40
when alloc size 0x36, marco [request2size] gave us an incorrect value
actual size obtained = 0x50
actual usable size = 0x50
alloc size 0x39 succeed, has enough space to use */
problem description:
I'm learning about off-by-one operations in heap scenarios. While understanding the `request2size` macro, I noticed that during the size conversion process, it splits the value into the form `n * 0x10 + x`. For example, 0x36 becomes `0x3 * 0x10 + 0x6`, then offsets upwards and aligns with `MALLOC_ALIGN_MASK`.
If `x` is less than or equal to 8, the `request2size` macro returns `(n + 1) * 0x10` as the chunk size. However, because the chunk needs to reserve space for `CHUNK_HDR_SZ`, the actual usable space is only `n * 0x10`, which is `x` bytes less than the actual required space.
This situation can cause unintentional overflow in the program.
my patch:
+ #ifdef MALLOC_SECURE
+ #define request2size_secure(req) \
+ ((((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) + \
+ ((req) > ((((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) - SIZE_SZ) ? \
+ MALLOC_ALIGNMENT : 0))
+ #endif
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20251111/a00a9b09/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: publickey - just4you_jongun@protonmail.com - 0xA0C5999E.asc
Type: application/pgp-keys
Size: 868 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20251111/a00a9b09/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 343 bytes
Desc: OpenPGP digital signature
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20251111/a00a9b09/attachment-0001.sig>
More information about the Libc-alpha
mailing list