linux: Fix _aligned_realloc implementation

Out-of-bounds memory is no longer accessed if the realloc size is larger.
If reallocation fails, the old memory will not be freed and a memcpy
will not take place.

This should match the Windows _aligned_realloc behaviour, except that an
extra parameter is used.
This commit is contained in:
Jonathan Li 2015-09-13 18:02:07 +01:00
parent 4760d71a86
commit 67dc65ea91
4 changed files with 12 additions and 11 deletions

View File

@ -15,7 +15,6 @@
#pragma once #pragma once
#include "MemcpyFast.h"
#include "SafeArray.h" #include "SafeArray.h"
// Internal constructor for use by derived classes. This allows a derived class to // Internal constructor for use by derived classes. This allows a derived class to
@ -132,7 +131,7 @@ T* SafeAlignedArray<T,Alignment>::_virtual_realloc( int newsize )
{ {
return (T*)( ( this->m_ptr == NULL ) ? return (T*)( ( this->m_ptr == NULL ) ?
_aligned_malloc( newsize * sizeof(T), Alignment ) : _aligned_malloc( newsize * sizeof(T), Alignment ) :
_aligned_realloc( this->m_ptr, newsize * sizeof(T), Alignment ) pcsx2_aligned_realloc( this->m_ptr, newsize * sizeof(T), Alignment, this->m_size * sizeof(T) )
); );
} }

View File

@ -51,8 +51,11 @@
// aligned_malloc: Implement/declare linux equivalents here! // aligned_malloc: Implement/declare linux equivalents here!
#if !defined(_MSC_VER) #if !defined(_MSC_VER)
extern void* __fastcall _aligned_malloc(size_t size, size_t align); extern void* __fastcall _aligned_malloc(size_t size, size_t align);
extern void* __fastcall _aligned_realloc(void* handle, size_t size, size_t align); extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t new_size, size_t align, size_t old_size);
extern void _aligned_free(void* pmem); extern void _aligned_free(void* pmem);
#else
#define pcsx2_aligned_realloc(handle, new_size, align, old_size) \
_aligned_realloc(handle, new_size, align)
#endif #endif
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -245,8 +248,8 @@ public:
virtual void Resize( size_t newsize ) virtual void Resize( size_t newsize )
{ {
this->m_size = newsize; this->m_buffer = (T*)pcsx2_aligned_realloc(this->m_buffer, newsize * sizeof(T), align, this->m_size * sizeof(T));
this->m_buffer = (T*)_aligned_realloc(this->m_buffer, newsize * sizeof(T), align); this->m_size = newsize;
if (!this->m_buffer) if (!this->m_buffer)
throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize"); throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize");

View File

@ -30,15 +30,14 @@ void* __fastcall _aligned_malloc(size_t size, size_t align)
#endif #endif
} }
void* __fastcall _aligned_realloc(void* handle, size_t size, size_t align) void* __fastcall pcsx2_aligned_realloc(void* handle, size_t new_size, size_t align, size_t old_size)
{ {
pxAssert( align < 0x10000 ); pxAssert( align < 0x10000 );
void* newbuf = _aligned_malloc( size, align ); void* newbuf = _aligned_malloc(new_size, align);
if( handle != NULL ) if (newbuf != NULL && handle != NULL) {
{ memcpy(newbuf, handle, std::min(old_size, new_size));
memcpy( newbuf, handle, size );
_aligned_free(handle); _aligned_free(handle);
} }
return newbuf; return newbuf;

View File

@ -81,7 +81,7 @@ public:
u32 d = (u32&)dataPtr; u32 d = (u32&)dataPtr;
SizeChain<T>& bucket( mBucket[d % hSize] ); SizeChain<T>& bucket( mBucket[d % hSize] );
if( bucket.Chain = (T*)_aligned_realloc( bucket.Chain, sizeof(T)*(bucket.Size+1), 16), bucket.Chain==NULL ) { if( (bucket.Chain = (T*)pcsx2_aligned_realloc( bucket.Chain, sizeof(T)*(bucket.Size+1), 16, sizeof(T)*bucket.Size)) == NULL ) {
throw Exception::OutOfMemory( throw Exception::OutOfMemory(
wxsFormat(L"HashBucket Chain (bucket size=%d)", bucket.Size+1) wxsFormat(L"HashBucket Chain (bucket size=%d)", bucket.Size+1)
); );