Commit 1b9a5efd 1b9a5efd51a4ae7a35f146f2035d76e0b284353a by Sergey Poznyakoff

Prevent possible infinite recursion (Fixes Bug#134330).

1 parent 15728c67
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
26 #define NOINFERIORS (1 << 3) 26 #define NOINFERIORS (1 << 3)
27 #define NOSELECT_RECURSE (1 << 4) 27 #define NOSELECT_RECURSE (1 << 4)
28 28
29 struct inode_list
30 {
31 struct inode_list *next;
32 ino_t inode;
33 };
34
29 /* 35 /*
30 1- IMAP4 insists: the reference argument that is include in the 36 1- IMAP4 insists: the reference argument that is include in the
31 interpreted form SHOULD prefix the interpreted form. It SHOULD 37 interpreted form SHOULD prefix the interpreted form. It SHOULD
...@@ -47,7 +53,7 @@ ...@@ -47,7 +53,7 @@
47 53
48 static int match __P ((const char *, const char *, const char *)); 54 static int match __P ((const char *, const char *, const char *));
49 static int imap_match __P ((const char *, const char *, const char *)); 55 static int imap_match __P ((const char *, const char *, const char *));
50 static void list_file __P ((const char *, const char *, const char *, const char *)); 56 static void list_file __P ((const char *, const char *, const char *, const char *, struct inode_list *));
51 static void print_file __P ((const char *, const char *, const char *)); 57 static void print_file __P ((const char *, const char *, const char *));
52 static void print_dir __P ((const char *, const char *, const char *)); 58 static void print_dir __P ((const char *, const char *, const char *));
53 59
...@@ -156,7 +162,13 @@ imap4d_list (struct imap4d_command *command, char *arg) ...@@ -156,7 +162,13 @@ imap4d_list (struct imap4d_command *command, char *arg)
156 162
157 if (chdir (cwd) == 0) 163 if (chdir (cwd) == 0)
158 { 164 {
159 list_file (cwd, ref, (dir) ? dir : "", delim); 165 struct stat st;
166 struct inode_list inode_rec;
167
168 stat (cwd, &st);
169 inode_rec.next = NULL;
170 inode_rec.inode = st.st_ino;
171 list_file (cwd, ref, (dir) ? dir : "", delim, &inode_rec);
160 chdir (homedir); 172 chdir (homedir);
161 } 173 }
162 free (cwd); 174 free (cwd);
...@@ -166,10 +178,20 @@ imap4d_list (struct imap4d_command *command, char *arg) ...@@ -166,10 +178,20 @@ imap4d_list (struct imap4d_command *command, char *arg)
166 return util_finish (command, RESP_OK, "Completed"); 178 return util_finish (command, RESP_OK, "Completed");
167 } 179 }
168 180
181 static int
182 inode_list_lookup (struct inode_list *list, ino_t inode)
183 {
184 for (; list; list = list->next)
185 if (list->inode == inode)
186 return 1;
187 return 0;
188 }
189
190
169 /* Recusively calling the files. */ 191 /* Recusively calling the files. */
170 static void 192 static void
171 list_file (const char *cwd, const char *ref, const char *pattern, 193 list_file (const char *cwd, const char *ref, const char *pattern,
172 const char *delim) 194 const char *delim, struct inode_list *inode_list)
173 { 195 {
174 DIR *dirp; 196 DIR *dirp;
175 struct dirent *dp; 197 struct dirent *dp;
...@@ -211,24 +233,43 @@ list_file (const char *cwd, const char *ref, const char *pattern, ...@@ -211,24 +233,43 @@ list_file (const char *cwd, const char *ref, const char *pattern,
211 { 233 {
212 if (status & NOSELECT) 234 if (status & NOSELECT)
213 { 235 {
236 struct stat st;
237
238 if (stat (entry, &st))
239 {
240 mu_error ("can't stat %s: %s",
241 entry, strerror (errno));
242 continue;
243 }
244
214 if (next || status & RECURSE_MATCH) 245 if (next || status & RECURSE_MATCH)
215 { 246 {
216 if (!next) 247 if (!next)
217 print_dir (ref, entry, delim); 248 print_dir (ref, entry, delim);
218 if (chdir (entry) == 0) 249
250 if (S_ISDIR (st.st_mode)
251 && inode_list_lookup (inode_list, st.st_ino) == 0)
219 { 252 {
220 char *rf; 253 if (chdir (entry) == 0)
221 char *cd; 254 {
222 rf = calloc (strlen (ref) + strlen (delim) + 255 char *rf;
223 strlen (entry) + 1, 1); 256 char *cd;
224 sprintf (rf, "%s%s%s", ref, delim, entry); 257 struct inode_list inode_rec;
225 cd = calloc (strlen (cwd) + strlen (delim) + 258
226 strlen (entry) + 1, 1); 259 inode_rec.inode = st.st_ino;
227 sprintf (cd, "%s%s%s", cwd, delim, entry); 260 inode_rec.next = inode_list;
228 list_file (cd, rf, (next) ? next : pattern, delim); 261 rf = calloc (strlen (ref) + strlen (delim) +
229 free (rf); 262 strlen (entry) + 1, 1);
230 free (cd); 263 sprintf (rf, "%s%s%s", ref, delim, entry);
231 chdir (cwd); 264 cd = calloc (strlen (cwd) + strlen (delim) +
265 strlen (entry) + 1, 1);
266 sprintf (cd, "%s%s%s", cwd, delim, entry);
267 list_file (cd, rf, (next) ? next : pattern,
268 delim, &inode_rec);
269 free (rf);
270 free (cd);
271 chdir (cwd);
272 }
232 } 273 }
233 } 274 }
234 else 275 else
......