udpiiu: reject a non-finite or non-positive EPICS_CA_MAX_SEARCH_PERIOD

epicsScanDouble accepts "inf" and "nan", so envGetDoubleConfigParam
returns success for them and the parsed value flows into getMaxPeriod's
only range gate, maxPeriod < maxSearchPeriodLowerLimit. That comparison
is false for both inf and NaN, so a non-finite period reaches
getNTimers(), whose static_cast<unsigned> of 1 + log(maxPeriod/...)/log2
is an undefined float->unsigned conversion: inf aborts the client in
malloc via a garbage nTimers allocation, and NaN drives the search-timer
wheel off a NaN period where every deadline comparison is false.

Gate the parsed value on finite() (from epicsMath.h) and positivity
alongside the parse status, and fall back to the default period. A
non-positive period is not a "low" period to be clamped up to the 60 s
lower limit; it takes the same invalid-input path as inf/NaN.

getMaxPeriod() is getNTimers()'s only caller, so this makes the
conversion finite and positive by construction.
This commit is contained in:
Sang Woo Kim authored and Dirk Zimoch committed 2026-10-14 11:20:25 +02:00
1 parent 42db938a94
commit bd20c712f3
1 file changed
+5 -2
+5 -2
View File
@@ -30,6 +30,7 @@
#include "osiProcess.h"
#include "osiWireFormat.h"
#include "epicsAlgorithm.h"
#include "epicsMath.h"
#include "errlog.h"
#include "locationException.h"
@@ -73,7 +74,7 @@ double getMaxPeriod()
if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
long longStatus = envGetDoubleConfigParam (
& EPICS_CA_MAX_SEARCH_PERIOD, & maxPeriod );
if ( ! longStatus ) {
if ( ! longStatus && finite ( maxPeriod ) && maxPeriod > 0.0 ) {
if ( maxPeriod < maxSearchPeriodLowerLimit ) {
epicsPrintf ( "\"%s\" out of range (low)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
@@ -83,7 +84,9 @@ double getMaxPeriod()
}
}
else {
epicsPrintf ( "EPICS \"%s\" wasn't a real number\n",
/* Reset to default on parse error or out of range value */
maxPeriod = maxSearchPeriodDefault;
epicsPrintf ( "EPICS \"%s\" was not a positive real number\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, maxPeriod );