[comp.sources.bugs] A bug in perl3. With a fix.

greim@sbsvax.UUCP (Michael Greim) (09/12/89)

Here's a bug report for perl3 and a fix for the bug.
This is only ment as an unofficial "quick fix".
I sent this report to Larry Wall too, who will probably include a bug fix of
his own in one of his next suit of patches.

A Bug in perl3.

Priority : medium

Symptoms:
	perl failed the test in base.term.
	The test

		$x = "\n";
		if ($x lt ' ') {print "ok 1\n";} else {print "not ok 1\n";}

	said "not ok 1".
	With the debug flag turned on, one sees that the result of
	the comparison "$s lt ' '" yields false.

Diagnosis:
	In several places bcmp is used. At least in one place, viz. the
	evaluation of the result of the O_SLT operator, the code relies
	on bcmp to return a value
	- less 0 if str1 < str2
	- 0 if str1 == str2
	- greater 0 if str1 > str2
	To cite the 4BSD manual page:
	
		bcmp(b1, b2, length)
		char *b1, *b2;
		int length;

		``bcmp compares sbyte string b1 against byte string b2, returning
		zero if they are identical, nonzero otherwise. Both strings are
		assumed to be length bytes long.''

	The code for O_SLT operator in eval.c:

    	case O_SLT:
		tmps = str_get(st[1]);
		value = (double) (str_cmp(st[1],st[2]) < 0);
		goto donumset;

	In routine str_cmp in str.c:

		if (str1->str_cur < str2->str_cur) {
-->			if (retval = bcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
				return retval;
			else
	    		return 1;
		}
-->		else if (retval = bcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
			return retval;
		else if (str1->str_cur == str2->str_cur)
			return 0;
		else
			return -1;

	The return of bcmp is returned as the result of str_cmp and tested
	if it is less than 0. Unfortunately according to the man page it is not
	guaranteed that the result of bcmp will be less than 0 .


Therapy:
	The best would be to examine the code for occurances of bcmp and
	rewrite it as necessary.
	A quick fix is to include a "handmade" bcmp. Here it is:

------ cut here ----------
bcmp (s1, s2, n)
	register unsigned char * s1;
	register unsigned char * s2;
	register int n;
/*
 * If bcmp returns always a number > 0 if s1 is not identical to s2 one
 * has to include this bcmp.
 *
 * Here is one which returns a number < 0 if s1 < s2 and a number > 0 if
 * s1 > s2.
 * ("unsigned char" to get subtraction correct)
 */
{
	while (n--) {
		if (*s1 != *s2)
			return ((int)(*s1 - *s2));
		s1++;
		s2++;
	}
	return (0);
}
------ cut here ----------


Absorb, apply and enjoy,

	-mg
-- 
Michael Greim    Email : greim@sbsvax.informatik.uni-saarland.dbp.de
                 or    : ...!uunet!unido!sbsvax!greim
[.signature removed by the board of censors for electronic mail's main
executive computer because it contained a four letter word ("word")]