diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index d2d32e559..a901b5190 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -14,6 +14,14 @@

Changes between 3.15.1 and 3.15.2

+

aoRecord raw conversion overflows

+ +

The ao record type now checks converted raw values and limits them to the +32-bit integer range before writing them to the RVAL field. Previously value +overflows relied on Undefined Behaviour which could give different results on +different platforms. The ROFF fields of the ao and ai record types are now +DBF_ULONG to allow an ROFF setting of 0x80000000 to work properly.

+

Changes to <top>/cfg/* files

The order in which cfg/CONFIG* and cfg/RULES* files are included from support diff --git a/src/ca/client/tools/tool_lib.c b/src/ca/client/tools/tool_lib.c index 8b9c5ca28..db670151a 100644 --- a/src/ca/client/tools/tool_lib.c +++ b/src/ca/client/tools/tool_lib.c @@ -85,7 +85,8 @@ static void sprint_long (char *ret, dbr_long_t val, IntFormatT outType) "0x%lX" /* hex */ }; - sprintf(ret, fmt[outType], val); + /* Formats have long modifier, pass value as a long */ + sprintf(ret, fmt[outType], (long) val); } } diff --git a/src/std/rec/aiRecord.dbd.pod b/src/std/rec/aiRecord.dbd.pod index e3f1cfdae..8da77055d 100644 --- a/src/std/rec/aiRecord.dbd.pod +++ b/src/std/rec/aiRecord.dbd.pod @@ -404,8 +404,8 @@ monitoring functionality. pp(TRUE) interest(2) } - field(ROFF,DBF_LONG) { - prompt("Raw Offset, obsolete") + field(ROFF,DBF_ULONG) { + prompt("Raw Offset") pp(TRUE) interest(2) } diff --git a/src/std/rec/aoRecord.c b/src/std/rec/aoRecord.c index a3def5607..63125593e 100644 --- a/src/std/rec/aoRecord.c +++ b/src/std/rec/aoRecord.c @@ -498,10 +498,20 @@ static void convert(aoRecord *prec, double value) } value -= prec->aoff; if (prec->aslo != 0) value /= prec->aslo; - if (value >= 0.0) - prec->rval = (epicsInt32)(value + 0.5) - prec->roff; - else - prec->rval = (epicsInt32)(value - 0.5) - prec->roff; + + /* Apply raw offset and limits, round to 32-bit integer */ + value -= prec->roff; + if (value >= 0.0) { + if (value >= (0x7fffffff - 0.5)) + prec->rval = 0x7fffffff; + else + prec->rval = (epicsInt32)(value + 0.5); + } else { + if (value > (0.5 - 0x80000000)) + prec->rval = (epicsInt32)(value - 0.5); + else + prec->rval = 0x80000000; + } } diff --git a/src/std/rec/aoRecord.dbd.pod b/src/std/rec/aoRecord.dbd.pod index 27e156ae1..5b9280a65 100644 --- a/src/std/rec/aoRecord.dbd.pod +++ b/src/std/rec/aoRecord.dbd.pod @@ -342,8 +342,8 @@ information on these fields. size(16) prop(YES) } - field(ROFF,DBF_LONG) { - prompt("Raw Offset, obsolete") + field(ROFF,DBF_ULONG) { + prompt("Raw Offset") pp(TRUE) interest(2) }