]> diplodocus.org Git - nmh/blobdiff - uip/mhfixmsg.c
ap: Fix write past end of addrs[] array.
[nmh] / uip / mhfixmsg.c
index 086bac09ec811ca0aca16e674b2f7598948fd716..b7f1917a382092b7dfebc88060fe6c7c2fc49b8f 100644 (file)
@@ -71,7 +71,6 @@ void flush_errors (void);
 
 /* mhfree.c */
 extern CT *cts;
 
 /* mhfree.c */
 extern CT *cts;
-void freects_done (int) NORETURN;
 
 /*
  * static prototypes
 
 /*
  * static prototypes
@@ -89,7 +88,7 @@ typedef struct fix_transformations {
     char *textcharset;
 } fix_transformations;
 
     char *textcharset;
 } fix_transformations;
 
-int mhfixmsgsbr (CT *, const fix_transformations *, char *);
+int mhfixmsgsbr (CT *, char *, const fix_transformations *, char *);
 static int fix_boundary (CT *, int *);
 static int copy_input_to_output (const char *, const char *);
 static int get_multipart_boundary (CT, char **);
 static int fix_boundary (CT *, int *);
 static int copy_input_to_output (const char *, const char *);
 static int get_multipart_boundary (CT, char **);
@@ -134,7 +133,7 @@ int
 main (int argc, char **argv) {
     int msgnum;
     char *cp, *file = NULL, *folder = NULL;
 main (int argc, char **argv) {
     int msgnum;
     char *cp, *file = NULL, *folder = NULL;
-    char *maildir, buf[100], *outfile = NULL;
+    char *maildir = NULL, buf[100], *outfile = NULL;
     char **argp, **arguments;
     struct msgs_array msgs = { 0, 0, NULL };
     struct msgs *mp = NULL;
     char **argp, **arguments;
     struct msgs_array msgs = { 0, 0, NULL };
     struct msgs *mp = NULL;
@@ -154,8 +153,6 @@ main (int argc, char **argv) {
 
     if (nmh_init(argv[0], 2)) { return 1; }
 
 
     if (nmh_init(argv[0], 2)) { return 1; }
 
-    done = freects_done;
-
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
 
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
 
@@ -392,6 +389,8 @@ main (int argc, char **argv) {
         }
         maildir = m_maildir (folder);
 
         }
         maildir = m_maildir (folder);
 
+        /* chdir so that error messages, esp. from MIME parser, just
+           refer to the message and not its path. */
         if (chdir (maildir) == NOTOK) {
             adios (maildir, "unable to change directory to");
         }
         if (chdir (maildir) == NOTOK) {
             adios (maildir, "unable to change directory to");
         }
@@ -418,9 +417,8 @@ main (int argc, char **argv) {
 
         for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
             if (is_selected(mp, msgnum)) {
 
         for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
             if (is_selected(mp, msgnum)) {
-                char *msgnam;
+                char *msgnam = m_name (msgnum);
 
 
-                msgnam = m_name (msgnum);
                 if ((ct = parse_mime (msgnam))) {
                     set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings);
                     *ctp++ = ct;
                 if ((ct = parse_mime (msgnam))) {
                     set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings);
                     *ctp++ = ct;
@@ -428,16 +426,25 @@ main (int argc, char **argv) {
                     advise (NULL, "unable to parse message %s", msgnam);
                     status = NOTOK;
 
                     advise (NULL, "unable to parse message %s", msgnam);
                     status = NOTOK;
 
-                    /* If there's an outfile, pass the input message unchanged, so the message won't
-                       get dropped from a pipeline. */
+                    /* If there's an outfile, pass the input message
+                       unchanged, so the message won't get dropped from a
+                       pipeline. */
                     if (outfile) {
                     if (outfile) {
-                        /* Something went wrong.  Output might be expected, such as if this were run
-                           as a filter.  Just copy the input to the output. */
-                        const char *input_filename = path (msgnam, TFILE);
+                        /* Something went wrong.  Output might be expected,
+                           such as if this were run as a filter.  Just copy
+                           the input to the output. */
+                        /* Can't use path() here because 1) it might have been
+                           called before and it caches the pwd, and 2) we call
+                           chdir() after that. */
+                        char *input_filename =
+                            concat (maildir, "/", msgnam, NULL);
 
                         if (copy_input_to_output (input_filename, outfile) != OK) {
 
                         if (copy_input_to_output (input_filename, outfile) != OK) {
-                            advise (NULL, "unable to copy message to %s, it might be lost\n", outfile);
+                            advise (NULL,
+                                    "unable to copy message to %s, it might be lost\n",
+                                    outfile);
                         }
                         }
+                        free (input_filename);
                     }
                 }
             }
                     }
                 }
             }
