Subject: lib/4845: [dM] broken quad shift by 0
To: None <gnats-bugs@gnats.netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 01/19/1998 18:24:04
>Number:         4845
>Category:       lib
>Synopsis:       [dM] broken quad shift by 0
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jan 19 15:35:01 1998
>Last-Modified:
>Originator:     der Mouse
>Organization:
	Dis-
>Release:        1.3
>Environment:
	Any 32-bit architecture for which shifting by 32 is equivalent
	to shifting by 0, and which uses lib/libc/quad/?sh?di3.c (at
	least rev 1.4) for shifting quads.  First noticed on a
	SPARCstation 1+.
>Description:
	When calling one of the [al]sh[lr]di3 routines to shift a quad,
	if the shift amount is zero, the result is incorrect.  (This
	won't normally happen, of course, unless the shift count is
	run-time variable.)  I would normally classify this as priority
	high; the reason I marked it only medium is that obviously
	shifting quads by variable amounts isn't done much, or this
	would have been caught much sooner - the current rev of these
	four files is over six months old.

	I actually noticed this when shifting unsigned quads left.
	Code inspection reveals the same problem exists in all four
	variants.
>How-To-Repeat:
	% cat foo.c
	#include <stdio.h>
	int main(void) {
	unsigned long long int q; int s;
	while (scanf("%d",&s) == 1)
	{ q = 1; q <<= s;
	  printf("0x1 << %d = 0x%qx\n",s,q);
	} }
	% cc -o foo foo.c
	% ./foo
	1
	0x1 << 1 = 0x2
	31
	0x1 << 31 = 0x80000000
	32
	0x1 << 32 = 0x100000000
	0
	0x1 << 0 = 0x100000001

	...say what??
>Fix:
	Here's what I'm doing.  It may be preferable to do what
	revision 1.2 of these four files did that avoided this problem,
	and instead change the "else" to "else if (shift > 0)".
	
	--- OLD/lib/libc/quad/ashldi3.c	Thu Jan  1 00:00:00 1970
	+++ NEW/lib/libc/quad/ashldi3.c	Thu Jan  1 00:00:00 1970
	@@ -59,6 +59,7 @@
	 {
	 	union uu aa;
	 
	+	if (shift == 0) return(a);
	 	aa.q = a;
	 	if (shift >= LONG_BITS) {
	 		aa.ul[H] = aa.ul[L] << (shift - LONG_BITS);
	--- OLD/lib/libc/quad/ashrdi3.c	Thu Jan  1 00:00:00 1970
	+++ NEW/lib/libc/quad/ashrdi3.c	Thu Jan  1 00:00:00 1970
	@@ -58,6 +58,7 @@
	 {
	 	union uu aa;
	 
	+	if (shift == 0) return(a);
	 	aa.q = a;
	 	if (shift >= LONG_BITS) {
	 		long s;
	--- OLD/lib/libc/quad/lshldi3.c	Thu Jan  1 00:00:00 1970
	+++ NEW/lib/libc/quad/lshldi3.c	Thu Jan  1 00:00:00 1970
	@@ -59,6 +59,7 @@
	 {
	 	union uu aa;
	 
	+	if (shift == 0) return(a);
	 	aa.q = a;
	 	if (shift >= LONG_BITS) {
	 		aa.ul[H] = aa.ul[L] << (shift - LONG_BITS);
	--- OLD/lib/libc/quad/lshrdi3.c	Thu Jan  1 00:00:00 1970
	+++ NEW/lib/libc/quad/lshrdi3.c	Thu Jan  1 00:00:00 1970
	@@ -58,6 +58,7 @@
	 {
	 	union uu aa;
	 
	+	if (shift == 0) return(a);
	 	aa.q = a;
	 	if (shift >= LONG_BITS) {
	 		aa.ul[L] = aa.ul[H] >> (shift - LONG_BITS);

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B
>Audit-Trail:
>Unformatted: