Skip to content

Commit 758af77

Browse files
committed
Path handling related refactorings
Primarily related to the path handling datatypes, to avoid unnecessary casts, where possible. Also some rework to avoid code dup. Probably more places are to go, even not path related, primarily to have less casts and unsigned integers where possible. That way, we've not only less warnings and casts, but are also safer with regard to the integer overflows. OFC it's not a panacea, but still significantly reduces the vulnerability potential.
1 parent afb6ca2 commit 758af77

13 files changed

+54
-97
lines changed

TSRM/readdir.h

+3-45
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,3 @@
1-
#ifndef READDIR_H
2-
#define READDIR_H
3-
4-
5-
/*
6-
* Structures and types used to implement opendir/readdir/closedir
7-
* on Windows 95/NT.
8-
*/
9-
10-
#include <windows.h>
11-
12-
#include <io.h>
13-
#include <stdio.h>
14-
#include <stdlib.h>
15-
#include <sys/types.h>
16-
#include <direct.h>
17-
18-
/* struct dirent - same as Unix */
19-
20-
struct dirent {
21-
long d_ino; /* inode (always 1 in WIN32) */
22-
off_t d_off; /* offset to this dirent */
23-
unsigned short d_reclen; /* length of d_name */
24-
char d_name[_MAX_FNAME + 1]; /* filename (null terminated) */
25-
};
26-
27-
28-
/* typedef DIR - not the same as Unix */
29-
typedef struct {
30-
HANDLE handle; /* _findfirst/_findnext handle */
31-
short offset; /* offset into directory */
32-
short finished; /* 1 if there are not more files */
33-
WIN32_FIND_DATA fileinfo; /* from _findfirst/_findnext */
34-
char *dir; /* the dir we are reading */
35-
struct dirent dent; /* the dirent to return */
36-
} DIR;
37-
38-
/* Function prototypes */
39-
DIR *opendir(const char *);
40-
struct dirent *readdir(DIR *);
41-
int readdir_r(DIR *, struct dirent *, struct dirent **);
42-
int closedir(DIR *);
43-
int rewinddir(DIR *);
44-
45-
#endif /* READDIR_H */
1+
/* Keep this header for compatibility with external code, it's currently not
2+
used anywhere in the core and there are no implementations in TSRM. */
3+
#include "win32/readdir.h"

TSRM/tsrm_win32.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -296,14 +296,14 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
296296

297297
if (CWDG(realpath_cache_size_limit)) {
298298
t = time(0);
299-
bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t);
299+
bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
300300
if(bucket == NULL && real_path == NULL) {
301301
/* We used the pathname directly. Call tsrm_realpath */
302302
/* so that entry is created in realpath cache */
303303
real_path = (char *)malloc(MAXPATHLEN);
304304
if(tsrm_realpath(pathname, real_path) != NULL) {
305305
pathname = real_path;
306-
bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t);
306+
bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
307307
PHP_WIN32_IOUTIL_REINIT_W(pathname);
308308
}
309309
}

UPGRADING.INTERNALS

+6-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ PHP 7.1 INTERNALS UPGRADE NOTES
1313
1. Internal API changes
1414
========================
1515

16-
a.
16+
a. Path related functions
17+
- CWD_API void realpath_cache_del(const char *path, size_t path_len);
18+
- CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, size_t path_len, time_t t);
19+
- PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, size_t filename_len);
20+
- PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value);
21+
1722

1823
========================
1924
2. Build system changes

Zend/zend_virtual_cwd.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ CWD_API char *virtual_getcwd(char *buf, size_t size) /* {{{ */
537537
/* }}} */
538538

539539
#ifdef ZEND_WIN32
540-
static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {{{ */
540+
static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /* {{{ */
541541
{
542542
register zend_ulong h;
543543
char *bucket_key_start = tsrm_win32_get_path_sid_key(path);
@@ -558,7 +558,7 @@ static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {
558558
}
559559
/* }}} */
560560
#else
561-
static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {{{ */
561+
static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /* {{{ */
562562
{
563563
register zend_ulong h;
564564
const char *e = path + path_len;
@@ -590,7 +590,7 @@ CWD_API void realpath_cache_clean(void) /* {{{ */
590590
}
591591
/* }}} */
592592

593-
CWD_API void realpath_cache_del(const char *path, int path_len) /* {{{ */
593+
CWD_API void realpath_cache_del(const char *path, size_t path_len) /* {{{ */
594594
{
595595
zend_ulong key = realpath_cache_key(path, path_len);
596596
zend_ulong n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
@@ -618,7 +618,7 @@ CWD_API void realpath_cache_del(const char *path, int path_len) /* {{{ */
618618
}
619619
/* }}} */
620620

621-
static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, int is_dir, time_t t) /* {{{ */
621+
static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, size_t realpath_len, int is_dir, time_t t) /* {{{ */
622622
{
623623
zend_long size = sizeof(realpath_cache_bucket) + path_len + 1;
624624
int same = 1;
@@ -664,7 +664,7 @@ static inline void realpath_cache_add(const char *path, int path_len, const char
664664
}
665665
/* }}} */
666666

667-
static inline realpath_cache_bucket* realpath_cache_find(const char *path, int path_len, time_t t) /* {{{ */
667+
static inline realpath_cache_bucket* realpath_cache_find(const char *path, size_t path_len, time_t t) /* {{{ */
668668
{
669669
zend_ulong key = realpath_cache_key(path, path_len);
670670
zend_ulong n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
@@ -693,7 +693,7 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p
693693
}
694694
/* }}} */
695695

696-
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t) /* {{{ */
696+
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, size_t path_len, time_t t) /* {{{ */
697697
{
698698
return realpath_cache_find(path, path_len, t);
699699
}

Zend/zend_virtual_cwd.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ extern virtual_cwd_globals cwd_globals;
232232
#endif
233233

234234
CWD_API void realpath_cache_clean(void);
235-
CWD_API void realpath_cache_del(const char *path, int path_len);
236-
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t);
235+
CWD_API void realpath_cache_del(const char *path, size_t path_len);
236+
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, size_t path_len, time_t t);
237237
CWD_API zend_long realpath_cache_size(void);
238238
CWD_API zend_long realpath_cache_max_buckets(void);
239239
CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void);

ext/phar/func_interceptors.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
585585
}
586586
/* }}} */
587587

