Use epicsVsnprintf to eliminate possibility of buffer overflows.

This commit is contained in:
W. Eric Norum
2003-09-17 18:51:44 +00:00
parent 2e922d7195
commit d158974870

View File

@@ -40,15 +40,8 @@
#define LOCAL static
#endif /* LOCAL */
/* BUFFER_EXTRA_BYTES is set equal to MAX_MESSAGE_SIZE in case
an os can't implement vsnprintf. Such an os
is subject to buffer overflow. Allocating an additional
BUFFER_EXTRA_BYTES bytes will at least make this less likely
*/
#define BUFFER_SIZE 1280
#define MAX_MESSAGE_SIZE 256
#define BUFFER_EXTRA_BYTES MAX_MESSAGE_SIZE
#define TRUNCATE_SIZE 80
#define MAX_ALIGNMENT 8
/*Declare storage for errVerbose */
@@ -57,7 +50,7 @@ epicsShareDef int errVerbose=0;
LOCAL void errlogThread(void);
LOCAL char *msgbufGetFree(int noConsoleMessage);
LOCAL void msgbufSetSize(int size);
LOCAL void msgbufSetSize(int size); /* Send 'size' chars plus trailing '\0' */
LOCAL char * msgbufGetSend(int *noConsoleMessage);
LOCAL void msgbufFreeSend(void);
@@ -94,7 +87,25 @@ LOCAL struct {
int missedMessages;
void *pbuffer;
}pvtData;
/*
* vsnprintf with truncation message
*/
LOCAL int tvsnPrint(char *str, size_t size, const char *format, va_list ap)
{
int nchar;
static const char tmsg[] = "<<TRUNCATED>>";
nchar = epicsVsnprintf(str, size, format?format:"", ap);
if(nchar >= size) {
if (size > sizeof tmsg)
strcpy(str+size-sizeof tmsg, tmsg);
nchar = size - 1;
}
return nchar;
}
epicsShareFunc int errlogPrintf( const char *pFormat, ...)
{
va_list pvar;
@@ -126,8 +137,8 @@ epicsShareFunc int errlogVprintf(
errlogInit(0);
pbuffer = msgbufGetFree(0);
if(!pbuffer) return(0);
nchar = vsprintf(pbuffer,pFormat?pFormat:"",pvar);
msgbufSetSize(nchar+1);/*include the \0*/
nchar = tvsnPrint(pbuffer,MAX_MESSAGE_SIZE,pFormat?pFormat:"",pvar);
msgbufSetSize(nchar);
return nchar;
}
@@ -144,7 +155,7 @@ epicsShareFunc int epicsShareAPI errlogMessage(const char *message)
pbuffer = msgbufGetFree(0);
if(!pbuffer) return(0);
strcpy(pbuffer,message);
msgbufSetSize(strlen(message) +1);
msgbufSetSize(strlen(message));
return 0;
}
@@ -179,8 +190,8 @@ epicsShareFunc int errlogVprintfNoConsole(
errlogInit(0);
pbuffer = msgbufGetFree(1);
if(!pbuffer) return(0);
nchar = vsprintf(pbuffer,pFormat?pFormat:"",pvar);
msgbufSetSize(nchar+1);/*include the \0*/
nchar = tvsnPrint(pbuffer,MAX_MESSAGE_SIZE,pFormat?pFormat:"",pvar);
msgbufSetSize(nchar);
return nchar;
}
@@ -221,10 +232,10 @@ epicsShareFunc int errlogSevVprintf(
if(!pnext) return(0);
nchar = sprintf(pnext,"sevr=%s ",errlogGetSevEnumString(severity));
pnext += nchar; totalChar += nchar;
nchar = vsprintf(pnext,pFormat,pvar);
nchar = tvsnPrint(pnext,MAX_MESSAGE_SIZE-1,pFormat,pvar);
pnext += nchar; totalChar += nchar;
sprintf(pnext,"\n");
totalChar += 2; /*include \n and \0*/
strcpy(pnext,"\n");
totalChar++; /*include \n */
msgbufSetSize(totalChar);
return(nchar);
}
@@ -322,16 +333,14 @@ epicsShareFunc void errPrintf(long status, const char *pFileName,
pnext += nchar; totalChar += nchar;
}
va_start (pvar, pformat);
/* buffer was allocated with an extra BUFFER_EXTRA_BYTES bytes*/
/* Thus the following will not overflow buffer */
nchar = epicsVsnprintf(pnext,MAX_MESSAGE_SIZE + BUFFER_EXTRA_BYTES,pformat,pvar);
nchar = tvsnPrint(pnext,MAX_MESSAGE_SIZE,pformat,pvar);
va_end (pvar);
if(nchar>0) {
pnext += nchar;
totalChar += nchar;
}
sprintf(pnext,"\n");
totalChar += 2; /*include the \n and the \0*/
strcpy(pnext,"\n");
totalChar++ ; /*include the \n */
msgbufSetSize(totalChar);
}
@@ -353,8 +362,7 @@ static void errlogInitPvt(void *arg)
pvtData.waitForFlush = epicsEventMustCreate(epicsEventEmpty);
pvtData.flush = epicsEventMustCreate(epicsEventEmpty);
pvtData.flushLock = epicsMutexMustCreate();
/*BUFFER_EXTRA_BYTES allows message overflow to be detected*/
pbuffer = pvtCalloc(pvtData.buffersize+BUFFER_EXTRA_BYTES,sizeof(char));
pbuffer = pvtCalloc(pvtData.buffersize,sizeof(char));
pvtData.pbuffer = pbuffer;
tid = epicsThreadCreate("errlog",epicsThreadPriorityLow,
epicsThreadGetStackSize(epicsThreadStackSmall),
@@ -479,31 +487,9 @@ LOCAL char *msgbufGetFree(int noConsoleMessage)
LOCAL void msgbufSetSize(int size)
{
char *pbuffer = (char *)pvtData.pbuffer;
msgNode *pnextSend = pvtData.pnextSend;
char *message = pnextSend->message;
if(size>MAX_MESSAGE_SIZE) {
int excess;
int nchar;
excess = size - (pvtData.buffersize -(message - pbuffer));
message[TRUNCATE_SIZE] = 0;
if(excess> 0) {
printf("errlog: A message overran buffer by %d. This is VERY bad\n",
excess);
nchar = sprintf(&message[TRUNCATE_SIZE],
"\nerrlog = previous message overran buffer. It was truncated."
" size = %d excess = %d\n", size,excess);
} else {
nchar = sprintf(&message[TRUNCATE_SIZE],
"\nerrlog = previous message too long. It was truncated."
" size=%d It was truncated\n",size);
}
pnextSend->length = TRUNCATE_SIZE + nchar +1;
} else {
pnextSend->length = size+1;
}
pnextSend->length = size+1;
ellAdd(&pvtData.msgQueue,&pnextSend->node);
epicsMutexUnlock(pvtData.msgQueueLock);
epicsEventSignal(pvtData.waitForWork);