From 9014ca899d97a25a4617763e908849f207da5fbb Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 30 Jul 2015 11:57:50 -0500 Subject: [PATCH 1/5] dbStatic: Fix invalid memory read --- src/dbStatic/dbStaticLib.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c index a3648f3bf..1a5d716e7 100644 --- a/src/dbStatic/dbStaticLib.c +++ b/src/dbStatic/dbStaticLib.c @@ -1375,14 +1375,19 @@ long epicsShareAPI dbGetAttributePart(DBENTRY *pdbentry, const char **ppname) const char *pname = *ppname; dbRecordAttribute *pattribute; - if (!precordType) return S_dbLib_recordTypeNotFound; + if (!precordType) + return S_dbLib_recordTypeNotFound; + pattribute = (dbRecordAttribute *)ellFirst(&precordType->attributeList); while (pattribute) { int nameLen = strlen(pattribute->name); int compare = strncmp(pattribute->name, pname, nameLen); - int ch = pname[nameLen]; + if (compare == 0) { - if (!(ch == '_' || isalnum(ch))) { + int ch = pname[nameLen]; + + if (ch != '_' && !isalnum(ch)) { + /* Any other character can't be in the attribute name */ pdbentry->pflddes = pattribute->pdbFldDes; pdbentry->pfield = pattribute->value; *ppname = &pname[nameLen]; From d7b3293ba3e13e1ce970eabd68d6bbc3d2b009a9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 7 Aug 2015 09:41:48 -0500 Subject: [PATCH 2/5] libCom: Use MSVC's struct timespec when available --- src/libCom/osi/os/WIN32/osdTime.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libCom/osi/os/WIN32/osdTime.h b/src/libCom/osi/os/WIN32/osdTime.h index 899eeb46a..5875c0e7e 100644 --- a/src/libCom/osi/os/WIN32/osdTime.h +++ b/src/libCom/osi/os/WIN32/osdTime.h @@ -3,9 +3,8 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -14,15 +13,22 @@ * Author: Jeff Hill */ -#ifndef osdTimeh -#define osdTimeh +#ifndef INC_osdTime_H +#define INC_osdTime_H #if ! defined(_MINGW) || ! defined(_TIMESPEC_DEFINED) +# if _MSC_VER >= 1900 +# include +# else + +#define _TIMESPEC_DEFINED 1 struct timespec { - time_t tv_sec; /* seconds since some epoch */ - long tv_nsec; /* nanoseconds within the second */ + time_t tv_sec; /* seconds since some epoch */ + long tv_nsec; /* nanoseconds within the second */ }; + +# endif /* _MSC_VER */ #endif /* ! defined(_MINGW) || ! defined(_TIMESPEC_DEFINED) */ -#endif /* ifndef osdTimeh */ +#endif /* ifndef INC_osdTime_H */ From ef7399159cc9d6213881f13762854fd0285a6ba8 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 10 Aug 2015 15:03:48 -0500 Subject: [PATCH 3/5] dbAccess: Make dbPut() always do special processing after put If the value gets rejected by a put to SCAN, we must still call dbPutSpecial() to add the record back onto its old scan thread. --- src/db/dbAccess.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c index 068e59bd4..871c97d3d 100644 --- a/src/db/dbAccess.c +++ b/src/db/dbAccess.c @@ -1460,14 +1460,16 @@ long epicsShareAPI dbPut(DBADDR *paddr, short dbrType, status = prset->put_array_info(paddr, nRequest); } } - if (status) return status; - /* check if special processing is required */ + /* Always do special processing if needed */ if (special) { - status = dbPutSpecial(paddr,1); - if (status) return status; + long status2 = dbPutSpecial(paddr,1); + if (status2) return status2; } + /* If the put failed, return the error */ + if (status) return status; + /* Propagate monitor events for this field, */ /* unless the field field is VAL and PP is true. */ pfldDes = paddr->pfldDes; From 9e82a9670082b6f75c83d21c7354b1e16ced306f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 10 Aug 2015 15:04:11 -0500 Subject: [PATCH 4/5] dbTest: Remove special ENUM handling from dbpf() This was preventing the value check in cvt_st_menu() from working. --- src/db/dbTest.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/db/dbTest.c b/src/db/dbTest.c index 2c9350d6f..b827465bb 100644 --- a/src/db/dbTest.c +++ b/src/db/dbTest.c @@ -336,7 +336,6 @@ long epicsShareAPI dbpf(const char *pname,const char *pvalue) { DBADDR addr; long status; - epicsUInt16 value; short dbrType; long n = 1; @@ -348,16 +347,7 @@ long epicsShareAPI dbpf(const char *pname,const char *pvalue) if (nameToAddr(pname, &addr)) return -1; - /* For enumerated types must allow for ENUM rather than string */ - /* If entire field is digits then use DBR_ENUM else DBR_STRING */ - if (addr.dbr_field_type == DBR_ENUM && *pvalue && - strspn(pvalue,"0123456789") == strlen(pvalue)) { - - sscanf(pvalue, "%hu", &value); - pvalue = (char *) &value; - dbrType = DBR_ENUM; - } - else if (addr.no_elements > 1 && + if (addr.no_elements > 1 && (addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) { dbrType = addr.dbr_field_type; n = strlen(pvalue) + 1; From fe4f607e639d989e20563feee7b74b6a91b4aea2 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 13 Aug 2015 10:44:52 -0500 Subject: [PATCH 5/5] libCom/errlog: Don't store stderr in pvtData.console Some VxWorks BSPs close the stderr stream that the shell running the startup script created and open a new one for the interactive shell. This change makes pvtData.console==NULL mean use stderr instead of storing the stderr value in pvtData.console at init. --- src/libCom/error/errlog.c | 55 +++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/libCom/error/errlog.c b/src/libCom/error/errlog.c index f0a653af5..b6789978a 100644 --- a/src/libCom/error/errlog.c +++ b/src/libCom/error/errlog.c @@ -120,10 +120,12 @@ epicsShareFunc int errlogPrintf(const char *pFormat, ...) isOkToBlock = epicsThreadIsOkToBlock(); if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { + FILE *console = pvtData.console ? pvtData.console : stderr; + va_start(pvar, pFormat); - nchar = vfprintf(pvtData.console, pFormat, pvar); + nchar = vfprintf(console, pFormat, pvar); va_end (pvar); - fflush(pvtData.console); + fflush(console); } if (pvtData.atExit) @@ -146,6 +148,7 @@ epicsShareFunc int errlogVprintf( int nchar; char *pbuffer; int isOkToBlock; + FILE *console; if (epicsInterruptIsInterruptContext()) { epicsInterruptContextMessage @@ -160,15 +163,17 @@ epicsShareFunc int errlogVprintf( pbuffer = msgbufGetFree(isOkToBlock); if (!pbuffer) { - vfprintf(pvtData.console, pFormat, pvar); - fflush(pvtData.console); + console = pvtData.console ? pvtData.console : stderr; + vfprintf(console, pFormat, pvar); + fflush(console); return 0; } nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar); if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { - fprintf(pvtData.console, "%s", pbuffer); - fflush(pvtData.console); + console = pvtData.console ? pvtData.console : stderr; + fprintf(console, "%s", pbuffer); + fflush(console); } msgbufSetSize(nchar); return nchar; @@ -243,11 +248,13 @@ epicsShareFunc int errlogSevPrintf( isOkToBlock = epicsThreadIsOkToBlock(); if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { - fprintf(pvtData.console, "sevr=%s ", errlogGetSevEnumString(severity)); + FILE *console = pvtData.console ? pvtData.console : stderr; + + fprintf(console, "sevr=%s ", errlogGetSevEnumString(severity)); va_start(pvar, pFormat); - vfprintf(pvtData.console, pFormat, pvar); + vfprintf(console, pFormat, pvar); va_end(pvar); - fflush(pvtData.console); + fflush(console); } va_start(pvar, pFormat); @@ -359,7 +366,9 @@ epicsShareFunc int epicsShareAPI errlogRemoveListeners( epicsMutexUnlock(pvtData.listenerLock); if (count == 0) { - fprintf(pvtData.console, + FILE *console = pvtData.console ? pvtData.console : stderr; + + fprintf(console, "errlogRemoveListeners: No listeners found\n"); } return count; @@ -376,7 +385,7 @@ epicsShareFunc int epicsShareAPI eltc(int yesno) epicsShareFunc int errlogSetConsole(FILE *stream) { errlogInit(0); - pvtData.console = stream ? stream : stderr; + pvtData.console = stream; return 0; } @@ -405,17 +414,19 @@ epicsShareFunc void errPrintf(long status, const char *pFileName, } if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) { + FILE *console = pvtData.console ? pvtData.console : stderr; + if (pFileName) - fprintf(pvtData.console, "filename=\"%s\" line number=%d\n", + fprintf(console, "filename=\"%s\" line number=%d\n", pFileName, lineno); if (status > 0) - fprintf(pvtData.console, "%s ", name); + fprintf(console, "%s ", name); va_start(pvar, pformat); - vfprintf(pvtData.console, pformat, pvar); + vfprintf(console, pformat, pvar); va_end(pvar); - fputc('\n', pvtData.console); - fflush(pvtData.console); + fputc('\n', console); + fflush(console); } if (pvtData.atExit) @@ -473,7 +484,7 @@ static void errlogInitPvt(void *arg) ellInit(&pvtData.listenerList); ellInit(&pvtData.msgQueue); pvtData.toConsole = TRUE; - pvtData.console = stderr; + pvtData.console = NULL; pvtData.waitForWork = epicsEventMustCreate(epicsEventEmpty); pvtData.listenerLock = epicsMutexMustCreate(); pvtData.msgQueueLock = epicsMutexMustCreate(); @@ -559,8 +570,10 @@ static void errlogThread(void) while ((pmessage = msgbufGetSend(&noConsoleMessage))) { epicsMutexMustLock(pvtData.listenerLock); if (pvtData.toConsole && !noConsoleMessage) { - fprintf(pvtData.console,"%s",pmessage); - fflush(pvtData.console); + FILE *console = pvtData.console ? pvtData.console : stderr; + + fprintf(console, "%s", pmessage); + fflush(console); } plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList); @@ -680,7 +693,9 @@ static void msgbufFreeSend(void) epicsMutexMustLock(pvtData.msgQueueLock); pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue); if (!pnextSend) { - fprintf(pvtData.console, "errlog: msgbufFreeSend logic error\n"); + FILE *console = pvtData.console ? pvtData.console : stderr; + + fprintf(console, "errlog: msgbufFreeSend logic error\n"); epicsThreadSuspendSelf(); } ellDelete(&pvtData.msgQueue, &pnextSend->node);