From 27cd9fd0514557822f55a658c74efdd5b6fb2e4e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 2 May 2017 17:52:58 -0400 Subject: [PATCH] ioc/dbStatic: dbFreeBase() don't double free alias'd records dbFreeBase() has been broken since alias() was introduced. Traversal of recList in the function assumed that dbDeleteRecord() remove only the current dbRecordNode. However, dbDeleteRecord() called dbDeleteAliases() which removes alias dbRecordNode s. If this happens (as it often does) to be the node immediately after the real node, dbFreeBase() will then iterate using a ellDelete()d node. --- src/dbStatic/dbStaticLib.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c index 545f8906d..a2ff7fc61 100644 --- a/src/dbStatic/dbStaticLib.c +++ b/src/dbStatic/dbStaticLib.c @@ -578,8 +578,6 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase) dbRecordType *pdbRecordType; dbRecordType *pdbRecordTypeNext; dbFldDes * pdbFldDes; - dbRecordNode *pdbRecordNode; - dbRecordNode *pdbRecordNodeNext; dbRecordAttribute *pAttribute; dbRecordAttribute *pAttributeNext; devSup *pdevSup; @@ -594,19 +592,21 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase) brkTable *pbrkTableNext; int i; DBENTRY dbentry; - + long status; dbInitEntry(pdbbase,&dbentry); - pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); - while(pdbRecordType) { - pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList); - while(pdbRecordNode) { - pdbRecordNodeNext = (dbRecordNode *)ellNext(&pdbRecordNode->node); - if(!dbFindRecord(&dbentry,pdbRecordNode->recordname)) - dbDeleteRecord(&dbentry); - pdbRecordNode = pdbRecordNodeNext; + status = dbFirstRecordType(&dbentry); + while(!status) { + /* dbDeleteRecord() will remove alias or real record node. + * For real record nodes, also removes the nodes of all aliases. + * This complicates safe traversal, so we re-start iteration + * from the first record after each call. + */ + while((status = dbFirstRecord(&dbentry))==0) { + dbDeleteRecord(&dbentry); } - pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node); + assert(status==S_dbLib_recNotFound); + status = dbNextRecordType(&dbentry); } dbFinishEntry(&dbentry); pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);