Skip to content

Commit 0d529d6

Browse files
committed
The d_name member of struct dirent should be a pointer
Rework for 6095070, so then any encoding is supported. The path segment length is measured in wchar_t size, whereby the number of wchar_t is 255+\0. This means, in the actual encoding, the path segment size can become (255*<bytes per glyph>)+\0 bytes in worst case. It is still valid, as all the FS API uses wide chars internally.
1 parent e637cd8 commit 0d529d6

File tree

2 files changed

+16
-10
lines changed

2 files changed

+16
-10
lines changed

win32/readdir.c

+15-9
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ DIR *opendir(const char *dir)
3737
return NULL;
3838
}
3939

40-
dp = (DIR *) malloc(sizeof(DIR));
40+
dp = (DIR *) calloc(1, sizeof(DIR));
4141
if (dp == NULL) {
4242
return NULL;
4343
}
@@ -87,6 +87,7 @@ DIR *opendir(const char *dir)
8787
struct dirent *readdir(DIR *dp)
8888
{
8989
char *_tmp;
90+
size_t reclen;
9091

9192
if (!dp || dp->finished)
9293
return NULL;
@@ -98,14 +99,15 @@ struct dirent *readdir(DIR *dp)
9899
}
99100
}
100101

101-
_tmp = php_win32_ioutil_w_to_any(dp->fileinfo.cFileName);
102+
_tmp = php_win32_cp_conv_w_to_any(dp->fileinfo.cFileName, PHP_WIN32_CP_IGNORE_LEN, &reclen);
102103
if (!_tmp) {
103104
/* wide to utf8 failed, should never happen. */
104105
return NULL;
105106
}
106-
strlcpy(dp->dent.d_name, _tmp, _MAX_FNAME*4+1);
107-
dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
108-
free(_tmp);
107+
if (dp->dent.d_name)
108+
free(dp->dent.d_name);
109+
dp->dent.d_name = _tmp;
110+
dp->dent.d_reclen = (unsigned short)reclen;
109111

110112
dp->offset++;
111113

@@ -118,6 +120,7 @@ struct dirent *readdir(DIR *dp)
118120
int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result)
119121
{
120122
char *_tmp;
123+
size_t reclen;
121124

122125
if (!dp || dp->finished) {
123126
*result = NULL;
@@ -132,15 +135,16 @@ int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result)
132135
}
133136
}
134137

135-
_tmp = php_win32_ioutil_w_to_any(dp->fileinfo.cFileName);
138+
_tmp = php_win32_cp_conv_w_to_any(dp->fileinfo.cFileName, PHP_WIN32_CP_IGNORE_LEN, &reclen);
136139
if (!_tmp) {
137140
/* wide to utf8 failed, should never happen. */
138141
result = NULL;
139142
return 0;
140143
}
141-
strlcpy(dp->dent.d_name, _tmp, _MAX_FNAME*4+1);
142-
dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
143-
free(_tmp);
144+
if (dp->dent.d_name)
145+
free(dp->dent.d_name);
146+
dp->dent.d_name = _tmp;
147+
dp->dent.d_reclen = (unsigned short)reclen;
144148

145149
dp->offset++;
146150

@@ -165,6 +169,8 @@ int closedir(DIR *dp)
165169
}
166170
if (dp->dirw)
167171
free(dp->dirw);
172+
if (dp->dent.d_name)
173+
free(dp->dent.d_name);
168174
if (dp)
169175
free(dp);
170176

win32/readdir.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct dirent {
2222
long d_ino; /* inode (always 1 in WIN32) */
2323
off_t d_off; /* offset to this dirent */
2424
unsigned short d_reclen; /* length of d_name */
25-
char d_name[_MAX_FNAME*4+1]; /* filename with care about UTF-8 (null terminated) */
25+
char *d_name; /* null terminated filename in the current encoding, glyph number <= 255 wchar_t's + \0 byte */
2626
};
2727

2828
/* typedef DIR - not the same as Unix */

0 commit comments

Comments
 (0)