dbStatic: avoid write past end of DBENTRY::message

Prevent long link strings (and maybe others)
from overflowing the fixed length string
buffer associated with each DBENTRY.
This commit is contained in:
Michael Davidsaver
2015-12-21 18:56:39 -05:00
parent 8f0950288a
commit e298fb4c27

View File

@@ -211,6 +211,27 @@ static char *getpMessage(DBENTRY *pdbentry)
return msg;
}
static
void dbMsgCpy(DBENTRY *pdbentry, const char *msg)
{
getpMessage(pdbentry);
strncpy(pdbentry->message, msg, messagesize-1);
pdbentry->message[messagesize-1] = '\0';
}
static
void dbMsgPrint(DBENTRY *pdbentry, const char *fmt, ...) EPICS_PRINTF_STYLE(2,3);
static
void dbMsgPrint(DBENTRY *pdbentry, const char *fmt, ...)
{
va_list args;
getpMessage(pdbentry);
va_start(args, fmt);
epicsVsnprintf(pdbentry->message, messagesize, fmt, args);
va_end(args);
}
/*Public only for dbStaticNoRun*/
dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
{
@@ -1718,15 +1739,29 @@ char * dbGetString(DBENTRY *pdbentry)
{
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
char *message;
DBLINK *plink;
message = getpMessage(pdbentry);
if(!pflddes) {strcpy(message,"fldDes not found"); return(message);}
if(!pflddes) {
dbMsgCpy(pdbentry, "fldDes not found");
return pdbentry->message;
}
switch (pflddes->field_type) {
case DBF_STRING:
if(!pfield) {strcpy(message,"Field not found"); return(message);}
strcpy(message, (char *)pfield);
case DBF_INLINK:
case DBF_OUTLINK:
case DBF_FWDLINK:
if(!pfield) {
dbMsgCpy(pdbentry, "Field not allocated (NULL)");
return pdbentry->message;
}
break;
default:
break;
}
switch (pflddes->field_type) {
case DBF_STRING:
dbMsgCpy(pdbentry, (char *)pfield);
break;
case DBF_CHAR:
case DBF_UCHAR:
@@ -1742,30 +1777,26 @@ char * dbGetString(DBENTRY *pdbentry)
return(dbGetStringNum(pdbentry));
case DBF_INLINK:
case DBF_OUTLINK:
if(!pfield) {strcpy(message,"Field not found"); return(message);}
plink = (DBLINK *)pfield;
switch(plink->type) {
case CONSTANT:
if(plink->value.constantStr) {
strcpy(message,plink->value.constantStr);
dbMsgCpy(pdbentry, plink->value.constantStr);
} else {
strcpy(message,"");
dbMsgCpy(pdbentry, "");
}
break;
case MACRO_LINK:
if(plink->value.macro_link.macroStr) {
strcpy(message,plink->value.macro_link.macroStr);
dbMsgCpy(pdbentry, plink->value.macro_link.macroStr);
} else {
strcpy(message,"");
dbMsgCpy(pdbentry, "");
}
break;
case PN_LINK:
if(plink->value.pv_link.pvname)
strcpy(message,plink->value.pv_link.pvname);
else
strcpy(message,"");
strcat(message," ");
strcat(message,msstring[plink->value.pv_link.pvlMask&pvlOptMsMode]);
case PN_LINK:
dbMsgPrint(pdbentry, "%s %s",
plink->value.pv_link.pvname ? plink->value.pv_link.pvname : "",
msstring[plink->value.pv_link.pvlMask&pvlOptMsMode]);
break;
case PV_LINK:
case CA_LINK:
@@ -1779,68 +1810,63 @@ char * dbGetString(DBENTRY *pdbentry)
else if(pvlMask&pvlOptCP) ppind=3;
else if(pvlMask&pvlOptCPP) ppind=4;
else ppind=0;
if (plink->value.pv_link.pvname) {
strcpy(message, plink->value.pv_link.pvname);
if (pvlMask & pvlOptTSELisTime)
strcat(message, ".TIME");
} else
strcpy(message,"");
strcat(message," ");
strcat(message,ppstring[ppind]);
strcat(message," ");
strcat(message,msstring[pvlMask&pvlOptMsMode]);
dbMsgPrint(pdbentry, "%s%s %s %s",
plink->value.pv_link.pvname ? plink->value.pv_link.pvname : "",
(pvlMask & pvlOptTSELisTime) ? ".TIME" : "",
ppstring[ppind],
msstring[plink->value.pv_link.pvlMask&pvlOptMsMode]);
break;
}
case VME_IO:
sprintf(message,"#C%d S%d @%s",
dbMsgPrint(pdbentry, "#C%d S%d @%s",
plink->value.vmeio.card,plink->value.vmeio.signal,
plink->value.vmeio.parm);
break;
case CAMAC_IO:
sprintf(message,"#B%d C%d N%d A%d F%d @%s",
dbMsgPrint(pdbentry, "#B%d C%d N%d A%d F%d @%s",
plink->value.camacio.b,plink->value.camacio.c,
plink->value.camacio.n,plink->value.camacio.a,
plink->value.camacio.f,plink->value.camacio.parm);
break;
case RF_IO:
sprintf(message,"#R%d M%d D%d E%d",
dbMsgPrint(pdbentry, "#R%d M%d D%d E%d",
plink->value.rfio.cryo,
plink->value.rfio.micro,
plink->value.rfio.dataset,
plink->value.rfio.element);
break;
case AB_IO:
sprintf(message,"#L%d A%d C%d S%d @%s",
dbMsgPrint(pdbentry, "#L%d A%d C%d S%d @%s",
plink->value.abio.link,plink->value.abio.adapter,
plink->value.abio.card,plink->value.abio.signal,
plink->value.abio.parm);
break;
case GPIB_IO:
sprintf(message,"#L%d A%d @%s",
dbMsgPrint(pdbentry, "#L%d A%d @%s",
plink->value.gpibio.link,plink->value.gpibio.addr,
plink->value.gpibio.parm);
break;
case BITBUS_IO:
sprintf(message,"#L%u N%u P%u S%u @%s",
dbMsgPrint(pdbentry, "#L%u N%u P%u S%u @%s",
plink->value.bitbusio.link,plink->value.bitbusio.node,
plink->value.bitbusio.port,plink->value.bitbusio.signal,
plink->value.bitbusio.parm);
break;
case BBGPIB_IO:
sprintf(message,"#L%u B%u G%u @%s",
dbMsgPrint(pdbentry, "#L%u B%u G%u @%s",
plink->value.bbgpibio.link,plink->value.bbgpibio.bbaddr,
plink->value.bbgpibio.gpibaddr,plink->value.bbgpibio.parm);
break;
case INST_IO:
sprintf(message,"@%s", plink->value.instio.string);
dbMsgPrint(pdbentry, "@%s", plink->value.instio.string);
break;
case VXI_IO :
if (plink->value.vxiio.flag == VXIDYNAMIC)
sprintf(message,"#V%d C%d S%d @%s",
dbMsgPrint(pdbentry, "#V%d C%d S%d @%s",
plink->value.vxiio.frame,plink->value.vxiio.slot,
plink->value.vxiio.signal,plink->value.vxiio.parm);
else
sprintf(message,"#V%d S%d @%s",
dbMsgPrint(pdbentry, "#V%d S%d @%s",
plink->value.vxiio.la,plink->value.vxiio.signal,
plink->value.vxiio.parm);
break;
@@ -1851,16 +1877,15 @@ char * dbGetString(DBENTRY *pdbentry)
case DBF_FWDLINK: {
DBLINK *plink=(DBLINK *)pfield;
if(!pfield) {strcpy(message,"Field not found"); return(message);}
switch(plink->type) {
case CONSTANT:
strcpy(message,"0");
dbMsgCpy(pdbentry, "0");
break;
case MACRO_LINK:
if(plink->value.macro_link.macroStr) {
strcpy(message,plink->value.macro_link.macroStr);
dbMsgCpy(pdbentry, plink->value.macro_link.macroStr);
} else {
strcpy(message,"");
dbMsgCpy(pdbentry, "");
}
break;
case PV_LINK:
@@ -1872,14 +1897,9 @@ char * dbGetString(DBENTRY *pdbentry)
pvlMask = plink->value.pv_link.pvlMask;
if(pvlMask&pvlOptCA) ppind=2;
else ppind=0;
if(plink->value.pv_link.pvname)
strcpy(message,plink->value.pv_link.pvname);
else
strcpy(message,"");
if(ppind) {
strcat(message," ");
strcat(message,ppstring[ppind]);
}
dbMsgPrint(pdbentry, "%s %s",
plink->value.pv_link.pvname ? plink->value.pv_link.pvname : "",
ppstring[ppind]);
break;
}
default :
@@ -1890,7 +1910,7 @@ char * dbGetString(DBENTRY *pdbentry)
default:
return(NULL);
}
return (message);
return pdbentry->message;
}
long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
@@ -3265,7 +3285,8 @@ void dbReportDeviceConfig(dbBase *pdbbase,FILE *report)
plink = pdbentry->pfield;
linkType = plink->type;
if(bus[linkType][0]==0) continue;
strcpy(linkValue,dbGetString(pdbentry));
strncpy(linkValue,dbGetString(pdbentry), NELEMENTS(linkValue)-1);
linkValue[NELEMENTS(linkValue)-1] = '\0';
status = dbFindField(pdbentry,"DTYP");
if(status) break;
strcpy(dtypValue,dbGetString(pdbentry));