Skip to content

Commit

Permalink
Path handling related refactorings
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
weltling committed Dec 22, 2016
1 parent afb6ca2 commit 758af77
Show file tree
Hide file tree
Showing 13 changed files with 54 additions and 97 deletions.
48 changes: 3 additions & 45 deletions TSRM/readdir.h
Original file line number Diff line number Diff line change
@@ -1,45 +1,3 @@
#ifndef READDIR_H
#define READDIR_H


/*
* Structures and types used to implement opendir/readdir/closedir
* on Windows 95/NT.
*/

#include <windows.h>

#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <direct.h>

/* struct dirent - same as Unix */

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[_MAX_FNAME + 1]; /* filename (null terminated) */
};


/* typedef DIR - not the same as Unix */
typedef struct {
HANDLE handle; /* _findfirst/_findnext handle */
short offset; /* offset into directory */
short finished; /* 1 if there are not more files */
WIN32_FIND_DATA fileinfo; /* from _findfirst/_findnext */
char *dir; /* the dir we are reading */
struct dirent dent; /* the dirent to return */
} DIR;

/* Function prototypes */
DIR *opendir(const char *);
struct dirent *readdir(DIR *);
int readdir_r(DIR *, struct dirent *, struct dirent **);
int closedir(DIR *);
int rewinddir(DIR *);

#endif /* READDIR_H */
/* Keep this header for compatibility with external code, it's currently not
used anywhere in the core and there are no implementations in TSRM. */
#include "win32/readdir.h"
4 changes: 2 additions & 2 deletions TSRM/tsrm_win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,14 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)

if (CWDG(realpath_cache_size_limit)) {
t = time(0);
bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t);
bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
if(bucket == NULL && real_path == NULL) {
/* We used the pathname directly. Call tsrm_realpath */
/* so that entry is created in realpath cache */
real_path = (char *)malloc(MAXPATHLEN);
if(tsrm_realpath(pathname, real_path) != NULL) {
pathname = real_path;
bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t);
bucket = realpath_cache_lookup(pathname, strlen(pathname), t);
PHP_WIN32_IOUTIL_REINIT_W(pathname);
}
}
Expand Down
7 changes: 6 additions & 1 deletion UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ PHP 7.1 INTERNALS UPGRADE NOTES
1. Internal API changes
========================

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


========================
2. Build system changes
Expand Down
12 changes: 6 additions & 6 deletions Zend/zend_virtual_cwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ CWD_API char *virtual_getcwd(char *buf, size_t size) /* {{{ */
/* }}} */

