Package: mutt
Version: 1.5.13-3
Severity: normal

The following command line:
 mutt 'mailto:[EMAIL 
PROTECTED]&References=%3c153185.7884%40example.org%3e&[EMAIL PROTECTED]'
does not take into account the given "From" header. More generally,
any header (or body) that is put after the "References" header is
ignored. For example,
 mutt 'mailto:[EMAIL 
PROTECTED]@example.net'&References=%3c153185.7884%40example.org%3e&Subject=subj&[EMAIL
 PROTECTED]
will take into account the "From" header, but neither the "Subject",
nor the "Reply-To".

That is because in this situation mutt uses the non-reentrant strtok
in a nested way. More precisely:
 - "mailto:"; URL parsing happens in function url_parse_mailto (file
   url.c).
 - that function calls strtok once with 'headers' as first argument
   and then with 'NULL' as first argument, to continue advancing in
   the same string.
 - but if the header being parsed is "References" (that is 'tag' is
   that string), then mutt_parse_rfc822_line (which finished the for
   loop) (file parse.c) will call mutt_parse_references, which will in
   turn call strtok() with a non-NULL first argument. (And then with
   NULL argument until it returns NULL.)
 - when the for loop in url_parse_mailto proceeds, the
   strtok(NULL,...) call proceeds on the string passed by
   mutt_parse_references, but it is already at its end, and returns
   NULL, terminating that function.


The attached patch changes all calls to strtok to the reentrant
strtok_r, fixing that problem.


-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.18-3-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_LU.UTF-8, LC_CTYPE=fr_LU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages mutt depends on:
ii  exim4                     4.67-1         metapackage to ease exim MTA (v4) 
ii  exim4-daemon-heavy [mail- 4.67-1         exim MTA (v4) daemon with extended
ii  libc6                     2.5-4          GNU C Library: Shared libraries
ii  libdb4.4                  4.4.20-8       Berkeley v4.4 Database Libraries [
ii  libgnutls13               1.6.2-1        the GNU TLS library - runtime libr
ii  libidn11                  0.6.5-1        GNU libidn library, implementation
ii  libncursesw5              5.5-5          Shared libraries for terminal hand
ii  libsasl2-2                2.1.22.dfsg1-9 Authentication abstraction library

Versions of packages mutt recommends:
ii  locales                       2.5-4      GNU C Library: National Language (
ii  mime-support                  3.39-1     MIME files 'mime.types' & 'mailcap

-- no debconf information
diff --recursive -u mutt-1.5.13/attach.c mutt-1.5.13.strtok_safe/attach.c
--- mutt-1.5.13/attach.c        2006-02-21 09:04:59.000000000 +0100
+++ mutt-1.5.13.strtok_safe/attach.c    2007-05-26 20:09:42.474452218 +0200
@@ -301,13 +301,15 @@
 
   if ((p = getenv ("MM_NOASK")) != NULL && *p)
   {
+    char *strtok_saveptr = NULL;
+
     if (mutt_strcmp (p, "1") == 0)
       return (1);
 
     strfcpy (tmp, p, sizeof (tmp));
     p = tmp;
 
-    while ((p = strtok (p, ",")) != NULL)
+    while ((p = strtok_r (p, ",", &strtok_saveptr)) != NULL)
     {
       if ((q = strrchr (p, '/')) != NULL)
       {
diff --recursive -u mutt-1.5.13/crypt-gpgme.c 
mutt-1.5.13.strtok_safe/crypt-gpgme.c
--- mutt-1.5.13/crypt-gpgme.c   2005-10-31 11:02:08.000000000 +0100
+++ mutt-1.5.13.strtok_safe/crypt-gpgme.c       2007-05-26 20:03:05.818425128 
+0200
@@ -3478,8 +3478,8 @@
   if ((scratch = safe_strdup (str)) == NULL)
     return hints;
 
-  for (t = strtok (scratch, " ,.:\"()<>\n"); t;
-       t = strtok (NULL, " ,.:\"()<>\n"))
+  for (t = strtok_r (scratch, " ,.:\"()<>\n", &strtok_saveptr); t;
+       t = strtok_r (NULL, " ,.:\"()<>\n", &strtok_saveptr))
     {
       if (strlen (t) > 3)
         hints = mutt_add_list (hints, t);
diff --recursive -u mutt-1.5.13/edit.c mutt-1.5.13.strtok_safe/edit.c
--- mutt-1.5.13/edit.c  2005-10-31 11:02:08.000000000 +0100
+++ mutt-1.5.13.strtok_safe/edit.c      2007-05-26 20:10:19.553071901 +0200
@@ -150,8 +150,9 @@
 {
   int offset, bytes, n;
   char tmp[LONG_STRING];
+  char *strtok_saveptr = NULL;
 
-  while ((msg = strtok (msg, " ,")) != NULL)
+  while ((msg = strtok_r (msg, " ,", &strtok_saveptr)) != NULL)
   {
     n = atoi (msg);
     if (n > 0 && n <= Context->msgcount)
diff --recursive -u mutt-1.5.13/getdomain.c mutt-1.5.13.strtok_safe/getdomain.c
--- mutt-1.5.13/getdomain.c     2005-02-03 19:47:52.000000000 +0100
+++ mutt-1.5.13.strtok_safe/getdomain.c 2007-05-26 19:56:37.142921822 +0200
@@ -46,9 +46,11 @@
     while (ISSPACE (*p)) p++;
     if (mutt_strncmp ("domain", p, 6) == 0 || mutt_strncmp ("search", p, 6) == 
0)
     {
+      char *strtok_saveptr = NULL;
+
       p += 6;
       
-      for (q = strtok (p, " \t\n"); q; q = strtok (NULL, " \t\n"))
+      for (q = strtok_r (p, " \t\n", &strtok_saveptr); q; q = strtok_r (NULL, 
" \t\n", &strtok_saveptr))
        if (strcmp (q, "."))
          break;
 
diff --recursive -u mutt-1.5.13/mh.c mutt-1.5.13.strtok_safe/mh.c
--- mutt-1.5.13/mh.c    2006-08-11 11:07:12.000000000 +0200
+++ mutt-1.5.13.strtok_safe/mh.c        2007-05-26 20:00:02.217351584 +0200
@@ -159,7 +159,9 @@
 
   while ((buff = mutt_read_line (buff, &sz, fp, &line)))
   {
-    if (!(t = strtok (buff, " \t:")))
+    char *strtok_saveptr = NULL;
+
+    if (!(t = strtok_r (buff, " \t:", &strtok_saveptr)))
       continue;
 
     if (!mutt_strcmp (t, MhUnseen))
@@ -171,7 +173,7 @@
     else                       /* unknown sequence */
       continue;
 
-    while ((t = strtok (NULL, " \t:")))
+    while ((t = strtok_r (NULL, " \t:", &strtok_saveptr)))
     {
       mh_read_token (t, &first, &last);
       for (; first <= last; first++)
diff --recursive -u mutt-1.5.13/parse.c mutt-1.5.13.strtok_safe/parse.c
--- mutt-1.5.13/parse.c 2006-04-28 21:48:32.000000000 +0200
+++ mutt-1.5.13.strtok_safe/parse.c     2007-05-26 20:07:12.007852591 +0200
@@ -94,8 +94,9 @@
   LIST *t, *lst = NULL;
   int m, n = 0;
   char *o = NULL, *new, *at;
+  char *strtok_saveptr = NULL;
 
-  while ((s = strtok (s, " \t;")) != NULL)
+  while ((s = strtok_r (s, " \t;", &strtok_saveptr)) != NULL)
   {
     /*
      * some mail clients add other garbage besides message-ids, so do a quick
@@ -781,6 +782,7 @@
   const char *ptz;
   char tzstr[SHORT_STRING];
   char scratch[SHORT_STRING];
+  char *strtok_saveptr = NULL;
 
   /* Don't modify our argument. Fixed-size buffer is ok here since
    * the date format imposes a natural limit. 
@@ -797,7 +799,7 @@
 
   memset (&tm, 0, sizeof (tm));
 
-  while ((t = strtok (t, " \t")) != NULL)
+  while ((t = strtok_r (t, " \t", &strtok_saveptr)) != NULL)
   {
     switch (count)
     {
@@ -877,7 +879,7 @@
          /* ad hoc support for the European MET (now officially CET) TZ */
          if (ascii_strcasecmp (t, "MET") == 0)
          {
-           if ((t = strtok (NULL, " \t")) != NULL)
+           if ((t = strtok_r (NULL, " \t", &strtok_saveptr)) != NULL)
            {
              if (!ascii_strcasecmp (t, "DST"))
                zhours++;
@@ -1446,6 +1448,7 @@
 ADDRESS *mutt_parse_adrlist (ADDRESS *p, const char *s)
 {
   const char *q;
+  char *strtok_saveptr = NULL;
 
   /* check for a simple whitespace separated list of addresses */
   if ((q = strpbrk (s, "\"<>():;,\\")) == NULL)
@@ -1455,7 +1458,7 @@
 
     strfcpy (tmp, s, sizeof (tmp));
     r = tmp;
-    while ((r = strtok (r, " \t")) != NULL)
+    while ((r = strtok_r (r, " \t", &strtok_saveptr)) != NULL)
     {
       p = rfc822_parse_adrlist (p, r);
       r = NULL;
diff --recursive -u mutt-1.5.13/pgpkey.c mutt-1.5.13.strtok_safe/pgpkey.c
--- mutt-1.5.13/pgpkey.c        2005-09-18 10:22:22.000000000 +0200
+++ mutt-1.5.13.strtok_safe/pgpkey.c    2007-05-26 19:57:17.781780847 +0200
@@ -788,12 +788,13 @@
 {
   char *scratch;
   char *t;
+  char *strtok_saveptr = NULL;
 
   if ((scratch = safe_strdup (str)) == NULL)
     return hints;
 
-  for (t = strtok (scratch, " ,.:\"()<>\n"); t;
-                       t = strtok (NULL, " ,.:\"()<>\n"))
+  for (t = strtok_r (scratch, " ,.:\"()<>\n" , &strtok_saveptr); t;
+                       t = strtok_r (NULL, " ,.:\"()<>\n" , &strtok_saveptr))
   {
     if (strlen (t) > 3)
       hints = mutt_add_list (hints, t);
diff --recursive -u mutt-1.5.13/postpone.c mutt-1.5.13.strtok_safe/postpone.c
--- mutt-1.5.13/postpone.c      2006-04-20 18:46:35.000000000 +0200
+++ mutt-1.5.13.strtok_safe/postpone.c  2007-05-26 20:03:55.965957091 +0200
@@ -376,13 +376,15 @@
     else if (mutt_strncmp ("X-Mutt-Mix:", tmp->data, 11) == 0)
     {
       char *t;
+      char *strtok_saveptr = NULL;
+
       mutt_free_list (&hdr->chain);
       
-      t = strtok (tmp->data + 11, " \t\n");
+      t = strtok_r (tmp->data + 11, " \t\n", &strtok_saveptr);
       while (t)
       {
        hdr->chain = mutt_add_list (hdr->chain, t);
-       t = strtok (NULL, " \t\n");
+       t = strtok_r (NULL, " \t\n", &strtok_saveptr);
       }
       
       next = tmp->next;
diff --recursive -u mutt-1.5.13/query.c mutt-1.5.13.strtok_safe/query.c
--- mutt-1.5.13/query.c 2006-03-03 10:53:31.000000000 +0100
+++ mutt-1.5.13.strtok_safe/query.c     2007-05-26 19:59:18.762293301 +0200
@@ -103,7 +103,9 @@
     *p = '\0';
   while ((buf = mutt_read_line (buf, &buflen, fp, &dummy)) != NULL)
   {
-    if ((p = strtok(buf, "\t\n")))
+    char *strtok_saveptr = NULL;
+
+    if ((p = strtok_r(buf, "\t\n", &strtok_saveptr)))
     {
       if (first == NULL)
       {
@@ -123,14 +125,14 @@
        SecondColumn = l;
        
       cur->addr = rfc822_parse_adrlist (cur->addr, p);
-      p = strtok(NULL, "\t\n");
+      p = strtok_r(NULL, "\t\n", &strtok_saveptr);
       if (p)
       {
        l = mutt_strwidth (p);
        if (l > FirstColumn)
          FirstColumn = l;
        cur->name = safe_strdup (p);
-       p = strtok(NULL, "\t\n");
+       p = strtok_r(NULL, "\t\n", &strtok_saveptr);
        if (p)
        {
          cur->other = safe_strdup (p);
diff --recursive -u mutt-1.5.13/remailer.c mutt-1.5.13.strtok_safe/remailer.c
--- mutt-1.5.13/remailer.c      2006-05-18 20:44:29.000000000 +0200
+++ mutt-1.5.13.strtok_safe/remailer.c  2007-05-26 20:05:13.011430894 +0200
@@ -166,27 +166,28 @@
   
   while (fgets (line, sizeof (line), fp))
   {
+    char *strtok_saveptr = NULL;
     p = mix_new_remailer ();
     
-    if (!(t = strtok (line, " \t\n")))
+    if (!(t = strtok_r (line, " \t\n", &strtok_saveptr)))
       goto problem;
     
     p->shortname = safe_strdup (t);
     
-    if (!(t = strtok (NULL, " \t\n")))
+    if (!(t = strtok_r (NULL, " \t\n", &strtok_saveptr)))
       goto problem;
 
     p->addr = safe_strdup (t);
     
-    if (!(t = strtok (NULL, " \t\n")))
+    if (!(t = strtok_r (NULL, " \t\n", &strtok_saveptr)))
       goto problem;
 
-    if (!(t = strtok (NULL, " \t\n")))
+    if (!(t = strtok_r (NULL, " \t\n", &strtok_saveptr)))
       goto problem;
 
     p->ver = safe_strdup (t);
     
-    if (!(t = strtok (NULL, " \t\n")))
+    if (!(t = strtok_r (NULL, " \t\n", &strtok_saveptr)))
       goto problem;
 
     p->caps = mix_get_caps (t);
diff --recursive -u mutt-1.5.13/sendlib.c mutt-1.5.13.strtok_safe/sendlib.c
--- mutt-1.5.13/sendlib.c       2006-07-18 20:16:24.000000000 +0200
+++ mutt-1.5.13.strtok_safe/sendlib.c   2007-05-26 20:02:04.897994046 +0200
@@ -954,6 +954,8 @@
 
     if ((f = fopen (buf, "r")) != NULL)
     {
+      char *strtok_saveptr = NULL;
+
       while (fgets (buf, sizeof (buf) - 1, f) != NULL)
       {
        /* weed out any comments */
@@ -971,7 +973,7 @@
        SKIPWS (p);
 
        /* cycle through the file extensions */
-       while ((p = strtok (p, " \t\n")))
+       while ((p = strtok_r (p, " \t\n", &strtok_saveptr)))
        {
          sze = mutt_strlen (p);
          if ((sze > cur_sze) && (szf >= sze) &&
@@ -1925,10 +1927,11 @@
   char **args = NULL;
   size_t argslen = 0, argsmax = 0;
   int i;
+  char *strtok_saveptr = NULL;
 
   ps = s;
   i = 0;
-  while ((ps = strtok (ps, " ")))
+  while ((ps = strtok_r (ps, " ", &strtok_saveptr)))
   {
     if (argslen == argsmax)
       safe_realloc (&args, sizeof (char *) * (argsmax += 5));
diff --recursive -u mutt-1.5.13/url.c mutt-1.5.13.strtok_safe/url.c
--- mutt-1.5.13/url.c   2005-09-18 10:22:22.000000000 +0200
+++ mutt-1.5.13.strtok_safe/url.c       2007-05-26 19:58:17.029950161 +0200
@@ -213,6 +213,7 @@
   char *headers;
   char *tag, *value;
   char scratch[HUGE_STRING];
+  char *strtok_saveptr = NULL;
 
   int taglen;
 
@@ -230,9 +231,9 @@
   url_pct_decode (tmp);
   e->to = rfc822_parse_adrlist (e->to, tmp);
 
-  tag = headers ? strtok (headers, "&") : NULL;
+  tag = headers ? strtok_r (headers, "&", &strtok_saveptr) : NULL;
   
-  for (; tag; tag = strtok (NULL, "&"))
+  for (; tag; tag = strtok_r (NULL, "&", &strtok_saveptr))
   {
     if ((value = strchr (tag, '=')))
       *value++ = '\0';

Reply via email to