Secure-memory alignment overflow turns a huge allocation into a zero-byte block
The secure allocator rounds requests to 32 bytes by adding 31 without checking size_t overflow. Any nonzero request in the final 31 values of the type can wrap to zero; gcry_malloc_secure(SIZE_MAX) then returns a non-NULL secure pointer whose user address overlaps the next block's allocator metadata, so the caller's first ordinary write corrupts the secure pool.
Vulnerable code
src/secmem.c, _gcry_secmem_malloc_internal:
c
/* Blocks are always a multiple of 32. */
size = ((size + 31) / 32) * 32;
mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
if (mb)
{
stats_update (pool, mb->size, 0);
return &mb->aligned.c;
}Why it matters
This is reachable through the public gcry_malloc_secure(size_t) API. The audit harness confirmed that gcry_malloc_secure(SIZE_MAX) returned a non-NULL pointer for which gcry_is_secure was true; writing its first byte aliases pool bookkeeping. Corruption can crash later allocations/frees or create overlapping blocks holding keys. Exploitation requires an application to forward an extreme length and then trust the successful allocation, so this is not an automatic remote primitive in typical callers.
Capacity checks cannot help because they see the already rounded value zero. Secure calloc multiplication checks likewise do not protect the plain allocation API.
Proposed fix
Before alignment, reject size > SIZE_MAX - 31 with ENOMEM. Use a checked alignment helper, and reject a zero aligned result for any nonzero input before calling mb_get_new. Also prove the aligned size and header addition fit the allocator's internal type. Add public-API boundary tests for SIZE_MAX, SIZE_MAX - 30, SIZE_MAX - 31, and the largest representable aligned size, checking failure without pool mutation.