#ifdef ZEND_WIN32
static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {{{ */
static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /* {{{ */
{
register zend_ulong h;
char *bucket_key_start = tsrm_win32_get_path_sid_key(path);
Expand All @@ -558,7 +558,7 @@ static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {
}
/* }}} */
#else
static inline zend_ulong realpath_cache_key(const char *path, int path_len) /* {{{ */
static inline zend_ulong realpath_cache_key(const char *path, size_t path_len) /* {{{ */
{
register zend_ulong h;
const char *e = path + path_len;
Expand Down Expand Up @@ -590,7 +590,7 @@ CWD_API void realpath_cache_clean(void) /* {{{ */
}
/* }}} */

CWD_API void realpath_cache_del(const char *path, int path_len) /* {{{ */
CWD_API void realpath_cache_del(const char *path, size_t path_len) /* {{{ */
{
zend_ulong key = realpath_cache_key(path, path_len);
zend_ulong n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
Expand Down Expand Up @@ -618,7 +618,7 @@ CWD_API void realpath_cache_del(const char *path, int path_len) /* {{{ */
}
/* }}} */

static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, int is_dir, time_t t) /* {{{ */
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) /* {{{ */
{
zend_long size = sizeof(realpath_cache_bucket) + path_len + 1;
int same = 1;
Expand Down Expand Up @@ -664,7 +664,7 @@ static inline void realpath_cache_add(const char *path, int path_len, const char
}
/* }}} */

static inline realpath_cache_bucket* realpath_cache_find(const char *path, int path_len, time_t t) /* {{{ */
static inline realpath_cache_bucket* realpath_cache_find(const char *path, size_t path_len, time_t t) /* {{{ */
{
zend_ulong key = realpath_cache_key(path, path_len);
zend_ulong n = key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
Expand Down Expand Up @@ -693,7 +693,7 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p
}
/* }}} */

CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t) /* {{{ */
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, size_t path_len, time_t t) /* {{{ */
{
return realpath_cache_find(path, path_len, t);
}
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_virtual_cwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ extern virtual_cwd_globals cwd_globals;
#endif

CWD_API void realpath_cache_clean(void);
CWD_API void realpath_cache_del(const char *path, int path_len);
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t);
CWD_API void realpath_cache_del(const char *path, size_t path_len);
CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, size_t path_len, time_t t);
CWD_API zend_long realpath_cache_size(void);
CWD_API zend_long realpath_cache_max_buckets(void);
CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void);
Expand Down
4 changes: 2 additions & 2 deletions ext/phar/func_interceptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
}
/* }}} */

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) /* {{{ */
static void phar_file_stat(const char *filename, size_t filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
if (!filename_length) {
RETURN_FALSE;
Expand Down Expand Up @@ -770,7 +770,7 @@ void fname(INTERNAL_FUNCTION_PARAMETERS) { \
return; \
} \
\
phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
phar_file_stat(filename, filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
} \
}
/* }}} */
Expand Down
10 changes: 5 additions & 5 deletions ext/phar/phar_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1423,7 +1423,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
uint32_t str_key_len, base_len = p_obj->l;
phar_entry_data *data;
php_stream *fp;
php_stat_len fname_len;
size_t fname_len;
size_t contents_len;
char *fname, *error = NULL, *base = p_obj->b, *save = NULL, *temp = NULL;
zend_string *opened;
Expand Down Expand Up @@ -1501,7 +1501,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
switch (intern->type) {
case SPL_FS_DIR:
test = spl_filesystem_object_get_path(intern, NULL);
fname_len = (php_stat_len)spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
php_stat(fname, fname_len, FS_IS_DIR, &dummy);

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

if (test) {
fname = test;
fname_len = (php_stat_len)strlen(fname);
fname_len = strlen(fname);
} else {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
return ZEND_HASH_APPLY_STOP;
Expand All @@ -1531,7 +1531,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
return ZEND_HASH_APPLY_STOP;
}

fname_len = (php_stat_len)strlen(fname);
fname_len = strlen(fname);
save = fname;
goto phar_spl_fileinfo;
}
Expand All @@ -1543,7 +1543,7 @@ static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
}

fname = Z_STRVAL_P(value);
fname_len = (php_stat_len)Z_STRLEN_P(value);
fname_len = Z_STRLEN_P(value);

phar_spl_fileinfo:
if (base_len) {
Expand Down
4 changes: 2 additions & 2 deletions ext/standard/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ PHP_NAMED_FUNCTION(php_if_readdir)
Find pathnames matching a pattern */
PHP_FUNCTION(glob)
{
int cwd_skip = 0;
size_t cwd_skip = 0;
#ifdef ZTS
char cwd[MAXPATHLEN];
char work_pattern[MAXPATHLEN];
Expand Down Expand Up @@ -459,7 +459,7 @@ PHP_FUNCTION(glob)
cwd[2] = '\0';
}
#endif
cwd_skip = (int)strlen(cwd)+1;
cwd_skip = strlen(cwd)+1;

snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
pattern = work_pattern;
Expand Down
8 changes: 4 additions & 4 deletions ext/standard/filestat.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ PHP_FUNCTION(touch)

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

php_clear_stat_cache(clear_realpath_cache, filename, (int)filename_len);
php_clear_stat_cache(clear_realpath_cache, filename, filename_len);
}
/* }}} */

Expand All @@ -751,7 +751,7 @@ PHP_FUNCTION(clearstatcache)

