diff options
| author | Rich Felker <dalias@aerifal.cx> | 2026-05-12 09:19:26 -0400 |
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2026-05-12 09:19:26 -0400 |
| commit | bf96b52a4429eeeb60e6c961c8687e52d90c5fa1 (patch) | |
| tree | fa430a00cc68ee9c13dfe0ec100cb4bfc68822a6 /src/stdio/fflush.c | |
| parent | 64f05291ff99ae407801ad7ab44cc4d7f6e0350f (diff) | |
| download | musl-bf96b52a4429eeeb60e6c961c8687e52d90c5fa1.tar.gz | |
mallocng: fix handling of allocations with extreme alignment
aligned allocations are handled by over-allocating enough to ensure an
aligned subrange exists and framing the usable space to that subrange.
the framing can only handle offsets up to a 32-bit multiple of the
allocation UNIT (16 bytes), and aligned_alloc correctly checks for and
rejects larger alignments.
however, when get_meta reads back the offset, the type of the variable
and everything else in the expression where it's used was int, not
size_t, and offset*UNIT can overflow. modulo the "anything can happen"
aspect of overflow being undefined, a clean trap will occur and the
program will terminate. this would happen on any call to free,
realloc, or malloc_usable_size call on the large-alignment object.
switch the type of offset in get_meta from int to size_t. this has
been checked not to break any of the subsequent assertions:
- assert(offset > 0xffff) was wrongly rejecting offsets that would be
interpreted as negative when converted to signed int. this is fixed
by processing offset as unsigned.
- the check against the slot boundaries switches which assert would
catch values that were previously interpreted as negative, but the
net effect is the same.
- the check against maplen was already converting to unsigned long due
to the 4096UL in the expression. in doing so, it was incorrectly
sign-extending the offset rather than zero-extending. this is fixed
by using unsigned type to begin with.
in addition, take the opportunity to trap on offsets were offset*UNIT
would overflow. this cannot happen on 64-bit archs (and it should be
optimized out by the compiler there), but it's an additional signal we
can use to catch out-of-bounds writes on 32-bit ones. and the check
only happens when operating on extremely large, overaligned objects,
so the relative cost of checking is essentially zero.
Diffstat (limited to 'src/stdio/fflush.c')
0 files changed, 0 insertions, 0 deletions
