Fix out-of-bounds error when incorporating email from stdin
[mmh] / sbr / vfgets.c
1 /*
2 ** vfgets.c -- virtual fgets
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <sysexits.h>
10 #include <h/mh.h>
11 #include <h/utils.h>
12
13 #define QUOTE '\\'
14
15
16 int
17 vfgets(FILE *in, char **bp)
18 {
19         int toggle;
20         char *cp, *dp, *ep, *fp;
21         static int len = 0;
22         static char *pp = NULL;
23
24         if (pp == NULL)
25                 pp = mh_xcalloc(len = BUFSIZ, sizeof(char));
26
27         for (ep = (cp = pp) + len - 1;;) {
28                 if (fgets(cp, ep - cp + 1, in) == NULL) {
29                         if (cp != pp) {
30                                 *bp = pp;
31                                 return 0;
32                         }
33                         return (ferror(in) && !feof(in) ? -1 : 1);
34                 }
35
36                 if ((dp = cp + strlen(cp) - 2) < cp || *dp != QUOTE) {
37 wrong_guess:
38                         if (cp > ++dp)
39                                 adios(EX_SOFTWARE, NULL, "vfgets() botch -- you lose big");
40                         if (*dp == '\n') {
41                                 *bp = pp;
42                                 return 0;
43                         } else {
44                                 cp = ++dp;
45                         }
46                 } else {
47                         for (fp = dp - 1, toggle = 0; fp >= cp; fp--) {
48                                 if (*fp != QUOTE)
49                                         break;
50                                 else
51                                         toggle = !toggle;
52                         }
53                         if (toggle)
54                                 goto wrong_guess;
55
56                         if (*++dp == '\n') {
57                                 *--dp = 0;
58                                 cp = dp;
59                         } else {
60                                 cp = ++dp;
61                         }
62                 }
63
64                 if (cp >= ep) {
65                         int curlen = cp - pp;
66
67                         dp = mh_xrealloc(pp, len += BUFSIZ);
68                         cp = dp + curlen;
69                         ep = (pp = dp) + len - 1;
70                 }
71         }
72 }