Protect open_and_sort_dir() from the directory changing size.
authorJeremy Allison <jra@samba.org>
Mon, 8 Apr 2013 23:40:35 +0000 (16:40 -0700)
committerKarolin Seeger <kseeger@samba.org>
Mon, 12 Aug 2013 07:09:43 +0000 (09:09 +0200)
Otherwise there could be an error between initial count, allocation
and re-read.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit 582d8ca565ad12133a4319650e886f58246b3bd9)

source3/modules/vfs_dirsort.c

index a3d106da22e4f87309217825fecdb6dff6a20975..3b7f57a78c080333dd9dda4b7ec57a300caccbf2 100644 (file)
@@ -30,7 +30,7 @@ static int compare_dirent (const SMB_STRUCT_DIRENT *da, const SMB_STRUCT_DIRENT
 struct dirsort_privates {
        long pos;
        SMB_STRUCT_DIRENT *directory_list;
-       long number_of_entries;
+       unsigned int number_of_entries;
        time_t mtime;
        SMB_STRUCT_DIR *source_directory;
        int fd;
@@ -42,9 +42,9 @@ static void free_dirsort_privates(void **datap) {
 
 static bool open_and_sort_dir (vfs_handle_struct *handle)
 {
-       SMB_STRUCT_DIRENT *dp;
        struct stat dir_stat;
        unsigned int i;
+       unsigned int total_count = 0;
        struct dirsort_privates *data = NULL;
 
        SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates,
@@ -58,10 +58,10 @@ static bool open_and_sort_dir (vfs_handle_struct *handle)
 
        while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL)
               != NULL) {
-               data->number_of_entries++;
+               total_count++;
        }
 
-       if (data->number_of_entries == 0) {
+       if (total_count == 0) {
                return false;
        }
 
@@ -73,16 +73,22 @@ static bool open_and_sort_dir (vfs_handle_struct *handle)
        TALLOC_FREE(data->directory_list); /* destroy previous cache if needed */
        data->directory_list = talloc_zero_array(data,
                                                 SMB_STRUCT_DIRENT,
-                                                data->number_of_entries);
+                                                total_count);
        if (!data->directory_list) {
                return false;
        }
-       i = 0;
-       while ((dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory,
-                                         NULL)) != NULL) {
-               data->directory_list[i++] = *dp;
+       for (i = 0; i < total_count; i++) {
+               SMB_STRUCT_DIRENT *dp = SMB_VFS_NEXT_READDIR(handle,
+                                               data->source_directory,
+                                               NULL);
+               if (dp == NULL) {
+                       break;
+               }
+               data->directory_list[i] = *dp;
        }
 
+       data->number_of_entries = i;
+
        /* Sort the directory entries by name */
        TYPESAFE_QSORT(data->directory_list, data->number_of_entries, compare_dirent);
        return true;