Fix a bug in detecting overflow in unsigned multiplication.

XXX Note that the overflow code for many cases seems to be buggy. I've
only fixed one bug that was bothering me. A set of regression tests
and extensive testing are needed.
This commit is contained in:
perry 2001-11-17 04:35:32 +00:00
parent 69e1926249
commit 46164f478c

View File

@ -1,4 +1,4 @@
/* $NetBSD: tree.c,v 1.21 2001/09/16 16:34:44 wiz Exp $ */
/* $NetBSD: tree.c,v 1.22 2001/11/17 04:35:32 perry Exp $ */
/*
* Copyright (c) 1994, 1995 Jochen Pohl
@ -33,7 +33,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: tree.c,v 1.21 2001/09/16 16:34:44 wiz Exp $");
__RCSID("$NetBSD: tree.c,v 1.22 2001/11/17 04:35:32 perry Exp $");
#endif
#include <stdlib.h>
@ -2607,6 +2607,12 @@ plength(type_t *tp)
return (getinode(st, (quad_t)(elem * elsz / CHAR_BIT)));
}
/*
* XXX
* Note: There appear to be a number of bugs in detecting overflow in
* this function. An audit and a set of proper regression tests are needed.
* --Perry Metzger, Nov. 16, 2001
*/
/*
* Do only as much as necessary to compute constant expressions.
* Called only if the operator allows folding and (both) operands
@ -2630,6 +2636,7 @@ fold(tnode_t *tn)
if (modtab[tn->tn_op].m_binary)
ur = sr = tn->tn_right->tn_val->v_quad;
mask = qlmasks[size(t)];
ovfl = 0;
switch (tn->tn_op) {
@ -2645,9 +2652,17 @@ fold(tnode_t *tn)
q = ~sl;
break;
case MULT:
q = utyp ? ul * ur : sl * sr;
if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1)))
ovfl = 1;
if (utyp) {
q = ul * ur;
if (q != (q & mask))
ovfl = 1;
else if ((ul != 0) && ((q / ul) != ur))
ovfl = 1;
} else {
q = sl * sr;
if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1)))
ovfl = 1;
}
break;
case DIV:
if (sr == 0) {
@ -2692,7 +2707,7 @@ fold(tnode_t *tn)
break;
case SHR:
/*
* The sign must be explizitly extended because
* The sign must be explicitly extended because
* shifts of signed values are implementation dependent.
*/
q = ul >> sr;
@ -2729,8 +2744,6 @@ fold(tnode_t *tn)
lerror("fold() 5");
}
mask = qlmasks[size(t)];
/* XXX does not work for quads. */
if (ovfl || ((q | mask) != ~(u_quad_t)0 && (q & ~mask) != 0)) {
if (hflag)