jnford@jay.weeg.uiowa.edu (Jay Ford) (11/14/89)
Subject: address parsing bug in Berkeley mail (/usr/ucb/Mail)
Index: UCB Mail Version 5.2 (6/21/85)
Description:
There is a parsing bug in the routine skin in aux.c which causes it
to mangle mail addresses containing quoted or commented strings
following an address in angle brackets.
Problem found on:
IBM RT running IBM/4.3 rel 2 (Dec 1988);
NeXT running MACH 1.0;
VAX running 4.3BSD;
Sun running SunOS Release 4.0
Rebeat-by:
Get mail from someone with an address like
<jnford@jay.weeg.uiowa.edu> "commas, in, quotes"
or
<jnford@jay.weeg.uiowa.edu> (commas, in, a, comment)
This can be done by saving a piece of mail, hacking the from line,
and using mail -f on the file.
Fix:
Apply the following patches in /usr/src/ucb/Mail.
Jay Ford, Weeg Computing Center, University of Iowa, Iowa City, IA 52242
jnford@jay.weeg.uiowa.edu or jnfordpb@uiamvs.bitnet, 319-335-5555
*** version.c.orig Fri Dec 9 13:56:05 1988
--- version.c Mon Nov 13 17:55:52 1989
***************
*** 13,19 ****
*/
#ifndef lint
! static char *sccsid = "@(#)version.c 5.2 (Berkeley) 6/21/85";
#endif not lint
/*
--- 13,19 ----
*/
#ifndef lint
! static char *sccsid = "@(#)version.c 5.2.1 (Berkeley) 11/13/89";
#endif not lint
/*
***************
*** 20,24 ****
* Just keep track of the date/sid of this version of Mail.
* Load this file first to get a "total" Mail version.
*/
! static char *SccsID = "@(#)UCB Mail Version 5.2 (6/21/85)";
! char *version = "5.2 6/21/85";
--- 20,24 ----
* Just keep track of the date/sid of this version of Mail.
* Load this file first to get a "total" Mail version.
*/
! static char *SccsID = "@(#)UCB Mail Version 5.2.1 (11/13/89)";
! char *version = "5.2.1 11/13/89";
*** def.h.orig Fri Dec 9 13:55:23 1988
--- def.h Mon Nov 13 17:32:54 1989
***************
*** 288,293 ****
--- 288,294 ----
char *arpafix();
char *calloc();
char *copy();
+ char *do_quoted_string();
char *copyin();
char *detract();
char *expand();
***************
*** 311,316 ****
--- 312,318 ----
char *salloc();
char *savestr();
char *skin();
+ char *skip_comment();
char *snarf();
char *strcat();
char *strcpy();
*** aux.c.orig Fri Dec 9 13:55:07 1988
--- aux.c Mon Nov 13 17:31:09 1989
***************
*** 547,557 ****
char *name;
{
register int c;
! register char *cp, *cp2;
char *bufend;
int gotlt, lastsp;
char nbuf[BUFSIZ];
- int nesting;
if (name == NOSTR)
return(NOSTR);
--- 547,558 ----
char *name;
{
register int c;
! register char *cp;
! char *cp2;
! int c2;
char *bufend;
int gotlt, lastsp;
char nbuf[BUFSIZ];
if (name == NOSTR)
return(NOSTR);
***************
*** 564,617 ****
for (cp = name, cp2 = bufend; c = *cp++; ) {
switch (c) {
case '(':
! /*
! * Start of a "comment".
! * Ignore it.
! */
! nesting = 1;
! while ((c = *cp) != 0) {
! cp++;
! switch (c) {
! case '\\':
! if (*cp == 0)
! goto outcm;
! cp++;
! break;
! case '(':
! nesting++;
! break;
!
! case ')':
! --nesting;
! break;
! }
!
! if (nesting <= 0)
! break;
! }
! outcm:
lastsp = 0;
break;
case '"':
! /*
! * Start of a "quoted-string".
! * Copy it in its entirety.
! */
! while ((c = *cp) != 0) {
! cp++;
! switch (c) {
! case '\\':
! if ((c = *cp) == 0)
! goto outqs;
! cp++;
! break;
! case '"':
! goto outqs;
! }
! *cp2++ = c;
! }
! outqs:
lastsp = 0;
break;
--- 565,576 ----
for (cp = name, cp2 = bufend; c = *cp++; ) {
switch (c) {
case '(':
! cp = skip_comment ( cp );
lastsp = 0;
break;
case '"':
! cp = do_quoted_string ( cp, &cp2 );
lastsp = 0;
break;
***************
*** 634,641 ****
case '>':
if (gotlt) {
gotlt = 0;
! while (*cp != ',' && *cp != 0)
! cp++;
if (*cp == 0 )
goto done;
*cp2++ = ',';
--- 593,613 ----
case '>':
if (gotlt) {
gotlt = 0;
! while (*cp != ',' && *cp != 0) {
! c2 = *cp++;
! switch ( c2 ) {
! case '\\':
! if (*cp != '\0') cp++;
! break;
! case '(':
! cp = skip_comment ( cp );
! break;
!
! case '"':
! cp = do_quoted_string ( cp, NULL );
! break;
! }
! }
if (*cp == 0 )
goto done;
*cp2++ = ',';
***************
*** 659,664 ****
--- 631,703 ----
*cp2 = 0;
return(savestr(nbuf));
+ }
+
+ /*
+ * Start of a "comment".
+ * Ignore it.
+ */
+ char *
+ skip_comment(cp)
+ register char *cp;
+ {
+ register int c;
+ int nesting;
+
+ nesting = 1;
+ while ((c = *cp) != 0) {
+ cp++;
+ switch (c) {
+ case '\\':
+ if (*cp == 0)
+ return ( cp );
+ cp++;
+ break;
+ case '(':
+ nesting++;
+ break;
+ case ')':
+ --nesting;
+ break;
+ }
+ if (nesting <= 0)
+ break;
+ }
+ return ( cp );
+ }
+
+ /*
+ * Start of a "quoted-string".
+ * If a target string is given, copy it & advance the pointer;
+ * otherwise, just advance the source pointer.
+ */
+ char *
+ do_quoted_string(cp, cp2p)
+ register char *cp;
+ char **cp2p;
+ {
+ register int c;
+
+ if ( cp2p != NULL ) printf ( "do_quoted_string: cp2p is not null\n" );
+ else printf ( "do_quoted_string: cp2p is null\n" );
+
+ while ((c = *cp) != 0) {
+ cp++;
+ switch (c) {
+ case '\\':
+ if ((c = *cp) == 0)
+ return ( cp );
+ cp++;
+ break;
+ case '"':
+ return ( cp );
+ }
+ if ( cp2p != NULL ) {
+ **cp2p = c;
+ (*cp2p)++;
+ }
+ }
+ return ( cp );
}
/*