[comp.mail.uucp] Bug in Smail 2.5 and Fix

mjy@sdti.SDTI.COM (Michael J. Young) (12/02/88)

Well, it finally happened.  The maps have gotten so large that I can no
longer run pathalias on even just [du].usa.* without running out of memory
(4.5 Meg) on a swapping Unix.  So I had to go back to using 'smart-host' to
get my routing done.  And guess what?  Smail 2.5 never seems to be able to
find 'smart-host' in my 'paths' file if it happened to be the last line of
the file.

It turns out that there are a couple of problems with the binary search
routine in getpath.c (looks like the quote on line 50 was prophetic!).
These were discovered and fixed by my colleague, Prescott K. Turner
(turner@sdti.sdti.com), who really seems to enjoy fixing binary search
routines!  The following comments are what he told me:

1.  Line 67:  Reaching EOF during the string search rules out the upper
    half of the range (between middle and hi).  It shouldn't rule out
    the entire range.  Line 67 should be changed to "break;".

    Note that as the code exists, the test for "c != EOF" on line 74
    is never operative.  But with the recommended fix, the test has the
    proper effect.  Perhaps this bug was introduced in order to avoid
    the bug on line 59.

2.  Line 59:  The test for EOF should be moved inside the "pos != 0"
    if on line 56, to make sure that the test is only made if "c" has
    been updated since the last fseek.

So here's the "official" bug report and suggested fix:

Problem:
	A bug in the binary search routine in getpath() causes smail
	to sometimes fail to find an entry in /usr/lib/uucp/paths.
	The problem shows up when the searched-for entry happens to
	be the last entry in the 'paths' file.  Under some conditions
	getpath() seeks into the middle of the last line, moves to the
	end of the line, then terminates on EOF.

Repeat by:
	Set up a 'paths' file with the following two lines:

	foo	%s	0
	smart-host	foo!%s	120

	Then run 'smail -AdR uunet!test'.  The attempt to find
	'smart-host' in the 'paths' file will fail.

Fix:
	Apply the following patch.  

*** getpath.c.orig	Thu Dec  1 13:58:38 1988
--- getpath.c	Thu Dec  1 13:58:17 1988
***************
*** 53,59
  	for( ;; ) {
  		pos = middle = ( hi+lo+1 )/2;
  		(void) fseek(file, pos, 0);	/* find midpoint */
! 		if(pos != 0)
  			while(((c = getc(file)) != EOF) && (c != '\n'))
  				;	/* go to beginning of next line */
  		if(c == EOF) {

--- 53,59 -----
  	for( ;; ) {
  		pos = middle = ( hi+lo+1 )/2;
  		(void) fseek(file, pos, 0);	/* find midpoint */
! 		if(pos != 0){
  			while(((c = getc(file)) != EOF) && (c != '\n'))
  				;	/* go to beginning of next line */
  			if(c == EOF) {
***************
*** 56,63
  		if(pos != 0)
  			while(((c = getc(file)) != EOF) && (c != '\n'))
  				;	/* go to beginning of next line */
! 		if(c == EOF) {
! 			return(EX_NOHOST);
  		}
  		for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */
  			if( *s == '\0' ) {

--- 56,64 -----
  		if(pos != 0){
  			while(((c = getc(file)) != EOF) && (c != '\n'))
  				;	/* go to beginning of next line */
! 			if(c == EOF) {
! 				return(EX_NOHOST);
! 			}
  		}
  		for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */
  			if( *s == '\0' ) {
***************
*** 64,70
  				goto solved;
  			}
  			if((c = getc(file)) == EOF) {
! 				return(EX_NOHOST);
  			}
  			flag = lower(c) - lower(*s);
  		} 

--- 65,71 -----
  				goto solved;
  			}
  			if((c = getc(file)) == EOF) {
! 				break;
  			}
  			flag = lower(c) - lower(*s);
  		} 
-- 
Mike Young
Software Development Technologies, Inc., Sudbury MA       Tel: +1 508 443 5779
Internet: mjy@sdti.sdti.com                 UUCP: {harvard,mit-eddie}!sdti!mjy