Prevent possible infinite recursion (Fixes Bug#134330).
Showing
1 changed file
with
57 additions
and
16 deletions
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment