From 020fdfd55dc534eecab12a53bb3ef50d7a71e5cb Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 15 Nov 2017 09:55:29 +0100 Subject: [PATCH] Fixed bug #75525 Access Violation in vcruntime140.dll It was a mistake to make d_name a pointer. d_name has to be allocated in the body of struct dirent as per POSIX.1-2008. The binary compatibility is kept through the extra padding, which will be removed in 7.3. --- win32/readdir.c | 14 +++++--------- win32/readdir.h | 6 +++++- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/win32/readdir.c b/win32/readdir.c index d11359e594..a3f20f7f3d 100644 --- a/win32/readdir.c +++ b/win32/readdir.c @@ -37,7 +37,7 @@ DIR *opendir(const char *dir) return NULL; } - dp = (DIR *) calloc(1, sizeof(DIR)); + dp = (DIR *) calloc(1, sizeof(DIR) + MAXPATHLEN*sizeof(char)); if (dp == NULL) { return NULL; } @@ -104,9 +104,8 @@ struct dirent *readdir(DIR *dp) /* wide to utf8 failed, should never happen. */ return NULL; } - if (dp->dent.d_name) - free(dp->dent.d_name); - dp->dent.d_name = _tmp; + memmove(dp->dent.d_name, _tmp, reclen + 1); + free(_tmp); dp->dent.d_reclen = (unsigned short)reclen; dp->offset++; @@ -141,9 +140,8 @@ int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result) result = NULL; return 0; } - if (dp->dent.d_name) - free(dp->dent.d_name); - dp->dent.d_name = _tmp; + memmove(dp->dent.d_name, _tmp, reclen + 1); + free(_tmp); dp->dent.d_reclen = (unsigned short)reclen; dp->offset++; @@ -169,8 +167,6 @@ int closedir(DIR *dp) } if (dp->dirw) free(dp->dirw); - if (dp->dent.d_name) - free(dp->dent.d_name); if (dp) free(dp); diff --git a/win32/readdir.h b/win32/readdir.h index 0ed7b1d640..5c594fd7ea 100644 --- a/win32/readdir.h +++ b/win32/readdir.h @@ -22,7 +22,11 @@ struct dirent { long d_ino; /* inode (always 1 in WIN32) */ off_t d_off; /* offset to this dirent */ unsigned short d_reclen; /* length of d_name */ - char *d_name; /* null terminated filename in the current encoding, glyph number <= 255 wchar_t's + \0 byte */ + unsigned short pad0; +#if defined(_WIN64) + uint32_t pad1; +#endif + char d_name[1]; /* null terminated filename in the current encoding, glyph number <= 255 wchar_t's + \0 byte */ }; /* typedef DIR - not the same as Unix */ -- 2.40.0