[net.bugs.4bsd] Cron chokes on long lines

wtm@bunker.UUCP (Bill McGarry) (10/22/86)

Subject:
	cron core dumps on lines 100 or more characters long
Index:
	/usr/src/cmd/cron.c 4.1BSD

Description: 
	When cron reads in the crontab table, it starts off with a 512
byte buffer.  After each line is read and converted to cron's internal
format, a check is made to ensure that there are at least 100 bytes left
in the buffer for the next line to be read.  The problem occurs when the
buffer has more than 100 bytes but the next line is too big to fit into
the remainder of the buffer.

Repeat-By:  
	Although the problem can occur (and did occur here) if only 
one line in crontab is over 100 bytes long, it is dependent upon the 
exact layout of the crontab and consequently it is not that easy 
to duplicate the problem.

Fix:
	Rather than just enlarging the buffer and then changing the
line limit from 100 to 200 or more bytes, I changed the code to check
for a buffer full condition as each byte is inserted into the buffer
during the "init" routine. (Diff suitable for "patch" is at the
end of this article.)


				Bill McGarry
				Bunker Ramo, Trumbull, CT

	PATH:	{decvax, philabs, ittatc, fortune}!bunker!wtm



Patch:

*** cron.c	Wed Oct 22 10:31:57 1986
--- cron.new.c	Wed Oct 22 09:57:02 1986
***************
*** 144,149
  	register char *cp;
  	register char *ocp;
  	register int n;
  
  	freopen(crontab, "r", stdin);
  	if (list) {

--- 144,150 -----
  	register char *cp;
  	register char *ocp;
  	register int n;
+ 	char	*ins_chr();
  
  	freopen(crontab, "r", stdin);
  	if (list) {
***************
*** 155,168
  	cp = list;
  
  loop:
- 	if(cp > list+listsize-100) {
- 		char *olist;
- 		listsize += LISTS;
- 		olist = list;
- 		free(list);
- 		list = realloc(list, listsize);
- 		cp = list + (cp - olist);
- 	}
  	ocp = cp;
  	for(i=0;; i++) {
  		do

--- 156,161 -----
  	cp = list;
  
  loop:
  	ocp = cp;
  	for(i=0;; i++) {
  		do
***************
*** 174,180
  		if(i == 5)
  			break;
  		if(c == '*') {
! 			*cp++ = ANY;
  			continue;
  		}
  		if ((n = number(c)) < 0)

--- 167,173 -----
  		if(i == 5)
  			break;
  		if(c == '*') {
! 			cp = ins_chr(cp, ANY);
  			continue;
  		}
  		if ((n = number(c)) < 0)
***************
*** 186,193
  			goto mrange;
  		if(c != '\t' && c != ' ')
  			goto ignore;
! 		*cp++ = EXACT;
! 		*cp++ = n;
  		continue;
  
  	mlist:

--- 179,186 -----
  			goto mrange;
  		if(c != '\t' && c != ' ')
  			goto ignore;
! 		cp = ins_chr(cp, EXACT);
! 		cp = ins_chr(cp, n);
  		continue;
  
  	mlist:
***************
*** 191,198
  		continue;
  
  	mlist:
! 		*cp++ = LIST;
! 		*cp++ = n;
  		do {
  			if ((n = number(getchar())) < 0)
  				goto ignore;

--- 184,191 -----
  		continue;
  
  	mlist:
! 		cp = ins_chr(cp, LIST);
! 		cp = ins_chr(cp, n);
  		do {
  			if ((n = number(getchar())) < 0)
  				goto ignore;
***************
*** 196,202
  		do {
  			if ((n = number(getchar())) < 0)
  				goto ignore;
! 			*cp++ = n;
  			c = getchar();
  		} while (c==',');
  		if(c != '\t' && c != ' ')

--- 189,195 -----
  		do {
  			if ((n = number(getchar())) < 0)
  				goto ignore;
! 			cp = ins_chr(cp, n);
  			c = getchar();
  		} while (c==',');
  		if(c != '\t' && c != ' ')
***************
*** 201,207
  		} while (c==',');
  		if(c != '\t' && c != ' ')
  			goto ignore;
! 		*cp++ = LIST;
  		continue;
  
  	mrange:

--- 194,200 -----
  		} while (c==',');
  		if(c != '\t' && c != ' ')
  			goto ignore;
! 		cp = ins_chr(cp, LIST);
  		continue;
  
  	mrange:
***************
*** 205,212
  		continue;
  
  	mrange:
! 		*cp++ = RANGE;
! 		*cp++ = n;
  		if ((n = number(getchar())) < 0)
  			goto ignore;
  		c = getchar();

--- 198,205 -----
  		continue;
  
  	mrange:
! 		cp = ins_chr(cp, RANGE);
! 		cp = ins_chr(cp, n);
  		if ((n = number(getchar())) < 0)
  			goto ignore;
  		c = getchar();
***************
*** 212,218
  		c = getchar();
  		if(c != '\t' && c != ' ')
  			goto ignore;
! 		*cp++ = n;
  	}
  	while(c != '\n') {
  		if(c == EOF)

--- 205,211 -----
  		c = getchar();
  		if(c != '\t' && c != ' ')
  			goto ignore;
! 		cp = ins_chr(cp, n);
  	}
  	while(c != '\n') {
  		if(c == EOF)
***************
*** 219,225
  			goto ignore;
  		if(c == '%')
  			c = '\n';
! 		*cp++ = c;
  		c = getchar();
  	}
  	*cp++ = '\n';

--- 212,218 -----
  			goto ignore;
  		if(c == '%')
  			c = '\n';
! 		cp = ins_chr(cp, c);
  		c = getchar();
  	}
  	cp = ins_chr(cp, '\n');
***************
*** 222,229
  		*cp++ = c;
  		c = getchar();
  	}
! 	*cp++ = '\n';
! 	*cp++ = 0;
  	goto loop;
  
  ignore:

--- 215,222 -----
  		cp = ins_chr(cp, c);
  		c = getchar();
  	}
! 	cp = ins_chr(cp, '\n');
! 	cp = ins_chr(cp, NULL);
  	goto loop;
  
  ignore:
***************
*** 230,237
  	cp = ocp;
  	while(c != '\n') {
  		if(c == EOF) {
! 			*cp++ = EOS;
! 			*cp++ = EOS;
  			fclose(stdin);
  			return;
  		}

--- 223,230 -----
  	cp = ocp;
  	while(c != '\n') {
  		if(c == EOF) {
! 			cp = ins_chr(cp, EOS);
! 			cp = ins_chr(cp, EOS);
  			fclose(stdin);
  			return;
  		}
***************
*** 254,256
  		return(-1);
  	return(n);
  }

--- 247,275 -----
  		return(-1);
  	return(n);
  }
+ 
+ 
+ /*
+  * ins_chr: This function will insert the character 'c' into the
+  * buffer at 'ptr'.  Before doing so, it will ensure that there is 
+  * enough room for the character.  If there is not, a realloc will
+  * be done to expand the buffer.  The updated buffer pointer is
+  * returned to the caller.
+  */
+ char *ins_chr(ptr, c)
+ register char *ptr, c;
+ {
+ register char	*olist;
+ 
+ if (ptr >= list + listsize - 1) {
+ 	listsize += LISTS;
+ 	olist = list;
+ 	free(list);
+ 	list = realloc(list, listsize);
+ 	ptr = list + (ptr - olist);
+ 	}
+ *ptr++ = c;
+ return(ptr);
+ }
+ 
+ 
--
End of patch