Make tests pass even if we use LTO.

This commit is contained in:
Dianne Skoll
2022-03-22 09:17:31 -04:00
parent b2d3d98d72
commit e651f92bd9
3 changed files with 37 additions and 40 deletions

View File

@@ -783,12 +783,11 @@ static int Add(void)
/* If both are ints, just add 'em */ /* If both are ints, just add 'em */
if (v2.type == INT_TYPE && v1.type == INT_TYPE) { if (v2.type == INT_TYPE && v1.type == INT_TYPE) {
int old = v1.v.val;
v1.v.val += v2.v.val;
/* Check for overflow */ /* Check for overflow */
if (_private_add_overflow(v1.v.val, v2.v.val, old)) { if (_private_add_overflow(v1.v.val, v2.v.val)) {
return E_2HIGH; return E_2HIGH;
} }
v1.v.val += v2.v.val;
PushValStack(v1); PushValStack(v1);
return OK; return OK;
} }
@@ -796,9 +795,8 @@ static int Add(void)
/* If it's a date plus an int, add 'em */ /* If it's a date plus an int, add 'em */
if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) || if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) ||
(v1.type == INT_TYPE && v2.type == DATE_TYPE)) { (v1.type == INT_TYPE && v2.type == DATE_TYPE)) {
int old = v1.v.val; if (_private_add_overflow(v1.v.val, v2.v.val)) return E_DATE_OVER;
v1.v.val += v2.v.val; v1.v.val += v2.v.val;
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
if (v1.v.val < 0) return E_DATE_OVER; if (v1.v.val < 0) return E_DATE_OVER;
v1.type = DATE_TYPE; v1.type = DATE_TYPE;
PushValStack(v1); PushValStack(v1);
@@ -808,9 +806,8 @@ static int Add(void)
/* If it's a datetime plus an int or a time, add 'em */ /* If it's a datetime plus an int or a time, add 'em */
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) || if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) { ((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
int old = v1.v.val; if (_private_add_overflow(v1.v.val, v2.v.val)) return E_DATE_OVER;
v1.v.val += v2.v.val; v1.v.val += v2.v.val;
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
if (v1.v.val < 0) return E_DATE_OVER; if (v1.v.val < 0) return E_DATE_OVER;
v1.type = DATETIME_TYPE; v1.type = DATETIME_TYPE;
PushValStack(v1); PushValStack(v1);
@@ -822,9 +819,8 @@ static int Add(void)
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) || if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
(v1.type == INT_TYPE && v2.type == TIME_TYPE) || (v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) { (v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
int old = v1.v.val; if (_private_add_overflow(v1.v.val, v2.v.val)) return E_DATE_OVER;
v1.v.val += v2.v.val; v1.v.val += v2.v.val;
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
v1.v.val = v1.v.val % MINUTES_PER_DAY; v1.v.val = v1.v.val % MINUTES_PER_DAY;
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY; if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
v1.type = TIME_TYPE; v1.type = TIME_TYPE;
@@ -885,18 +881,16 @@ static int Subtract(void)
/* If they're both INTs, do subtraction */ /* If they're both INTs, do subtraction */
if (v1.type == INT_TYPE && v2.type == INT_TYPE) { if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
int old = v1.v.val; if (_private_sub_overflow(v1.v.val, v2.v.val)) return E_2HIGH;
v1.v.val -= v2.v.val; v1.v.val -= v2.v.val;
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_2HIGH;
PushValStack(v1); PushValStack(v1);
return OK; return OK;
} }
/* If it's a date minus an int, do subtraction, checking for underflow */ /* If it's a date minus an int, do subtraction, checking for underflow */
if (v1.type == DATE_TYPE && v2.type == INT_TYPE) { if (v1.type == DATE_TYPE && v2.type == INT_TYPE) {
int old = v1.v.val; if (_private_sub_overflow(v1.v.val, v2.v.val)) return E_DATE_OVER;
v1.v.val -= v2.v.val; v1.v.val -= v2.v.val;
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
if (v1.v.val < 0) return E_DATE_OVER; if (v1.v.val < 0) return E_DATE_OVER;
PushValStack(v1); PushValStack(v1);
return OK; return OK;
@@ -905,9 +899,8 @@ static int Subtract(void)
/* If it's a datetime minus an int or a time, do subtraction, /* If it's a datetime minus an int or a time, do subtraction,
* checking for underflow */ * checking for underflow */
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) { if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
int old = v1.v.val; if (_private_sub_overflow(v1.v.val, v2.v.val)) return E_DATE_OVER;
v1.v.val -= v2.v.val; v1.v.val -= v2.v.val;
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
if (v1.v.val < 0) return E_DATE_OVER; if (v1.v.val < 0) return E_DATE_OVER;
PushValStack(v1); PushValStack(v1);
return OK; return OK;
@@ -925,9 +918,8 @@ static int Subtract(void)
if ((v1.type == TIME_TYPE && v2.type == TIME_TYPE) || if ((v1.type == TIME_TYPE && v2.type == TIME_TYPE) ||
(v1.type == DATETIME_TYPE && v2.type == DATETIME_TYPE) || (v1.type == DATETIME_TYPE && v2.type == DATETIME_TYPE) ||
(v1.type == DATE_TYPE && v2.type == DATE_TYPE)) { (v1.type == DATE_TYPE && v2.type == DATE_TYPE)) {
int old = v1.v.val; if (_private_sub_overflow(v1.v.val, v2.v.val)) return E_DATE_OVER;
v1.v.val -= v2.v.val; v1.v.val -= v2.v.val;
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
v1.type = INT_TYPE; v1.type = INT_TYPE;
PushValStack(v1); PushValStack(v1);
return OK; return OK;
@@ -962,11 +954,8 @@ static int Multiply(void)
(v1.v.val == -1 && v2.v.val == INT_MIN)) { (v1.v.val == -1 && v2.v.val == INT_MIN)) {
return E_2HIGH; return E_2HIGH;
} }
int old = v1.v.val; if (_private_mul_overflow(v1.v.val, v2.v.val)) return E_2HIGH;
v1.v.val *= v2.v.val; v1.v.val *= v2.v.val;
if (v2.v.val != 0) {
if (_private_div(v1.v.val, v2.v.val) != old) return E_2HIGH;
}
PushValStack(v1); PushValStack(v1);
return OK; return OK;
} }
@@ -1177,9 +1166,8 @@ static int UnMinus(void)
{ {
Value *v = &ValStack[ValStackPtr-1]; Value *v = &ValStack[ValStackPtr-1];
if (v->type != INT_TYPE) return E_BAD_TYPE; if (v->type != INT_TYPE) return E_BAD_TYPE;
int old = v->v.val; if (v->v.val == INT_MIN) return E_2HIGH;
v->v.val = -v->v.val; v->v.val = -v->v.val;
if (_private_unminus_overflow(old, v->v.val)) return E_2HIGH;
return OK; return OK;
} }

View File

@@ -58,7 +58,7 @@ else \
in various arithmetic operators. They have to be in separate in various arithmetic operators. They have to be in separate
functions with extern linkage to defeat compiler optimizations functions with extern linkage to defeat compiler optimizations
that would otherwise break the overflow checks. */ that would otherwise break the overflow checks. */
extern int _private_div(int a, int b); extern int _private_mul_overflow(int a, int b);
extern int _private_add_overflow(int result, int b, int old); extern int _private_add_overflow(int a, int b);
extern int _private_sub_overflow(int result, int b, int old); extern int _private_sub_overflow(int a, int b);
extern int _private_unminus_overflow(int a, int b);

View File

@@ -130,24 +130,33 @@ int DateOK(int y, int m, int d)
/* Functions designed to defeat gcc optimizer */ /* Functions designed to defeat gcc optimizer */
int _private_div(int a, int b) { return a/b; } int _private_mul_overflow(int a, int b)
int _private_add_overflow(int result, int b, int old)
{ {
if (b > 0 && result < old) return 1; double aa = (double) a;
if (b < 0 && result > old) return 1; double bb = (double) b;
return 0;
} if (aa*bb > (double) INT_MAX || aa*bb < (double) INT_MIN) {
int _private_sub_overflow(int result, int b, int old) return 1;
{ }
if (b < 0 && result < old) return 1;
if (b > 0 && result > old) return 1;
return 0; return 0;
} }
int _private_unminus_overflow(int a, int b) int _private_add_overflow(int a, int b)
{ {
if (a > 0 && b > 0) return 1; double aa = (double) a;
if (a < 0 && b < 0) return 1; double bb = (double) b;
if (aa+bb < (double) INT_MIN) return 1;
if (aa+bb > (double) INT_MAX) return 1;
return 0;
}
int _private_sub_overflow(int a, int b)
{
double aa = (double) a;
double bb = (double) b;
if (aa-bb < (double) INT_MIN) return 1;
if (aa-bb > (double) INT_MAX) return 1;
return 0; return 0;
} }