[comp.bugs.4bsd] Portable C Compiler Bug

amh@uvacs.cs.Virginia.EDU (Anne M. Holler) (10/07/88)

    I have found and fixed a bug in the version of the Portable C compiler
distributed with Berkeley UNIX 4.3.  The bug causes the compiler to some-
times fail giving the error message "schain botch".
    The situation is that in the process of clearing the symbol table at
the end of a block (in the function clearst in the module pftn.c), the
compiler moves into the newly-freed symbol table entries any remaining
entries previously blocked by the removed symbols from hashing into those
positions.  However, pointers to symbol table entries are kept in a linked
list for the block level to which they belong (schain), and these pointers
are not being updated to reflect the moved entries' new locations.
    The bug fix is as follows.  When an entry in the symbol table is moved
into a freed position, its pointer in the schain is found and modified.  A
portion of code from clearst along with the changes necessary is given below.
Existing code:
			if( (r = relook(q)) != q ) {
				*r = *q;
				q->stype = TNULL;
				}
Revised code:
			if( (r = relook(q)) != q ) {
			    struct symtab *sptr, *sptrbak;
				*r = *q;
				/* Fix up mishashed entries' schain values */
				for (sptrbak=sptr=schain[q->slevel]; sptr!=NULL;
				     sptrbak=sptr,sptr=sptr->snext) {
					if (sptr==q) {
						if (sptr == sptrbak)
							schain[q->slevel] = r;
						else
							sptrbak->snext = r;
						break;
						}
					}
				q->stype = TNULL;
				}
    Please feel free to correspond with me about this matter.  Thanks.
Anne Holler

chris@mimsy.UUCP (Chris Torek) (10/08/88)

In article <2737@uvacs.cs.Virginia.EDU> amh@uvacs.cs.Virginia.EDU
(Anne M. Holler) writes:
>...3.  The bug causes the compiler to sometimes fail giving the error
>message "schain botch".

Yes.  Anne's fix should work.  The bug is already fixed in
4.3BSD-tahoe; here is the `official' fix.  Your line numbers will
differ.

***************
*** 1854,1859 ****
  	/* step 1: remove entries */
  	while( chaintop-1 > lev ){
- 		register int type;
- 
  		p = schain[--chaintop];
  		schain[chaintop] = 0;
--- 1890,1893 ----
***************
*** 1860,1864 ****
  		for( ; p; p = q ){
  			q = p->snext;
- 			type = p->stype;
  			if( p->stype == TNULL || p->slevel <= lev )
  				cerror( "schain botch" );
--- 1894,1897 ----
***************
*** 1894,1898 ****
  	p = clist;
  	while( p ){
! 		register struct symtab *r, *next;
  
  		q = p;
--- 1927,1931 ----
  	p = clist;
  	while( p ){
! 		register struct symtab *next, **t, *r;
  
  		q = p;
***************
*** 1902,1905 ****
--- 1935,1946 ----
  			if( q == p || q->stype == TNULL )break;
  			if( (r = relook(q)) != q ) {
+ 				/* move q in schain list */
+ 				t = &schain[q->slevel];
+ 				while( *t && *t != q )
+ 					t = &(*t)->snext;
+ 				if( *t )
+ 					*t = r;
+ 				else
+ 					cerror("schain botch 2");
  				*r = *q;
  				q->stype = TNULL;
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris