[comp.bugs.4bsd] macro bug of sendmail 5.65

demizu@nff.ncl.omron.co.jp (DEMIZU Noritoshi) (05/04/91)

Macros used in sendmail.cf are sometimes scratched.

For example, when I wrote following line in sendmail.cf,
  H?P?Return-Path: <$g>
Some of the mails contains following line.
  Return-Path: <group:*:123:>

The reason is that the function define() only copies the POINTER
to the string to memorize macro value, while the POINTER points
non-permanent storage.  I mean,
    foo()
    {
        char buf[100];
        strcpy(buf, "string");
        define('h', buf, CurEnv);
    }
    define(char n, char* v, ENVELOPE* e)
    {
        e->e_macro[n&0177] = v;
    }

Basic idea in this patch is:
  (1) prepare new storage and copy the string to memorize macro value.
	(In macro.c)
  (2) free old storage when redefining macro.
	(In macro.c)
  (3) stop using function newstr() in the argument of define().
	This will save memory a bit.
	(In other sources)

Excuse my English.

 --- DEMIZU Noritoshi    OMRON Corporation

=====================================================================

*** macro.c.ORG	Wed Jun  6 10:27:44 1990
--- macro.c	Sat May  4 13:51:37 1991
***************
*** 212,218 ****
  		xputs(v);
  		printf(")\n");
  	}
! 	e->e_macro[n & 0177] = v;
  }
  /*
  **  MACVALUE -- return uninterpreted value of a macro.
--- 212,221 ----
  		xputs(v);
  		printf(")\n");
  	}
! 	if (e->e_macro[n & 0177] != NULL) {
! 		free(e->e_macro[n & 0177]);
! 	}
! 	e->e_macro[n & 0177] = v ? newstr(v) : NULL;
  }
  /*
  **  MACVALUE -- return uninterpreted value of a macro.
*** collect.c.ORG	Wed Jun  6 10:27:43 1990
--- collect.c	Sat May  4 12:34:19 1991
***************
*** 403,418 ****
  
  	if (*p != NULL)
  	{
! 		char *q;
  		extern char *arpadate();
  
  		/* we have found a date */
- 		q = xalloc(25);
  		(void) strncpy(q, p, 25);
  		q[24] = '\0';
  		define('d', q, CurEnv);
! 		q = arpadate(q);
! 		define('a', newstr(q), CurEnv);
  	}
  }
  
--- 403,416 ----
  
  	if (*p != NULL)
  	{
! 		char q[25];
  		extern char *arpadate();
  
  		/* we have found a date */
  		(void) strncpy(q, p, 25);
  		q[24] = '\0';
  		define('d', q, CurEnv);
! 		define('a', arpadate(q), CurEnv);
  	}
  }
  
*** envelope.c.ORG	Wed Jun  6 10:27:44 1990
--- envelope.c	Sat May  4 12:39:14 1991
***************
*** 328,334 ****
  	*index(dbuf, '\n') = '\0';
  	if (macvalue('d', CurEnv) == NULL)
  		define('d', dbuf, CurEnv);
! 	p = newstr(arpadate(dbuf));
  	if (macvalue('a', CurEnv) == NULL)
  		define('a', p, CurEnv);
  	define('b', p, CurEnv);
--- 328,334 ----
  	*index(dbuf, '\n') = '\0';
  	if (macvalue('d', CurEnv) == NULL)
  		define('d', dbuf, CurEnv);
! 	p = arpadate(dbuf);
  	if (macvalue('a', CurEnv) == NULL)
  		define('a', p, CurEnv);
  	define('b', p, CurEnv);
***************
*** 560,566 ****
  	rewrite(pvp, 1);
  	rewrite(pvp, 4);
  	cataddr(pvp, buf, sizeof buf);
! 	define('f', newstr(buf), CurEnv);
  
  	/* save the domain spec if this mailer wants it */
  	if (CurEnv->e_from.q_mailer != NULL &&
--- 560,566 ----
  	rewrite(pvp, 1);
  	rewrite(pvp, 4);
  	cataddr(pvp, buf, sizeof buf);
! 	define('f', buf, CurEnv);
  
  	/* save the domain spec if this mailer wants it */
  	if (CurEnv->e_from.q_mailer != NULL &&
*** headers.c.ORG	Wed Jun  6 10:27:44 1990
--- headers.c	Sat May  4 12:42:17 1991
***************
*** 380,386 ****
  	{
  		define('a', p, e);
  		/* we don't have a good way to do canonical conversion ....
! 		define('d', newstr(arpatounix(p)), e);
  		.... so we will ignore the problem for the time being */
  	}
  
--- 380,386 ----
  	{
  		define('a', p, e);
  		/* we don't have a good way to do canonical conversion ....
! 		define('d', arpatounix(p), e);
  		.... so we will ignore the problem for the time being */
  	}
  
*** main.c.ORG	Sat Jul 21 06:19:20 1990
--- main.c	Sat May  4 12:47:05 1991
***************
*** 257,265 ****
  		{
  			if (tTd(0, 4))
  				printf("canonical name: %s\n", jbuf);
! 			p = newstr(jbuf);
! 			define('w', p, CurEnv);
! 			setclass('w', p);
  		}
  		while (av != NULL && *av != NULL)
  		{
--- 257,264 ----
  		{
  			if (tTd(0, 4))
  				printf("canonical name: %s\n", jbuf);
! 			define('w', jbuf, CurEnv);
! 			setclass('w', jbuf);
  		}
  		while (av != NULL && *av != NULL)
  		{
***************
*** 842,848 ****
  	{
  		buf[0] = m->metaval;
  		buf[1] = '\0';
! 		define(m->metaname, newstr(buf), CurEnv);
  	}
  	buf[0] = MATCHREPL;
  	buf[2] = '\0';
--- 841,847 ----
  	{
  		buf[0] = m->metaval;
  		buf[1] = '\0';
! 		define(m->metaname, buf, CurEnv);
  	}
  	buf[0] = MATCHREPL;
  	buf[2] = '\0';
***************
*** 849,855 ****
  	for (c = '0'; c <= '9'; c++)
  	{
  		buf[1] = c;
! 		define(c, newstr(buf), CurEnv);
  	}
  }
  /*
--- 848,854 ----
  	for (c = '0'; c <= '9'; c++)
  	{
  		buf[1] = c;
! 		define(c, buf, CurEnv);
  	}
  }
  /*
*** readcf.c.ORG	Wed Jun  6 10:27:45 1990
--- readcf.c	Sat May  4 12:48:05 1991
***************
*** 167,173 ****
  			break;
  
  		  case 'D':		/* macro definition */
! 			define(buf[1], newstr(munchstring(&buf[2])), CurEnv);
  			break;
  
  		  case 'H':		/* required header line */
--- 167,173 ----
  			break;
  
  		  case 'D':		/* macro definition */
! 			define(buf[1], munchstring(&buf[2]), CurEnv);
  			break;
  
  		  case 'H':		/* required header line */
***************
*** 804,810 ****
  		break;
  
  	  case 'M':		/* define macro */
! 		define(val[0], newstr(&val[1]), CurEnv);
  		sticky = FALSE;
  		break;
  
--- 818,824 ----
  		break;
  
  	  case 'M':		/* define macro */
! 		define(val[0], &val[1], CurEnv);
  		sticky = FALSE;
  		break;
  
=====================================================================
--
;  DEMIZU, Noritoshi		OMRON Computer Systems R&D laboratory
;  demizu@nff.ncl.omron.co.jp	tel: 075-951-5111  fax: 075-956-7403

e07@nikhefh.nikhef.nl (Eric Wassenaar) (05/07/91)

In article <DEMIZU.91May4155034@freezer.nff.ncl.omron.co.jp>, demizu@nff.ncl.omron.co.jp (DEMIZU Noritoshi) writes:
> Macros used in sendmail.cf are sometimes scratched.
> The reason is that the function define() only copies the POINTER
> to the string to memorize macro value, while the POINTER points
> non-permanent storage.  I mean,
>     foo()
>     {
>         char buf[100];
>         strcpy(buf, "string");
>         define('h', buf, CurEnv);
>     }
> Basic idea in this patch is:
>   (1) prepare new storage and copy the string to memorize macro value.
>   (2) free old storage when redefining macro.
>   (3) stop using function newstr() in the argument of define().

On first sight, I could not locate offending code of the sort
mentioned above, i.e. when the value of the defined macro is
used outside the defining module and is stored in non-permanent
space. But I may have overlooked something.

However, the proposed patch breaks code such as in the following
example from parseaddr.c

remotename(name, m, senderaddress, canonical)
{
	char *oldg = macvalue('g', CurEnv);

	cataddr(pvp, lbuf, sizeof lbuf);
	define('g', lbuf, CurEnv);
	expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
	define('g', oldg, CurEnv);

With the proposed patch, the storage pointed to by oldg would
be freed by the first define() and possibly reused by newstr()
inside define() so that it would be screwed up at the moment
of the second define().

Eric Wassenaar
-- 
Organization: NIKHEF-H, National Institute for Nuclear and High-Energy Physics
Address: Kruislaan 409, P.O. Box 41882, 1009 DB Amsterdam, the Netherlands
Phone: +31 20 592 0412, Home: +31 20 6909449, Telefax: +31 20 592 5155
Internet: e07@nikhef.nl

demizu@nff.ncl.omron.co.jp (DEMIZU Noritoshi) (05/18/91)

In article <1224@nikhefh.nikhef.nl>
	e07@nikhefh.nikhef.nl (Eric Wassenaar) writes:

 |On first sight, I could not locate offending code of the sort
 |mentioned above, i.e. when the value of the defined macro is
 |used outside the defining module and is stored in non-permanent
 |space. But I may have overlooked something.

I should say that I did not read sendmail 5.65 source carefully when I
posted previsous article.  I cannot prove that such a macro is used
outside the function.

But at my site, $g often changed to scratched value before I modified
sendmail 5.65 as I posted before.  I will check it again.


 |However, the proposed patch breaks code such as in the following
 |example from parseaddr.c

This is true.  Previous patch was not correct.
--
;  DEMIZU, Noritoshi		OMRON Computer Systems R&D laboratory
;  demizu@nff.ncl.omron.co.jp	tel: 075-951-5111  fax: 075-956-7403