------------------------------------------------------------ committer: Andrew Johnson timestamp: Thu 2015-04-09 15:53:16 -0500 message: Merged fix to ReadNotifyCache buffer size issue from 3.14 branch diff: === modified file 'src/ioc/db/dbCAC.h' --- src/ioc/db/dbCAC.h 2013-06-07 23:08:38 +0000 +++ src/ioc/db/dbCAC.h 2015-04-09 20:53:16 +0000 @@ -34,6 +34,8 @@ # undef epicsExportSharedSymbols #endif +#include "stdlib.h" + #include "tsDLList.h" #include "tsFreeList.h" #include "resourceLib.h" @@ -137,7 +139,9 @@ void show ( unsigned level ) const; private: struct cacheElem_t { + size_t size; struct cacheElem_t * pNext; + char buf[1]; }; unsigned long _readNotifyCacheSize; cacheElem_t * _pReadNotifyCache; === modified file 'src/ioc/db/dbContextReadNotifyCache.cpp' --- src/ioc/db/dbContextReadNotifyCache.cpp 2012-04-27 17:21:41 +0000 +++ src/ioc/db/dbContextReadNotifyCache.cpp 2015-04-09 20:53:16 +0000 @@ -13,7 +13,10 @@ * Auther Jeff Hill */ +#include + #include "epicsMutex.h" +#include "dbDefs.h" #include "cadef.h" // this can be eliminated when the callbacks use the new interface #include "db_access.h" // should be eliminated here in the future @@ -23,6 +26,8 @@ #include "db_access_routines.h" #include "dbCAC.h" +#include "epicsAssert.h" + dbContextReadNotifyCache::dbContextReadNotifyCache ( epicsMutex & mutexIn ) : _mutex ( mutexIn ) { @@ -112,10 +117,10 @@ void dbContextReadNotifyCacheAllocator::reclaimAllCacheEntries () { - while ( _pReadNotifyCache ) { cacheElem_t * pNext = _pReadNotifyCache->pNext; - delete [] _pReadNotifyCache; + assert(_pReadNotifyCache->size == _readNotifyCacheSize); + ::free(_pReadNotifyCache); _pReadNotifyCache = pNext; } } @@ -129,20 +134,26 @@ cacheElem_t * pAlloc = _pReadNotifyCache; if ( pAlloc ) { + assert(pAlloc->size == _readNotifyCacheSize); _pReadNotifyCache = pAlloc->pNext; } else { - size_t nElem = _readNotifyCacheSize / sizeof ( cacheElem_t ); - pAlloc = new cacheElem_t [ nElem + 1 ]; + pAlloc = (cacheElem_t*)calloc(1, sizeof(cacheElem_t)+_readNotifyCacheSize); + if(!pAlloc) throw std::bad_alloc(); + pAlloc->size = _readNotifyCacheSize; } - return reinterpret_cast < char * > ( pAlloc ); + return pAlloc->buf; } void dbContextReadNotifyCacheAllocator::free ( char * pFree ) { - cacheElem_t * pAlloc = reinterpret_cast < cacheElem_t * > ( pFree ); - pAlloc->pNext = _pReadNotifyCache; - _pReadNotifyCache = pAlloc; + cacheElem_t * pAlloc = (cacheElem_t*)(pFree - offsetof(cacheElem_t, buf)); + if (pAlloc->size == _readNotifyCacheSize) { + pAlloc->pNext = _pReadNotifyCache; + _pReadNotifyCache = pAlloc; + } else { + ::free(pAlloc); + } } void dbContextReadNotifyCacheAllocator::show ( unsigned level ) const @@ -152,6 +163,7 @@ size_t count =0; cacheElem_t * pNext = _pReadNotifyCache; while ( pNext ) { + assert(pNext->size == _readNotifyCacheSize); pNext = _pReadNotifyCache->pNext; count++; }