From dean-debian@arctic.org Tue Feb 10 18:41:07 2004
Date: Sat, 20 Apr 2002 12:21:22 -0700 (PDT)
From: dean gaudet <dean-debian@arctic.org>
To: submit@bugs.debian.org
Subject: unsigned long long sign extension bugs
X-comment: visit http://arctic.org/~dean/legal for information regarding
    copyright and disclaimer.

Package: strace
Version: 4.4-1.2

the patch below fixes some sign extension bugs, at least on 32-bit
arches... i don't know the correct way to fix this for 64-bit
architectures, my patch may just work, but i have none to try with.

the problem is that:

	int foo = 0x80000000;

means:

	(unsigned long long) foo == 0xffffffff80000000ULL;

foo is promoted first to a (long long) which requires sign extension.

in strace in many place it constructs 64-bit quantities by shifing and
oring 32-bit quantities, and when the lower half is signed, the
extension corrupts the top half.

for example, before the patch i would see:

_llseek(6, 18446744071562067968, [2147483648], SEEK_SET) = 0

and with the patch i see:

_llseek(6, 2147483648, [2147483648], SEEK_SET) = 0

-dean


diff -ru strace-4.4/defs.h strace-4.4.dg/defs.h
--- strace-4.4/defs.h	Fri Sep 21 14:50:35 2001
+++ strace-4.4.dg/defs.h	Sun Mar 17 07:38:13 2002
@@ -528,9 +528,9 @@

 #if HAVE_LITTLE_ENDIAN_LONG_LONG
 #define LONG_LONG(_l,_h) \
-    ((long long)((unsigned long long)(_l) | ((unsigned long long)(_h)<<32)))
+    ((long long)((unsigned long long)(unsigned)(_l) | ((unsigned long long)(_h)<<32)))
 #else
 #define LONG_LONG(_l,_h) \
-    ((long long)((unsigned long long)(_h) | ((unsigned long long)(_l)<<32)))
+    ((long long)((unsigned long long)(unsigned)(_h) | ((unsigned long long)(_l)<<32)))
 #endif
 #endif
diff -ru strace-4.4/file.c strace-4.4.dg/file.c
--- strace-4.4/file.c	Tue Mar 27 04:17:17 2001
+++ strace-4.4.dg/file.c	Sun Mar 17 07:26:01 2002
@@ -404,11 +404,11 @@
 	if (tcp->u_arg[4] == SEEK_SET)
 	    tprintf("%ld, %llu, ", tcp->u_arg[0],
 		    (((long long int) tcp->u_arg[1]) << 32
-		     | (unsigned long long) tcp->u_arg[2]));
+		     | (unsigned long long) (unsigned) tcp->u_arg[2]));
 	else
 	    tprintf("%ld, %lld, ", tcp->u_arg[0],
 		    (((long long int) tcp->u_arg[1]) << 32
-		     | (unsigned long long) tcp->u_arg[2]));
+		     | (unsigned long long) (unsigned) tcp->u_arg[2]));
     }
     else {
 	long long int off;
diff -ru strace-4.4/io.c strace-4.4.dg/io.c
--- strace-4.4/io.c	Fri Jul 13 15:07:45 2001
+++ strace-4.4.dg/io.c	Sun Mar 17 07:34:32 2002
@@ -162,7 +162,7 @@
 #else
 		tprintf(", %lu, %llu", tcp->u_arg[2],
 				(((unsigned long long) tcp->u_arg[4]) << 32
-				 | tcp->u_arg[3]));
+				 | (unsigned) tcp->u_arg[3]));
 #endif
 	}
 	return 0;
@@ -181,7 +181,7 @@
 #else
 		tprintf(", %lu, %llu", tcp->u_arg[2],
 				(((unsigned long long) tcp->u_arg[4]) << 32
-				 | tcp->u_arg[3]));
+				 | (unsigned) tcp->u_arg[3]));
 #endif
 	}
 	return 0;
@@ -199,7 +199,7 @@
 	if (entering(tcp)) {
 		tprintf("%ld, %ld, %llu, %lu", tcp->u_arg[0], tcp->u_arg[1],
 			(((unsigned long long) tcp->u_arg[3]) << 32 |
-			 tcp->u_arg[2]), tcp->u_arg[4]);
+			 (unsigned) tcp->u_arg[2]), tcp->u_arg[4]);
 	} else {
 		off_t offset;




