Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions calcApp/src/aCalcPerform.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@
#define myMIN(a,b) (a)<(b)?(a):(b)
#define SMALL 1.e-9

/* Signed remainder that guards the one case C leaves undefined: INT_MIN % -1.
* On x86 the idiv used for '%' traps that quotient overflow as #DE, delivered
* as SIGFPE, killing the whole IOC. Mathematically x % -1 == 0 for every x, so
* return 0 for a -1 divisor instead of executing the trapping remainder. The
* divisor == 0 case is guarded separately at each call site. */
static long safeModulo(long a, long b)
{
if (b == -1) return 0;
return a % b;
}

static double local_random();
static int cond_search(const unsigned char **ppinst, int match);

Expand Down Expand Up @@ -647,7 +658,7 @@ long aCalcPerform(double *p_dArg, int num_dArgs, double **pp_aArg,
if ((int)ps1->a[i] == 0) {
ps->a[i] = myMAXFLOAT;
} else {
ps->a[i] = (double)((int)ps->a[i] % (int)ps1->a[i]);
ps->a[i] = (double)safeModulo((int)ps->a[i], (int)ps1->a[i]);
}
}
break;
Expand All @@ -671,7 +682,7 @@ long aCalcPerform(double *p_dArg, int num_dArgs, double **pp_aArg,
if ((int)ps1->d == 0) {
ps->a[i] = myMAXFLOAT;
} else {
ps->a[i] = (double)((int)ps->a[i] % (int)ps1->d);
ps->a[i] = (double)safeModulo((int)ps->a[i], (int)ps1->d);
}
}
break;
Expand All @@ -698,7 +709,7 @@ long aCalcPerform(double *p_dArg, int num_dArgs, double **pp_aArg,
if ((int)ps1->d == 0) {
ps->d = myMAXFLOAT;
} else {
ps->d = (double)((int)ps->d % (int)ps1->d);
ps->d = (double)safeModulo((int)ps->d, (int)ps1->d);
}
break;
}
Expand Down
16 changes: 14 additions & 2 deletions calcApp/src/sCalcPerform.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ static int cond_search(const unsigned char **ppinst, int match);
#define myMIN(a,b) (a)<(b)?(a):(b)
#define SMALL 1.e-11

/* Signed remainder that guards the one case C leaves undefined: INT_MIN % -1
* (here also INT64_MIN % -1 on LP64). On x86 the idiv used for '%' traps that
* quotient overflow as #DE, delivered as SIGFPE, killing the whole IOC.
* Mathematically x % -1 == 0 for every x, so return 0 for a -1 divisor instead
* of executing the trapping remainder. The divisor == 0 case is guarded
* separately at each call site. */
static long safeModulo(long a, long b)
{
if (b == -1) return 0;
return a % b;
}

#define DEBUG 1
#define INIT_STACK 1
volatile int sCalcPerformDebug = 0;
Expand Down Expand Up @@ -559,7 +571,7 @@ epicsShareFunc long
--pd;
if ((int)(pd[1]) == 0)
return(-1);
*pd = (double)((int)(*pd) % (int)(pd[1]));
*pd = (double)safeModulo((int)(*pd), (int)(pd[1]));
break;

case REL_OR:
Expand Down Expand Up @@ -1106,7 +1118,7 @@ epicsShareFunc long
toDouble(ps);
if ((long)ps1->d == 0)
return(-1);
ps->d = (double)((long)ps->d % (long)ps1->d);
ps->d = (double)safeModulo((long)ps->d, (long)ps1->d);
break;

case REL_OR:
Expand Down