commit bbd01c3002170a72e7d82fdabd60dedd0cca9ae4
parent 87c077405904cd63f73c2b66a96b8a10defef19c
Author: Karl Schultheisz <k@kdsch.org>
Date: Sat, 14 May 2022 22:00:00 -0400
eval: avoid float exception in compile-time exprs
Generate a diagnostic message for compile time expressions with a zero
divisor or modulus, which would cause a floating-point exception during
evaluation.
Signed-off-by: Karl Schultheisz <k@kdsch.org>
Diffstat:
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/src/eval.c b/src/eval.c
@@ -181,11 +181,23 @@ eval_binarithm(struct context *ctx, struct expression *in, struct expression *ou
break;
case BIN_DIV:
if (type_is_float(lvalue.result)) {
- fval = ftrunc(lvalue.result, flval) / ftrunc(rvalue.result, frval);
+ double r = ftrunc(rvalue.result, frval);
+ if (r == 0) {
+ return EVAL_INVALID;
+ }
+ fval = ftrunc(lvalue.result, flval) / r;
} else if (type_is_signed(lvalue.result)) {
- ival = itrunc(lvalue.result, ilval) / itrunc(rvalue.result, irval);
+ uintmax_t r = itrunc(rvalue.result, irval);
+ if (r == 0) {
+ return EVAL_INVALID;
+ }
+ ival = itrunc(lvalue.result, ilval) / r;
} else {
- uval = itrunc(lvalue.result, ulval) / itrunc(rvalue.result, urval);
+ uintmax_t r = itrunc(rvalue.result, urval);
+ if (r == 0) {
+ return EVAL_INVALID;
+ }
+ uval = itrunc(lvalue.result, ulval) / r;
}
break;
case BIN_LSHIFT:
@@ -205,8 +217,16 @@ eval_binarithm(struct context *ctx, struct expression *in, struct expression *ou
case BIN_MODULO:
assert(!type_is_float(lvalue.result));
if (type_is_signed(lvalue.result)) {
+ uintmax_t r = itrunc(rvalue.result, irval);
+ if (r == 0) {
+ return EVAL_INVALID;
+ }
ival = itrunc(lvalue.result, ilval) % itrunc(rvalue.result, irval);
} else {
+ uintmax_t r = itrunc(rvalue.result, urval);
+ if (r == 0) {
+ return EVAL_INVALID;
+ }
uval = itrunc(lvalue.result, ulval) % itrunc(rvalue.result, urval);
}
break;