Prevent possible infinite recursion (Fixes Bug#134330).
Showing
1 changed file
with
45 additions
and
4 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,26 +233,45 @@ list_file (const char *cwd, const char *ref, const char *pattern, | ... | @@ -211,26 +233,45 @@ 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); |
249 | |||
250 | if (S_ISDIR (st.st_mode) | ||
251 | && inode_list_lookup (inode_list, st.st_ino) == 0) | ||
252 | { | ||
218 | if (chdir (entry) == 0) | 253 | if (chdir (entry) == 0) |
219 | { | 254 | { |
220 | char *rf; | 255 | char *rf; |
221 | char *cd; | 256 | char *cd; |
257 | struct inode_list inode_rec; | ||
258 | |||
259 | inode_rec.inode = st.st_ino; | ||
260 | inode_rec.next = inode_list; | ||
222 | rf = calloc (strlen (ref) + strlen (delim) + | 261 | rf = calloc (strlen (ref) + strlen (delim) + |
223 | strlen (entry) + 1, 1); | 262 | strlen (entry) + 1, 1); |
224 | sprintf (rf, "%s%s%s", ref, delim, entry); | 263 | sprintf (rf, "%s%s%s", ref, delim, entry); |
225 | cd = calloc (strlen (cwd) + strlen (delim) + | 264 | cd = calloc (strlen (cwd) + strlen (delim) + |
226 | strlen (entry) + 1, 1); | 265 | strlen (entry) + 1, 1); |
227 | sprintf (cd, "%s%s%s", cwd, delim, entry); | 266 | sprintf (cd, "%s%s%s", cwd, delim, entry); |
228 | list_file (cd, rf, (next) ? next : pattern, delim); | 267 | list_file (cd, rf, (next) ? next : pattern, |
268 | delim, &inode_rec); | ||
229 | free (rf); | 269 | free (rf); |
230 | free (cd); | 270 | free (cd); |
231 | chdir (cwd); | 271 | chdir (cwd); |
232 | } | 272 | } |
233 | } | 273 | } |
274 | } | ||
234 | else | 275 | else |
235 | print_dir (ref, entry, delim); | 276 | print_dir (ref, entry, delim); |
236 | } | 277 | } | ... | ... |
-
Please register or sign in to post a comment