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: