COMMAND
mutt
SYSTEMS AFFECTED
mutt up to 0.95.3 (including that one)
PROBLEM
Hamish Moffatt found following. On his hamm system, when viewing
text/html messages, mutt writes the text to /tmp/mutt.html then
calls lynx on that file. So, if you make a symlink like
/tmp/mutt.html -> /home/hamish/blah
then viewing an HTML message, the file "blah" (which previously
did not exist) contained 4k of nulls. Mutt also deleted the
symlink afterwards. The behaviour Hamish describes exhibits two
different problems:
- The temporary file name generator we use when interpreting
nametemplates from the mailcap file was broken since it used
access(2) to check for the existance of a file. Obviously, this
doesn't detect dangling symlinks.
- There are some attachment-handling functions which don't avoid
race conditions by using our safe_fopen() function, but relied
on stock libc fopen(3) instead.
SOLUTION
The attached patch is against mutt 0.95.3 and is supposed to fix
these problems. mutt 0.95.4 will fix that too. As a work-around,
you can use a private $TMPDIR with mutt. (This may be a good idea
in general.)
Index: attach.c
=====================================================================
RCS file: /home/roessler/cvsroot/mutt/attach.c,v
retrieving revision 2.1.4.4
diff -u -u -r2.1.4.4 attach.c
--- attach.c 1999/02/10 22:02:02 2.1.4.4
+++ attach.c 1999/02/28 08:06:08
@@ -707,9 +707,11 @@
memset (&s, 0, sizeof (s));
if (flags == M_SAVE_APPEND)
- s.fpout = safe_fopen (path, "a");
- else
+ s.fpout = fopen (path, "a");
+ else if (flags == M_SAVE_OVERWRITE)
s.fpout = fopen (path, "w");
+ else
+ s.fpout = safe_fopen (path, "w");
if (s.fpout == NULL)
{
mutt_perror ("fopen");
@@ -771,9 +773,12 @@
s.flags = displaying ? M_DISPLAY : 0;
if (flags == M_SAVE_APPEND)
- s.fpout = safe_fopen (path, "a");
- else
+ s.fpout = fopen (path, "a");
+ else if (flags == M_SAVE_OVERWRITE)
s.fpout = fopen (path, "w");
+ else
+ s.fpout = safe_fopen (path, "w");
+
if (s.fpout == NULL)
{
perror ("fopen");
Index: lib.c
=====================================================================
RCS file: /home/roessler/cvsroot/mutt/lib.c,v
retrieving revision 2.2.4.5
diff -u -u -r2.2.4.5 lib.c
--- lib.c 1999/02/10 22:02:04 2.2.4.5
+++ lib.c 1999/02/28 08:06:08
@@ -803,8 +803,10 @@
case 2: /* append */
*append = M_SAVE_APPEND;
+ break;
case 1: /* overwrite */
- ;
+ *append = M_SAVE_OVERWRITE;
+ break;
}
}
return 0;
Index: mutt.h
=====================================================================
RCS file: /home/roessler/cvsroot/mutt/mutt.h,v
retrieving revision 2.1.4.6
diff -u -u -r2.1.4.6 mutt.h
--- mutt.h 1999/02/10 21:42:31 2.1.4.6
+++ mutt.h 1999/02/28 08:06:08
@@ -227,7 +227,8 @@
M_NEW_SOCKET,
/* Options for mutt_save_attachment */
- M_SAVE_APPEND
+ M_SAVE_APPEND,
+ M_SAVE_OVERWRITE
};
/* possible arguments to set_quadoption() */
Index: rfc1524.c
=====================================================================
RCS file: /home/roessler/cvsroot/mutt/rfc1524.c,v
retrieving revision 2.0.4.4
diff -u -u -r2.0.4.4 rfc1524.c
--- rfc1524.c 1999/02/10 22:02:06 2.0.4.4
+++ rfc1524.c 1999/02/28 08:06:09
@@ -29,11 +29,14 @@
#include "mutt.h"
#include "rfc1524.h"
-#include <ctype.h>
+#include <string.h>
#include <stdlib.h>
-#include <unistd.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
#include <sys/wait.h>
-#include <string.h>
+#include <errno.h>
+#include <unistd.h>
/* The command semantics include the following:
* %s is the filename that contains the mail body data
@@ -445,6 +448,7 @@
char tmp[_POSIX_PATH_MAX];
char *period;
size_t sl;
+ struct stat sb;
strfcpy (buf, NONULL (Tempdir), sizeof (buf));
mutt_expand_path (buf, sizeof (buf));
@@ -457,7 +461,7 @@
{
strfcpy (tmp, s, sizeof (tmp));
snprintf (s, l, "%s/%s", buf, tmp);
- if (access (s, F_OK) != 0)
+ if (lstat (s, &sb) == -1 && errno == ENOENT)
return;
if ((period = strrchr (tmp, '.')) != NULL)
*period = 0;
@@ -610,6 +614,11 @@
* This function returns 0 on successful move, 1 on old file doesn't exist,
* 2 on new file already exists, and 3 on other failure.
*/
+
+/* note on access(2) use: No dangling symlink problems here due to
+ * safe_fopen().
+ */
+
int mutt_rename_file (char *oldfile, char *newfile)
{
FILE *ofp, *nfp;