]> diplodocus.org Git - nmh/blobdiff - uip/mhfixmsg.c
ap: Fix write past end of addrs[] array.
[nmh] / uip / mhfixmsg.c
index 388a1c6cda5daa098a8593671b9e4f3efb714e2b..b7f1917a382092b7dfebc88060fe6c7c2fc49b8f 100644 (file)
@@ -71,7 +71,6 @@ void flush_errors (void);
 
 /* mhfree.c */
 extern CT *cts;
-void freects_done (int) NORETURN;
 
 /*
  * static prototypes
@@ -89,7 +88,7 @@ typedef struct 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 **);
@@ -134,7 +133,7 @@ int
 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;
@@ -154,8 +153,6 @@ main (int argc, char **argv) {
 
     if (nmh_init(argv[0], 2)) { return 1; }
 
-    done = freects_done;
-
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
 
@@ -392,6 +389,8 @@ main (int argc, char **argv) {
         }
         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");
         }
@@ -418,9 +417,8 @@ main (int argc, char **argv) {
 
         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;
@@ -428,16 +426,25 @@ main (int argc, char **argv) {
                     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) {
-                        /* 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) {
-                            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) {
-            status += mhfixmsgsbr (ctp, &fx, outfile);
+            status += mhfixmsgsbr (ctp, maildir, &fx, outfile);
+            free_content (*ctp);
 
             if (using_stdin) {
                 (void) m_unlink (file);
@@ -464,6 +472,8 @@ main (int argc, char **argv) {
                 }
             }
         }
+
+        free (cts);
     } else {
         status = 1;
     }
@@ -474,7 +484,6 @@ main (int argc, char **argv) {
     free (folder);
     free (arguments);
 
-    /* done is freects_done, which will clean up all of cts. */
     done (status);
     return NOTOK;
 }
@@ -484,10 +493,13 @@ main (int argc, char **argv) {
  * 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. */
-    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;
@@ -676,7 +688,7 @@ fix_boundary (CT *ct, int *message_mods) {
  */
 static int
 get_multipart_boundary (CT ct, char **part_boundary) {
-    char buffer[BUFSIZ];
+    char buffer[NMH_BUFSIZ];
     char *end_boundary = NULL;
     off_t begin = (off_t) ct->c_end > (off_t) (ct->c_begin + sizeof buffer)
         ?  (off_t) (ct->c_end - sizeof buffer)
@@ -684,10 +696,10 @@ get_multipart_boundary (CT ct, char **part_boundary) {
     size_t bytes_read;
     int status = OK;
 
-    /* This will fail if the boundary spans fread() calls.  BUFSIZ should
+    /* 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;
@@ -744,6 +756,11 @@ get_multipart_boundary (CT ct, char **part_boundary) {
         status = NOTOK;
     }
 
+    if (ct->c_fp) {
+        fclose (ct->c_fp);
+        ct->c_fp = NULL;
+    }
+
     if (status == OK) {
         *part_boundary = end_boundary;
     } else {
@@ -762,7 +779,7 @@ static int
 replace_boundary (CT ct, char *file, char *boundary) {
     FILE *fpin, *fpout;
     int compnum, state;
-    char buf[BUFSIZ], name[NAMESZ];
+    char buf[NMH_BUFSIZ], name[NAMESZ];
     char *np, *vp;
     m_getfld_state_t gstate = 0;
     int status = OK;
@@ -1780,7 +1797,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) {
  */
 static int
 boundary_in_content (FILE **fp, char *file, const char *boundary) {
-    char buffer[BUFSIZ];
+    char buffer[NMH_BUFSIZ];
     size_t bytes_read;
     int found_boundary = 0;
 
@@ -2074,7 +2091,7 @@ content_encoding (CT ct, const char **reason) {
 
     if (ce->ce_file) {
         size_t line_len = 0;
-        char buffer[BUFSIZ];
+        char buffer[NMH_BUFSIZ];
         size_t inbytes;
 
         if (! ce->ce_fp  &&  (ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) {
@@ -2169,7 +2186,7 @@ strip_crs (CT ct, int *message_mods) {
         }
 
         if (fp  &&  *fp) {
-            char buffer[BUFSIZ];
+            char buffer[NMH_BUFSIZ];
             size_t bytes_read;
             size_t bytes_to_read =
                 end > 0 && end > begin  ?  end - begin  :  sizeof buffer;
@@ -2635,7 +2652,7 @@ write_content (CT ct, const char *input_filename, char *outfile, int modify_inpl
                         int i = -1;
 
                         if (old != -1  &&  new != -1) {
-                            char buffer[BUFSIZ];
+                            char buffer[NMH_BUFSIZ];
 
                             while ((i = read (old, buffer, sizeof buffer)) >
                                    0) {