Experimental Physics and Industrial Control System
A possible problem exists when a DBR_STRING request is made
for a DBF_DOUBLE field. The problem exists in release 3.12.2
and possibly earlier releases. In order for the problem to appear
the following must be true:
1) Locally written record support is used.
2) The get_precision routine calls recGblGetPrec
without setting precision to some default.
NOTE: ALL record support supplied with EPICS base are OK.
The problem was discovered by Tim Mooney (APS/XFD).
In his case the result was a hard crash of his IOC,
which made it really fun to find the problem.
The gory details are as follows:
Unless get_precision sets precision to some default
no other ioc code does. Things start with
an internal conversion routine called getDoubleString.
The final routine involved is routine cvtDoubleToString.
It begins with the code:
int cvtDoubleToString(
double flt_value,
char *pstr_value,
unsigned short precision)
{
unsigned short got_one,i;
long whole,iplace,number,fraction,fplace;
double ftemp;
char *startAddr;
/* can this routine handle this conversion */
if (precision > 8 || flt_value > 10000000.0 || flt_value < -10000000.0)
{
if (precision > 8 || flt_value > 1e16 || flt_value < -1e16) {
/*if(precision>17) precision=17;*/
sprintf(pstr_value,"%*.*e\0",precision+7,precision,
flt_value);
...
NOTE: The commented out line
/*if(precision>17) precision=17;*/
Is NOT present in the 3.12.2 version.
Since precision was never initialized it can have any value
between 0 and 65535. In Tim Mooneys case it had the
value 0xeee (vxWorks initializes stack to this value).
Thus the sprintf generates a string of length 0xeee + 7.
Since the receive buffer is 40 bytes (it was a Channel
Access call) it wipes out some portion of memory.
Solution:
For 3.12.2 make sure that any locally written record support
codes the get_precision starting as follows:
static long get_precision(DBADDR *paddr, long *precision)
{
aiRecord *pai=(aiRecord *)paddr->precord;
*precision = pai->prec;
For 3.13 the following will be done.
1) getDoubleString (and corresponding fast convert routine)
initializes precision to 0.
2) cvtDoubleToString adds the commented out statement shown
above.
All record support should still follow the example shown above.
Marty Kraimer
- Navigate by Date:
- Prev:
PC-port status Bob Dalesio
- Next:
Drivers Fred Carter
- Index:
1994
1995
<1996>
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
PC-port status Bob Dalesio
- Next:
Drivers Fred Carter
- Index:
1994
1995
<1996>
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024