scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 42fd6480b200aab21dc5118050b8f4753cd25967
parent bcc4de52e4e216a3b5a9d734fed46a4d06c3252c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  2 Sep 2015 11:41:05 +0200

Add validation for float operations

Diffstat:
cc1/fold.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+), 0 deletions(-)

diff --git a/cc1/fold.c b/cc1/fold.c @@ -23,12 +23,36 @@ addi(TINT l, TINT r, Type *tp) } 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); } 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 @@ muli(TINT l, TINT r, Type *tp) } 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 @@ divi(TINT l, TINT r, Type *tp) } 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 @@ foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r) { 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;