diff options
| author | Michael Forney <mforney@mforney.org> | 2022-05-19 11:49:06 -0700 | 
|---|---|---|
| committer | Michael Forney <mforney@mforney.org> | 2022-05-19 11:49:06 -0700 | 
| commit | 13eb0640cc58bee1a29c82c1b230137e7ff411c3 (patch) | |
| tree | 4dcf9bde63a4a8c49236dc8cc3413bd753563ef4 | |
| parent | b82a2315827553f8d1e7476b1261c5f1d00a7c7e (diff) | |
| download | cproc-13eb0640cc58bee1a29c82c1b230137e7ff411c3.tar.xz | |
eval: Fix range check of double during conversion to int
2⁶⁴-1 and 2⁶³-1 are not representable as double and get rounded to
2⁶⁴ and 2⁶³ respectively, which are outside the range of 64-bit
[u]int.
This causes undefined behavior when a constant expression is evaluated
that involves a conversion of a very large or small value to an
integer type.
To fix this, change the > to >= and use constants representable as
double.
| -rw-r--r-- | eval.c | 4 | 
1 files changed, 2 insertions, 2 deletions
| @@ -162,11 +162,11 @@ eval(struct expr *expr, enum evalkind kind)  					expr->u.constant.f = l->u.constant.u;  			} else if (l->type->prop & PROPFLOAT && t->prop & PROPINT) {  				if (t->u.basic.issigned) { -					if (l->u.constant.f < -1 - 0x7fffffffffffffff || l->u.constant.f > 0x7fffffffffffffff) +					if (l->u.constant.f < -0x1p63 || l->u.constant.f >= 0x1p63)  						error(&tok.loc, "integer part of floating-point constant %g cannot be represented as signed integer", l->u.constant.f);  					expr->u.constant.i = l->u.constant.f;  				} else { -					if (l->u.constant.f < 0 || l->u.constant.f > 0xffffffffffffffff) +					if (l->u.constant.f < 0.0 || l->u.constant.f >= 0x1p64)  						error(&tok.loc, "integer part of floating-point constant %g cannot be represented as unsigned integer", l->u.constant.f);  					expr->u.constant.u = l->u.constant.f;  				} | 