@@ -453,7 +460,8 @@ main (int argc, char **argv) {
 
     if (*cts) {
         for (ctp = cts; *ctp; ++ctp) {
 
     if (*cts) {
         for (ctp = cts; *ctp; ++ctp) {
-            status += mhfixmsgsbr (ctp, &fx, outfile);
+            status += mhfixmsgsbr (ctp, maildir, &fx, outfile);
+            free_content (*ctp);
 
             if (using_stdin) {
                 (void) m_unlink (file);
 
             if (using_stdin) {
                 (void) m_unlink (file);
@@ -464,6 +472,8 @@ main (int argc, char **argv) {
                 }
             }
         }
                 }
             }
         }
+
+        free (cts);
     } else {
         status = 1;
     }
     } else {
         status = 1;
     }
@@ -474,7 +484,6 @@ main (int argc, char **argv) {
     free (folder);
     free (arguments);
 
     free (folder);
     free (arguments);
 
-    /* done is freects_done, which will clean up all of cts. */
     done (status);
     return NOTOK;
 }
     done (status);
     return NOTOK;
 }
@@ -484,10 +493,13 @@ main (int argc, char **argv) {
  * Apply transformations to one message.
  */
 int
  * Apply transformations to one message.
  */
 int
-mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) {
+mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx,
+             char *outfile) {
     /* Store input filename in case one of the transformations, i.e.,
        fix_boundary(), rewrites to a tmp file. */
     /* Store input filename in case one of the transformations, i.e.,
        fix_boundary(), rewrites to a tmp file. */
-    char *input_filename = add ((*ctp)->c_file, NULL);
+    char *input_filename = maildir
+        ?  concat (maildir, "/", (*ctp)->c_file, NULL)
+        :  add ((*ctp)->c_file, NULL);
     int modify_inplace = 0;
     int message_mods = 0;
     int status = OK;
     int modify_inplace = 0;
     int message_mods = 0;
     int status = OK;
@@ -687,7 +699,7 @@ get_multipart_boundary (CT ct, char **part_boundary) {
     /* This will fail if the boundary spans fread() calls.  NMH_BUFSIZ should
        be big enough, even if it's just 1024, to make that unlikely. */
 
     /* This will fail if the boundary spans fread() calls.  NMH_BUFSIZ should
        be big enough, even if it's just 1024, to make that unlikely. */
 
-    /* free_content() will close ct->c_fp. */
+    /* free_content() will close ct->c_fp if bogus MP boundary is fixed. */
     if (! ct->c_fp  &&  (ct->c_fp = fopen (ct->c_file, "r")) == NULL) {
         advise (ct->c_file, "unable to open for reading");
         return NOTOK;
     if (! ct->c_fp  &&  (ct->c_fp = fopen (ct->c_file, "r")) == NULL) {
         advise (ct->c_file, "unable to open for reading");
         return NOTOK;
@@ -744,6 +756,11 @@ get_multipart_boundary (CT ct, char **part_boundary) {
         status = NOTOK;
     }
 
         status = NOTOK;
     }
 
+    if (ct->c_fp) {
+        fclose (ct->c_fp);
+        ct->c_fp = NULL;
+    }
+
     if (status == OK) {
         *part_boundary = end_boundary;
     } else {
     if (status == OK) {
         *part_boundary = end_boundary;
     } else {