Path: utzoo!utgpu!utstat!jarvis.csri.toronto.edu!mailrus!uunet!ns-mx!jay.weeg.uiowa.edu!jnford From: jnford@jay.weeg.uiowa.edu (Jay Ford) Newsgroups: comp.bugs.4bsd Subject: parsing bug in Berkeley mail Keywords: mail, parsing Message-ID: <189@ns-mx.uiowa.edu> Date: 14 Nov 89 00:34:03 GMT Sender: news@ns-mx.uiowa.edu Reply-To: jnford@jay.weeg.uiowa.edu (Jay Ford) Organization: U Uiowa, Weeg Computing Center Lines: 294 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 "commas, in, quotes" or (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 ); } /*