dbStatic: dbPutStringNum() overflow handling
Default to accepting over-size integers in DB fields, truncate to field size. E.g. permits setting DBF_LONG fields to 0xffffffff. Adds dbConvertStrict config variable to disable this.
This commit is contained in:
@@ -50,6 +50,14 @@ void testGetString(void)
|
||||
testdbGetStringEqual("recoverwrite.DISV", "0");
|
||||
}
|
||||
|
||||
static
|
||||
void testStringMax(void)
|
||||
{
|
||||
testDiag("testStringMax()");
|
||||
|
||||
testdbGetStringEqual("recmax.DISA", "-1");
|
||||
}
|
||||
|
||||
void dbTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
MAIN(dbPutGet)
|
||||
@@ -63,6 +71,8 @@ MAIN(dbPutGet)
|
||||
|
||||
testGetString();
|
||||
|
||||
testStringMax();
|
||||
|
||||
testdbCleanup();
|
||||
|
||||
return testDone();
|
||||
|
||||
@@ -29,3 +29,7 @@ record(x, "recoverwrite") {
|
||||
field(DISA, "")
|
||||
field(DISV, "")
|
||||
}
|
||||
|
||||
record(x, "recmax") {
|
||||
field(DISA, "0xffffffff")
|
||||
}
|
||||
|
||||
@@ -244,6 +244,7 @@ epicsShareFunc void dbCatString(char **string, int *stringLength,
|
||||
char *pnew, char *separator);
|
||||
|
||||
extern int dbStaticDebug;
|
||||
extern int dbConvertStrict;
|
||||
|
||||
#define S_dbLib_recordTypeNotFound (M_dbLib|1) /* Record Type does not exist */
|
||||
#define S_dbLib_recExists (M_dbLib|3) /* Record Already exists */
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "epicsTypes.h"
|
||||
#include "errMdef.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsExport.h" /* #define epicsExportSharedSymbols */
|
||||
#include "dbBase.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbStaticLib.h"
|
||||
@@ -31,6 +31,9 @@
|
||||
#include "devSup.h"
|
||||
#include "special.h"
|
||||
|
||||
epicsShareDef int dbConvertStrict = 0;
|
||||
epicsExportAddress(int, dbConvertStrict);
|
||||
|
||||
static long do_nothing(struct dbCommon *precord) { return 0; }
|
||||
|
||||
/* Dummy DSXT used for soft device supports */
|
||||
@@ -372,39 +375,85 @@ long dbPutStringNum(DBENTRY *pdbentry, const char *pstring)
|
||||
{
|
||||
dbFldDes *pflddes = pdbentry->pflddes;
|
||||
void *pfield = pdbentry->pfield;
|
||||
long status;
|
||||
epicsUInt64 u64;
|
||||
epicsInt64 i64;
|
||||
|
||||
if (!pfield)
|
||||
return S_dbLib_fieldNotFound;
|
||||
|
||||
/* empty string is the same as writing numeric zero */
|
||||
if(pstring[0]=='\0')
|
||||
if (pstring[0] == '\0')
|
||||
pstring = "0";
|
||||
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_CHAR:
|
||||
return epicsParseInt8(pstring, pfield, 0, NULL);
|
||||
|
||||
case DBF_UCHAR:
|
||||
return epicsParseUInt8(pstring, pfield, 0, NULL);
|
||||
if (dbConvertStrict)
|
||||
return epicsParseInt8(pstring, pfield, 0, NULL);
|
||||
goto lax_signed;
|
||||
|
||||
case DBF_SHORT:
|
||||
return epicsParseInt16(pstring, pfield, 0, NULL);
|
||||
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
return epicsParseUInt16(pstring, pfield, 0, NULL);
|
||||
if (dbConvertStrict)
|
||||
return epicsParseInt16(pstring, pfield, 0, NULL);
|
||||
goto lax_signed;
|
||||
|
||||
case DBF_LONG:
|
||||
return epicsParseInt32(pstring, pfield, 0, NULL);
|
||||
|
||||
case DBF_ULONG:
|
||||
return epicsParseUInt32(pstring, pfield, 0, NULL);
|
||||
if (dbConvertStrict)
|
||||
return epicsParseInt32(pstring, pfield, 0, NULL);
|
||||
goto lax_signed;
|
||||
|
||||
case DBF_INT64:
|
||||
return epicsParseInt64(pstring, pfield, 0, NULL);
|
||||
if (dbConvertStrict)
|
||||
return epicsParseInt64(pstring, pfield, 0, NULL);
|
||||
|
||||
lax_signed:
|
||||
status = epicsParseInt64(pstring, &i64, 0, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_CHAR: *(epicsInt8 *)pfield = (epicsInt8) i64; break;
|
||||
case DBF_SHORT: *(epicsInt16*)pfield = (epicsInt16)i64; break;
|
||||
case DBF_LONG: *(epicsInt32*)pfield = (epicsInt32)i64; break;
|
||||
case DBF_INT64: *(epicsInt64*)pfield = (epicsInt64)i64; break;
|
||||
default: break;
|
||||
}
|
||||
return status;
|
||||
|
||||
case DBF_UCHAR:
|
||||
if (dbConvertStrict)
|
||||
return epicsParseUInt8(pstring, pfield, 0, NULL);
|
||||
goto lax_unsigned;
|
||||
|
||||
case DBF_ENUM:
|
||||
case DBF_USHORT:
|
||||
if (dbConvertStrict)
|
||||
return epicsParseUInt16(pstring, pfield, 0, NULL);
|
||||
goto lax_unsigned;
|
||||
|
||||
case DBF_ULONG:
|
||||
if (dbConvertStrict)
|
||||
return epicsParseUInt32(pstring, pfield, 0, NULL);
|
||||
goto lax_unsigned;
|
||||
|
||||
case DBF_UINT64:
|
||||
return epicsParseUInt64(pstring, pfield, 0, NULL);
|
||||
if (dbConvertStrict)
|
||||
return epicsParseUInt64(pstring, pfield, 0, NULL);
|
||||
|
||||
lax_unsigned:
|
||||
status = epicsParseUInt64(pstring, &u64, 0, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_UCHAR: *(epicsUInt8 *)pfield = (epicsInt8) u64; break;
|
||||
case DBF_ENUM:
|
||||
case DBF_USHORT: *(epicsUInt16*)pfield = (epicsInt16)u64; break;
|
||||
case DBF_ULONG: *(epicsUInt32*)pfield = (epicsInt32)u64; break;
|
||||
case DBF_UINT64: *(epicsUInt64*)pfield = (epicsInt64)u64; break;
|
||||
default: break;
|
||||
}
|
||||
return status;
|
||||
|
||||
case DBF_FLOAT:
|
||||
return epicsParseFloat32(pstring, pfield, NULL);
|
||||
|
||||
@@ -14,6 +14,7 @@ variable(dbRecordsOnceOnly,int)
|
||||
variable(dbRecordsAbcSorted,int)
|
||||
variable(dbBptNotMonotonic,int)
|
||||
variable(dbQuietMacroWarnings,int)
|
||||
variable(dbConvertStrict,int)
|
||||
|
||||
# dbLoadTemplate settings
|
||||
variable(dbTemplateMaxVars,int)
|
||||
|
||||
Reference in New Issue
Block a user