588-
static void phar_file_stat(const char *filename, php_stat_len filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
588+
static void phar_file_stat(const char *filename, size_t filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
589589
{
590590
if (!filename_length) {
591591
RETURN_FALSE;
@@ -770,7 +770,7 @@ void fname(INTERNAL_FUNCTION_PARAMETERS) { \
770770
return; \
771771
} \
772772
\
773-
phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
773+
phar_file_stat(filename, filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
774774
} \
775775
}
776776
/* }}} */

ext/phar/phar_object.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
14231423
uint32_t str_key_len, base_len = p_obj->l;
14241424
phar_entry_data *data;
14251425
php_stream *fp;
1426-
php_stat_len fname_len;
1426+
size_t fname_len;
14271427
size_t contents_len;
14281428
char *fname, *error = NULL, *base = p_obj->b, *save = NULL, *temp = NULL;
14291429
zend_string *opened;
@@ -1501,7 +1501,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
15011501
switch (intern->type) {
15021502
case SPL_FS_DIR:
15031503
test = spl_filesystem_object_get_path(intern, NULL);
1504-
fname_len = (php_stat_len)spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
1504+
fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
15051505
php_stat(fname, fname_len, FS_IS_DIR, &dummy);
15061506

15071507
if (Z_TYPE(dummy) == IS_TRUE) {
@@ -1515,7 +1515,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
15151515

15161516
if (test) {
15171517
fname = test;
1518-
fname_len = (php_stat_len)strlen(fname);
1518+
fname_len = strlen(fname);
15191519
} else {
15201520
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
15211521
return ZEND_HASH_APPLY_STOP;
@@ -1531,7 +1531,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
15311531
return ZEND_HASH_APPLY_STOP;
15321532
}
15331533

1534-
fname_len = (php_stat_len)strlen(fname);
1534+
fname_len = strlen(fname);
15351535
save = fname;
15361536
goto phar_spl_fileinfo;
15371537
}
@@ -1543,7 +1543,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
15431543
}
15441544

15451545
fname = Z_STRVAL_P(value);
1546-
fname_len = (php_stat_len)Z_STRLEN_P(value);
1546+
fname_len = Z_STRLEN_P(value);
15471547

15481548
phar_spl_fileinfo:
15491549
if (base_len) {

ext/standard/dir.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ PHP_NAMED_FUNCTION(php_if_readdir)
420420
Find pathnames matching a pattern */
421421
PHP_FUNCTION(glob)
422422
{
423-
int cwd_skip = 0;
423+
size_t cwd_skip = 0;
424424
#ifdef ZTS
425425
char cwd[MAXPATHLEN];
426426
char work_pattern[MAXPATHLEN];
@@ -459,7 +459,7 @@ PHP_FUNCTION(glob)
459459
cwd[2] = '\0';
460460
}
461461
#endif
462-
cwd_skip = (int)strlen(cwd)+1;
462+
cwd_skip = strlen(cwd)+1;
463463

464464
snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
465465
pattern = work_pattern;

ext/standard/filestat.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ PHP_FUNCTION(touch)
705705

706706
/* {{{ php_clear_stat_cache()
707707
*/
708-
PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len)
708+
PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, size_t filename_len)
709709
{
710710
/* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL
711711
* as it may contain outdated data (e.g. "nlink" for a directory when deleting a file
@@ -740,7 +740,7 @@ PHP_FUNCTION(clearstatcache)
740740
return;
741741
}
742742

743-
php_clear_stat_cache(clear_realpath_cache, filename, (int)filename_len);
743+
php_clear_stat_cache(clear_realpath_cache, filename, filename_len);
744744
}
745745
/* }}} */
746746

@@ -751,7 +751,7 @@ PHP_FUNCTION(clearstatcache)
751751

752752
/* {{{ php_stat
753753
*/
754-
PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value)
754+
PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value)
755755
{
756756
zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
757757
stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
@@ -996,7 +996,7 @@ void name(INTERNAL_FUNCTION_PARAMETERS) { \
996996
Z_PARAM_PATH(filename, filename_len) \
997997
ZEND_PARSE_PARAMETERS_END(); \
998998
\
999-
php_stat(filename, (php_stat_len) filename_len, funcnum, return_value); \
999+
php_stat(filename, filename_len, funcnum, return_value); \
10001000
}
10011001
/* }}} */
10021002

ext/standard/php_filestat.h

+4-7
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,11 @@ PHP_FUNCTION(clearstatcache);
7878
#define getuid() 1
7979
#endif
8080

81-
#ifdef PHP_WIN32
82-
typedef unsigned int php_stat_len;
83-
#else
84-
typedef int php_stat_len;
85-
#endif
81+
/* Compatibility. */
82+
typedef size_t php_stat_len;
8683

87-
PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len);
88-
PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value);
84+
PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, size_t filename_len);
85+
PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value);
8986

9087
/* Switches for various filestat functions: */
9188
#define FS_PERMS 0

sapi/cli/php_cli.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ static int do_cli(int argc, char **argv) /* {{{ */
11261126
}
11271127
case PHP_MODE_REFLECTION_EXT_INFO:
11281128
{
1129-
int len = (int)strlen(reflection_what);
1129+
size_t len = strlen(reflection_what);
11301130
char *lcname = zend_str_tolower_dup(reflection_what, len);
11311131
zend_module_entry *module;
11321132

@@ -1202,7 +1202,7 @@ int main(int argc, char *argv[])
12021202
int php_optind = 1, use_extended_info = 0;
12031203
char *ini_path_override = NULL;
12041204
char *ini_entries = NULL;
1205-
int ini_entries_len = 0;
1205+
size_t ini_entries_len = 0;
12061206
int ini_ignore = 0;
12071207
sapi_module_struct *sapi_module = &cli_sapi_module;
12081208

@@ -1276,19 +1276,19 @@ int main(int argc, char *argv[])
12761276
break;
12771277
case 'd': {
12781278
/* define ini entries on command line */
1279-
int len = (int)strlen(php_optarg);
1279+
size_t len = strlen(php_optarg);
12801280
char *val;
12811281

12821282
if ((val = strchr(php_optarg, '='))) {
12831283
val++;
12841284
if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
12851285
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
12861286
memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
1287-
ini_entries_len += (int)(val - php_optarg);
1287+
ini_entries_len += (val - php_optarg);
12881288
memcpy(ini_entries + ini_entries_len, "\"", 1);
12891289
ini_entries_len++;
12901290
memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg));
1291-
ini_entries_len += len - (int)(val - php_optarg);
1291+
ini_entries_len += len - (val - php_optarg);
12921292
memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
12931293
ini_entries_len += sizeof("\n\0\"") - 2;
12941294
} else {

win32/readdir.c

-10
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,6 @@
2424
extern "C" {
2525
#endif
2626

27-
/* typedef DIR - not the same as Unix */
28-
struct DIR_W32 {
29-
HANDLE handle; /* _findfirst/_findnext handle */
30-
int offset; /* offset into directory */
31-
short finished; /* 1 if there are not more files */
32-
WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */
33-
wchar_t *dirw; /* the dir we are reading */
34-
struct dirent dent; /* the dirent to return */
35-
};
36-
3727
DIR *opendir(const char *dir)
3828
{
3929
DIR *dp;

win32/readdir.h

+13-6
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,32 @@ extern "C" {
88

99
/*
1010
* Structures and types used to implement opendir/readdir/closedir
11-
* on Windows 95/NT.
11+
* on Windows.
1212
*/
1313

1414
#include <config.w32.h>
1515

16-
#include <stdlib.h>
17-
#include <sys/types.h>
16+
#include "ioutil.h"
1817

1918
#define php_readdir_r readdir_r
2019

2120
/* struct dirent - same as Unix */
2221
struct dirent {
2322
long d_ino; /* inode (always 1 in WIN32) */
24-
off_t d_off; /* offset to this dirent */
25-
unsigned short d_reclen; /* length of d_name */
26-
char d_name[_MAX_FNAME + 1]; /* filename (null terminated) */
23+
off_t d_off; /* offset to this dirent */
24+
unsigned short d_reclen; /* length of d_name */
25+
char d_name[PHP_WIN32_IOUTIL_MAXPATHLEN + 1]; /* filename (null terminated) */
2726
};
2827

2928
/* typedef DIR - not the same as Unix */
29+
struct DIR_W32 {
30+
HANDLE handle; /* _findfirst/_findnext handle */
31+
uint16_t offset; /* offset into directory */
32+
uint8_t finished; /* 1 if there are not more files */
33+
WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */
34+
wchar_t *dirw; /* the dir we are reading */
35+
struct dirent dent; /* the dirent to return */
36+
};
3037
typedef struct DIR_W32 DIR;
3138

3239
/* Function prototypes */

0 commit comments

Comments
 (0)