[net.bugs.uucp] Bug in pk0.c on 32 bit machines

wes@felix.UUCP (07/08/83)

Reference: <>

	Neil MacKenzie of Simon Fraser University (143@sfucmpt.UUCP) asked
for help in getting uucp to run between a Perkin-Elmer machine and a VAX.
The symptom was alarm messages from uucico after protocol selection.  Since
I've run across a similar problem on a couple of 32 bit machines using
the PCC compiler (esp. UniSoft ports to 68000's), I thought that the
fix deserved general notice.

	The bug is in pk0.c and appears at or near line 620 in the routine
chksum():

620c620
old< 		if ((unsigned)sum <= t) {
---
new> 		if ((unsigned short)sum <= t) {

The problem is in the meaning of casts, which were initially implemented
differently in the Ritchie and PCC compilers.  Sum is declared as short and
t as unsigned short.  The PCC compiler defines unsigned to be unsigned int
which on the Motorola 68000 and, I strongly suspect, the Perkin-Elmer is
the same as unsigned long.  The code that gets generated (properly according
to the most recent interpretation of casts) for "(unsigned)sum <= t" is:
	sign-extend sum to a long (because the underlying type decides
		the type of extension)
	zero extend t to a long (ditto)
	compare as unsigned longs
What was desired is to do an unsigned comparison of sum and t as
shorts (hence the fix).

	Wes Chalfant
	FileNet Corp.
	..!{decvax,ucbvax}!trw-unix!felix!wes

chris@umcp-cs.UUCP (07/10/83)

Yeah, that checksum routine (shall we say) sucks.  I did a profile of
our (slightly modified) 4.1BSD uucico on our CVL connection, which is a
9600 baud hardwired link.  Uucico was spending most of its time in
system calls, namely read, write, and any directory-touching calls, but
chksum() was the top user-level CPU eater.  No wonder:  it uses
"register unsigned short"s, which (on VAXen) means unsigned shorts.
This is ridiculously expensive, so I rewrote it.  Here's what I've got
now; this has been working for about a month with no trouble.  It gets
turned into much nicer code, especially after optimization.

# if vax

/*
 * Vax-specific checksum generator, same checksum as portable version
 * but faster.  NOTE: ASSUMES n < 65535
 * 14 June 1983
 * Chris Torek
 * University of Maryland
 */
chksum (s, n)
register char *s;
register n;
{
	register sum, x;
	register unsigned t;

	sum = -1;
	x = 0;
	do {
		/* Rotate left, copying bit 15 to bit 0 */
		if (sum & 0x8000)
			sum <<= 1, sum++;
		else
			sum <<= 1;
		sum &= 0xffff;		/* Switch to unsigned short */
		t = sum;
		sum = (sum + (*s++ & 0377)) & 0xffff;
		x += sum ^ n;
		if ((unsigned)sum <= t)	/* (unsigned) not necessary */
			sum ^= x;	/* but doesn't hurt */
	} while (--n > 0);

	return (int) (short) sum;
}

# else (not vax)

[ original routine, elided due to licensing ]

# endif (vax)
-- 
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs
ARPA:	chris.umcp-cs@UDel-Relay