]> granicus.if.org Git - php/commitdiff
Fixed bug #75525 Access Violation in vcruntime140.dll
authorAnatol Belski <ab@php.net>
Wed, 15 Nov 2017 08:55:29 +0000 (09:55 +0100)
committerAnatol Belski <ab@php.net>
Wed, 15 Nov 2017 08:55:29 +0000 (09:55 +0100)
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
win32/readdir.h

index d11359e59422e19fcecb76a360079f6524c751dc..a3f20f7f3d4269d955392dec41edc9691fee4784 100644 (file)
@@ -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);
 
index 0ed7b1d6404b591475e53bd0ca0196bb82d7eae8..5c594fd7ea5e1cfadffb8d5be7241f3f26701a56 100644 (file)
@@ -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 */