/* {{{ php_stat
*/
PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value)
PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value)
{
zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
Expand Down Expand Up @@ -996,7 +996,7 @@ void name(INTERNAL_FUNCTION_PARAMETERS) { \
Z_PARAM_PATH(filename, filename_len) \
ZEND_PARSE_PARAMETERS_END(); \
\
php_stat(filename, (php_stat_len) filename_len, funcnum, return_value); \
php_stat(filename, filename_len, funcnum, return_value); \
}
/* }}} */

Expand Down
11 changes: 4 additions & 7 deletions ext/standard/php_filestat.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,11 @@ PHP_FUNCTION(clearstatcache);
#define getuid() 1
#endif

#ifdef PHP_WIN32
typedef unsigned int php_stat_len;
#else
typedef int php_stat_len;
#endif
/* Compatibility. */
typedef size_t php_stat_len;

PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len);
PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value);
PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, size_t filename_len);
PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value);

/* Switches for various filestat functions: */
#define FS_PERMS 0
Expand Down
10 changes: 5 additions & 5 deletions sapi/cli/php_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ static int do_cli(int argc, char **argv) /* {{{ */
}
case PHP_MODE_REFLECTION_EXT_INFO:
{
int len = (int)strlen(reflection_what);
size_t len = strlen(reflection_what);
char *lcname = zend_str_tolower_dup(reflection_what, len);
zend_module_entry *module;

Expand Down Expand Up @@ -1202,7 +1202,7 @@ int main(int argc, char *argv[])
int php_optind = 1, use_extended_info = 0;
char *ini_path_override = NULL;
char *ini_entries = NULL;
int ini_entries_len = 0;
size_t ini_entries_len = 0;
int ini_ignore = 0;
sapi_module_struct *sapi_module = &cli_sapi_module;

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

if ((val = strchr(php_optarg, '='))) {
val++;
if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
ini_entries_len += (int)(val - php_optarg);
ini_entries_len += (val - php_optarg);
memcpy(ini_entries + ini_entries_len, "\"", 1);
ini_entries_len++;
memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg));
ini_entries_len += len - (int)(val - php_optarg);
ini_entries_len += len - (val - php_optarg);
memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
ini_entries_len += sizeof("\n\0\"") - 2;
} else {
Expand Down
10 changes: 0 additions & 10 deletions win32/readdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@
extern "C" {
#endif

/* typedef DIR - not the same as Unix */
struct DIR_W32 {
HANDLE handle; /* _findfirst/_findnext handle */
int offset; /* offset into directory */
short finished; /* 1 if there are not more files */
WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */
wchar_t *dirw; /* the dir we are reading */
struct dirent dent; /* the dirent to return */
};

DIR *opendir(const char *dir)
{
DIR *dp;
Expand Down
19 changes: 13 additions & 6 deletions win32/readdir.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,32 @@ extern "C" {

/*
* Structures and types used to implement opendir/readdir/closedir
* on Windows 95/NT.
* on Windows.
*/

#include <config.w32.h>

#include <stdlib.h>
#include <sys/types.h>
#include "ioutil.h"

#define php_readdir_r readdir_r

/* struct dirent - same as Unix */
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[_MAX_FNAME + 1]; /* filename (null terminated) */
off_t d_off; /* offset to this dirent */
unsigned short d_reclen; /* length of d_name */
char d_name[PHP_WIN32_IOUTIL_MAXPATHLEN + 1]; /* filename (null terminated) */
};

/* typedef DIR - not the same as Unix */
struct DIR_W32 {
HANDLE handle; /* _findfirst/_findnext handle */
uint16_t offset; /* offset into directory */
uint8_t finished; /* 1 if there are not more files */
WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */
wchar_t *dirw; /* the dir we are reading */
struct dirent dent; /* the dirent to return */
};
typedef struct DIR_W32 DIR;

/* Function prototypes */
Expand Down

0 comments on commit 758af77

Please sign in to comment.