mailsplit: make PATH_MAX buffers dynamic

There are several PATH_MAX-sized buffers in mailsplit, along with some questionable uses of sprintf. These are not really of security interest, as local mailsplit pathnames are not typically under control of an attacker, and you could generally only overflow a few numbers at the end of a path that approaches PATH_MAX (a longer path would choke mailsplit long before). But it does not hurt to be careful, and as a bonus we lift some limits for systems with too-small PATH_MAX varibles. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 24, 2015 at 17:05 UTC 1d895f194ff612057989f477dc106aa1c7ac2016
1 file changed +23 -11
builtin/mailsplit.c
+23 -11
@@ -98,30 +98,37 @@ static int populate_maildir_list(struct string_list *list, const char *path)
98 {
99 DIR *dir;
100 struct dirent *dent;
101 - char name[PATH_MAX];
101 + char *name = NULL;
102 char *subs[] = { "cur", "new", NULL };
103 char **sub;
104 + int ret = -1;
105
106 for (sub = subs; *sub; ++sub) {
106 - snprintf(name, sizeof(name), "%s/%s", path, *sub);
107 + free(name);
108 + name = xstrfmt("%s/%s", path, *sub);
109 if ((dir = opendir(name)) == NULL) {
110 if (errno == ENOENT)
111 continue;
112 error("cannot opendir %s (%s)", name, strerror(errno));
111 - return -1;
113 + goto out;
114 }
115
116 while ((dent = readdir(dir)) != NULL) {
117 if (dent->d_name[0] == '.')
118 continue;
117 - snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name);
119 + free(name);
120 + name = xstrfmt("%s/%s", *sub, dent->d_name);
121 string_list_insert(list, name);
122 }
123
124 closedir(dir);
125 }
126
124 - return 0;
127 + ret = 0;
128 +
129 +out:
130 + free(name);
131 + return ret;
132 }
133
134 static int maildir_filename_cmp(const char *a, const char *b)
@@ -148,8 +155,7 @@ static int maildir_filename_cmp(const char *a, const char *b)
155 static int split_maildir(const char *maildir, const char *dir,
156 int nr_prec, int skip)
157 {
151 - char file[PATH_MAX];
152 - char name[PATH_MAX];
158 + char *file = NULL;
159 FILE *f = NULL;
160 int ret = -1;
161 int i;
@@ -161,7 +167,11 @@ static int split_maildir(const char *maildir, const char *dir,
167 goto out;
168
169 for (i = 0; i < list.nr; i++) {
164 - snprintf(file, sizeof(file), "%s/%s", maildir, list.items[i].string);
170 + char *name;
171 +
172 + free(file);
173 + file = xstrfmt("%s/%s", maildir, list.items[i].string);
174 +
175 f = fopen(file, "r");
176 if (!f) {
177 error("cannot open mail %s (%s)", file, strerror(errno));
@@ -173,8 +183,9 @@ static int split_maildir(const char *maildir, const char *dir,
183 goto out;
184 }
185
176 - sprintf(name, "%s/%0*d", dir, nr_prec, ++skip);
186 + name = xstrfmt("%s/%0*d", dir, nr_prec, ++skip);
187 split_one(f, name, 1);
188 + free(name);
189
190 fclose(f);
191 f = NULL;
@@ -184,6 +195,7 @@ static int split_maildir(const char *maildir, const char *dir,
195 out:
196 if (f)
197 fclose(f);
198 + free(file);
199 string_list_clear(&list, 1);
200 return ret;
201 }
@@ -191,7 +203,6 @@ out:
203 static int split_mbox(const char *file, const char *dir, int allow_bare,
204 int nr_prec, int skip)
205 {
194 - char name[PATH_MAX];
206 int ret = -1;
207 int peek;
208
@@ -218,8 +229,9 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
229 }
230
231 while (!file_done) {
221 - sprintf(name, "%s/%0*d", dir, nr_prec, ++skip);
232 + char *name = xstrfmt("%s/%0*d", dir, nr_prec, ++skip);
233 file_done = split_one(f, name, allow_bare);
234 + free(name);
235 }
236
237 if (f != stdin)