Skip to content

ext/hash relies on implementation-defined malloc alignment #18173

@arnaud-lb

Description

@arnaud-lb

Description

ext/hash uses ecalloc() to allocate context buffers in php_hash_alloc_context(), and assumes that the buffer will be 16 bytes aligned. If it's not, it crashes at least here:

XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */
XXH_ASSERT(((size_t)dst16 & 15) == 0);
for (i=0; i < nbRounds; ++i) {
dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed);

Posix specifies that "The pointer returned [by calloc()] shall be suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated [...]".

On x86_64 there is no type requiring an alignment larger than 8 bytes, so it's really an implementation details that [e]calloc() returns a 16 bytes aligned buffer in php_hash_alloc_context(), and it's dependent on the requested size and the state of the heap.

The crash can be reproduced with the help of #18172:

ZEND_MM_DEBUG=padding=8 TESTS=ext/hash make test

PHP Version

PHP8.3

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions