Make aligned allocation without posix_memalign more robust

Instead of guessing the right function to use, we malloc() 15 bytes more than
we need, and compute the aligned offset within.  The AlignedBuffer class takes
care of passing the original pointer to free().
This commit is contained in:
Keegan McAllister
2012-03-24 22:46:51 -04:00
committed by Keith Winstein
parent 0734640e14
commit 3b61581bcd
3 changed files with 27 additions and 23 deletions
+1
View File
@@ -118,6 +118,7 @@ AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINT8_T
AC_TYPE_UINTPTR_T
# Checks for library functions.
AC_FUNC_FORK
+24 -22
View File
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/resource.h>
#include "byteorder.h"
@@ -47,33 +48,34 @@ long int myatoi( const char *str )
}
AlignedBuffer::AlignedBuffer( size_t len, const char *data )
: m_len( len ), m_data( NULL )
: m_len( len ), m_allocated( NULL ), m_data( NULL )
{
void *ptr = NULL;
#if defined(HAVE_POSIX_MEMALIGN)
if( (0 != posix_memalign( (void **)&ptr, 16, len )) || (ptr == NULL) ) {
if ( ( 0 != posix_memalign( &m_allocated, 16, len ) )
|| ( m_allocated == NULL ) ) {
throw std::bad_alloc();
}
#else
// Some platforms will align malloc. Let's try that first.
if( ! (ptr = malloc(len)) ) {
throw std::bad_alloc();
}
if( (uintptr_t)ptr & 0xF ) {
// The pointer wasn't 16-byte aligned, so try again with valloc
free(ptr);
if( ! (ptr = valloc(len)) ) {
throw std::bad_alloc();
}
if( (uintptr_t)ptr & 0xF ) {
free(ptr);
throw std::bad_alloc();
}
}
#endif /* !defined(HAVE_POSIX_MEMALIGN) */
m_data = (char *) m_allocated;
m_data = (char *) ptr;
#else
/* malloc() a region 15 bytes larger than we need, and find
the aligned offset within. */
m_allocated = malloc( 15 + len );
if ( m_allocated == NULL ) {
throw std::bad_alloc();
}
uintptr_t iptr = (uintptr_t) m_allocated;
if ( iptr & 0xF ) {
iptr += 16 - ( iptr & 0xF );
}
assert( !( iptr & 0xF ) );
assert( iptr >= (uintptr_t) m_allocated );
assert( iptr <= ( 15 + (uintptr_t) m_allocated ) );
m_data = (char *) iptr;
#endif /* !defined(HAVE_POSIX_MEMALIGN) */
if ( data ) {
memcpy( m_data, data, len );
+2 -1
View File
@@ -42,13 +42,14 @@ namespace Crypto {
class AlignedBuffer {
private:
size_t m_len;
void *m_allocated;
char *m_data;
public:
AlignedBuffer( size_t len, const char *data = NULL );
~AlignedBuffer() {
free( m_data );
free( m_allocated );
}
char * data( void ) const { return m_data; }