Re: Y2K

From: Byron C. Darrah <bdarr_at_sse.FU.HAC.COM_at_hypermail-project.org>
Date: Fri, 9 Oct 1998 10:57:36 -0700 (PDT)
Message-Id: <199810091757.KAA03184_at_pepperoni.pizza.hac.com>

Hi, I noticed a bug in an old variant version of hypermail so I inspected the sources of the latest beta release and it seems to be there, too. I'm a little surprised that it hasn't been caught by now.

Anyway, there's a function called replace() in strings.c that is used to do things like variable substitution and url encoding. (eg: replace occurrences of "$TO" with an email address.) Well, this function is written such that if the new text *contains* the pattern you are replacing, you get incorrect results. In fact, you get infinite recursion. For example, try to replace "%" with "%25" (for url-encoding), and you end up

with an endless sequence of "%%%%%%%%%%%%%%%%%%%%%%%...".

I noticed the new version is slightly better than my crummy old deviant version because it uses strcpymax() instead of strcpy() at one place, but I think the basic problem is still there.

Here is a possible replacement for replace().

Besides the main problem, replace() is tail-recursive which is unnecessary, and also tends to do some unnecessary recopying of a static buffer onto itself due to the recursion. So I cleaned that up a bit, too.

--Byron Darrah

/* Given a string, replaces all instances of "oldpiece" with "newpiece".
 *
 * Modified this routine to eliminate recursion and to avoid infinite
 * expansion of string when newpiece contains oldpiece.  --Byron
*/

char *replace(char *string, char *oldpiece, char *newpiece) {

   int str_index, newstr_index, oldpiece_index, end,

      new_len, old_len, cpy_len;
   char *c;
   char beforestring[MAXLINE], afterstring[MAXLINE];    static char newstring[MAXLINE];

   if ((c = (char *) strstr(string, oldpiece)) == NULL)

      return string;

   new_len        = strlen(newpiece);
   old_len        = strlen(oldpiece);
   end            = strlen(string)   - old_len;
   oldpiece_index = c - string;
        

   newstr_index = 0;
   str_index = 0;
   while(str_index <= end && c != NULL)
   {

/* Copy characters from the left of matched pattern occurence */

      cpy_len = oldpiece_index-str_index;
      strncpy(newstring+newstr_index, string+str_index, cpy_len);
      newstr_index += cpy_len;
      str_index    += cpy_len;


/* Copy replacement characters instead of matched pattern */
strcpy(newstring+newstr_index, newpiece); newstr_index += new_len; str_index += old_len;
/* Check for another pattern match */
if((c = (char *) strstr(string+str_index, oldpiece)) != NULL) oldpiece_index = c - string;

   }
   /* Copy remaining characters from the right of last matched pattern */    strcpy(newstring+newstr_index, string+str_index);

   return newstring;
} Received on Fri 09 Oct 1998 08:01:33 PM GMT

This archive was generated by hypermail 2.3.0 : Sat 13 Mar 2010 03:46:11 AM GMT GMT