ref: 42fd6480b200aab21dc5118050b8f4753cd25967
parent: bcc4de52e4e216a3b5a9d734fed46a4d06c3252c
author: Roberto E. Vargas Caballero <[email protected]>
date: Wed Sep 2 07:41:05 EDT 2015
Add validation for float operations
--- a/cc1/fold.c
+++ b/cc1/fold.c
@@ -23,6 +23,24 @@
}
static bool
+addf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+ TFLOAT max = lim->max.f, min = lim->min.f;
+
+ if (l < 0 && r < 0 && l >= min - r ||
+ l == 0 ||
+ r == 0 ||
+ l < 0 && r > 0 ||
+ l > 0 && r < 0 ||
+ l > 0 && r > 0 && l <= max - r) {
+ return 1;
+ }
+ warn("overflow in constant expression");
+ return 0;
+}
+
+static bool
subi(TINT l, TINT r, Type *tp)
{
return addi(l, -r, tp);
@@ -29,6 +47,12 @@
}
static bool
+subf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ return addf(l, -r, tp);
+}
+
+static bool
muli(TINT l, TINT r, Type *tp)
{
struct limits *lim = getlimits(tp);
@@ -47,6 +71,24 @@
}
static bool
+mulf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+ TFLOAT max = lim->max.i, min = lim->min.i;
+
+ if (l > -1 && l <= 1 ||
+ r > -1 && r <= 1 ||
+ l < 0 && r < 0 && -l <= max/-r ||
+ l < 0 && r > 0 && l >= min/r ||
+ l > 0 && r < 0 && r >= min/l ||
+ l > 0 && r > 0 && l <= max/r) {
+ return 1;
+ }
+ warn("overflow in constant expression");
+ return 0;
+}
+
+static bool
divi(TINT l, TINT r, Type *tp)
{
struct limits *lim = getlimits(tp);
@@ -63,6 +105,25 @@
}
static bool
+divf(TFLOAT l, TFLOAT r, Type *tp)
+{
+ struct limits *lim = getlimits(tp);
+
+ if (l < 0) l = -l;
+ if (r < 0) r = -r;
+
+ if (r == 0.0) {
+ warn("division by 0");
+ return 0;
+ }
+ if (r < 1.0 && l > lim->max.f * r) {
+ warn("overflow in constant expression");
+ return 0;
+ }
+ return 1;
+}
+
+static bool
lshi(TINT l, TINT r, Type *tp)
{
if (r < 0 || r >= tp->size * 8) {
@@ -174,6 +235,18 @@
{
TFLOAT f;
TINT i;
+ bool (*validate)(TFLOAT, TFLOAT, Type *tp);
+
+ switch (op) {
+ case OADD: validate = addf; break;
+ case OSUB: validate = subf; break;
+ case OMUL: validate = mulf; break;
+ case ODIV: validate = divf; break;
+ default: validate = NULL; break;
+ }
+
+ if (validate && !(*validate)(l, r, res->type))
+ return 0;
switch (op) {
case OADD: f = l + r; break;