al_read_directory crash on 64bit Windows 8
simast

Hello,

I suspect there is a bug somewhere in al_read_directory code.. It could be related to 64bit setup as I am both using a 64bit Windows 8 RTM and have my project (and static Allegro 5.0.7 lib compiled as a 64bit binary). Here is the snipped I am having issues with:

#SelectExpand
1ALLEGRO_FS_ENTRY* resDir = al_create_fs_entry("D:\\Test\\"); 2 3if (al_open_directory(resDir)) { 4 5 ALLEGRO_FS_ENTRY* nextFile; 6 while (nextFile = al_read_directory(resDir)) { // Crash 7 8 al_destroy_fs_entry(nextFile); 9 } 10 11 al_close_directory(resDir); 12} 13 14al_destroy_fs_entry(resDir);

The "D:\Test\" directory exists (it passes the al_open_directory() call) and has some files/directories in it. The crash is access violation type (pointer issues?) and the stack dump points to ntdll.dll/findf64.c file.

I am using Visual Studio 2012 as my compiler/runtime.

Can anyone confirm it? Had similar issues before? Is there a possible workaround?

Edit: It seems the crash is in Allegro fshook_stdio.c line 269 trying to call _tfindnext():

fshook_stdio.c#SelectExpand
1/* 2 * readdir 3 * 4 * Return a pointer to a dirent structure filled with the information on the 5 * next entry in the directory. 6 */ 7static struct dirent* readdir(DIR* dirp) 8{ 9 errno = 0; 10 11 /* Check for valid DIR struct. */ 12 if (!dirp) { 13 errno = EFAULT; 14 return (struct dirent*) 0; 15 } 16 17 if (dirp->dd_stat < 0) { 18 /* We have already returned all files in the directory 19 * (or the structure has an invalid dd_stat). */ 20 return (struct dirent*) 0; 21 } 22 else if (dirp->dd_stat == 0) { 23 /* We haven't started the search yet. */ 24 /* Start the search */ 25 dirp->dd_handle = _tfindfirst(dirp->dd_name, &(dirp->dd_dta)); 26 27 if (dirp->dd_handle == -1) { 28 /* Whoops! Seems there are no files in that 29 * directory. */ 30 dirp->dd_stat = -1; 31 } 32 else { 33 dirp->dd_stat = 1; 34 } 35 } 36 else { 37 /* Get the next search entry. */
38 if (_tfindnext(dirp->dd_handle, &(dirp->dd_dta))) {
39 /* We are off the end or otherwise error. 40 _findnext sets errno to ENOENT if no more file 41 Undo this. */ 42 DWORD winerr = GetLastError(); 43 if (winerr == ERROR_NO_MORE_FILES) 44 errno = 0; 45 _findclose(dirp->dd_handle); 46 dirp->dd_handle = -1; 47 dirp->dd_stat = -1; 48 } 49 else { 50 /* Update the status to indicate the correct 51 * number. */ 52 dirp->dd_stat++; 53 } 54 } 55 56 if (dirp->dd_stat > 0) { 57 /* Successfully got an entry. Everything about the file is 58 * already appropriately filled in except the length of the 59 * file name. */ 60 dirp->dd_dir.d_namlen = _tcslen(dirp->dd_dta.name); 61 _tcscpy(dirp->dd_dir.d_name, dirp->dd_dta.name); 62 return &dirp->dd_dir; 63 } 64 65 return (struct dirent*) 0; 66}

Thread #611254. Printed from Allegro.cc