From aa54bf0e773538e1ce12d31e670fbf656902c67d Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Thu, 23 Dec 2021 09:36:22 -0500 Subject: [PATCH 1/3] PHP 8.0: Make stream wrapper and windows drive checks locale-independent - Avoid registering/detecting stream wrappers in locale-independent ways. - Avoid locale dependence for Windows drive letter names in zend_virtual_cwd - Make parse_url stop depending on locale Related to https://bugs.php.net/bug.php?id=52923 iscntrl is locale-dependent which seems to corrupt certain bytes. - Make FILTER_VALIDATE_HOSTNAME with flag FILTER_VALIDATE_DOMAIN locale-independent Somewhat related to https://wiki.php.net/rfc/strtolower-ascii but I don't think most of these should have been locale-dependent in the first place - the code may not have considered locales E.g. on Linux, `setlocale(LC_ALL, 'de_DE');` (if the locale is installed and it succeeds) will have some values for alpha/cntrl in the range 128-256 where the C locale has no values. To avoid this locale-dependence in older php versions, applications can set `setlocale(LC_CTYPE, 'C')`. --- Zend/zend_compile.c | 2 +- Zend/zend_operators.c | 41 +++++++++++++++++++ Zend/zend_operators.h | 7 ++++ Zend/zend_virtual_cwd.h | 2 +- ext/filter/logical_filters.c | 8 ++-- .../tests/filter_validate_domain_locale.phpt | 19 +++++++++ ext/standard/tests/streams/locale.phpt | 26 ++++++++++++ main/fopen_wrappers.c | 6 +-- main/streams/streams.c | 4 +- main/streams/transports.c | 2 +- 10 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 ext/filter/tests/filter_validate_domain_locale.phpt create mode 100644 ext/standard/tests/streams/locale.phpt diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c8fbf7452288..4a93beea86b7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1941,7 +1941,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len) /* Note that on Win32 CWD is per drive (heritage from CP/M). * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive. */ - if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) { + if ((2 <= len) && zend_isalpha_ascii((int)((unsigned char *)path)[0]) && (':' == path[1])) { /* Skip over the drive spec (if any) so as not to change */ path += 2; len_adjust += 2; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index acda841979eb..75f4fb2fcde5 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -66,6 +66,47 @@ static const unsigned char tolower_map[256] = { #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)]) +/* ctype's isalpha varies based on locale, which is not what we want for many use cases. + * This is what it'd be in the "C" locale. */ +ZEND_API const bool zend_isalpha_map[256] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +/* ctype's isalnum is isalpha + isdigit(0-9) */ +ZEND_API const bool zend_isalnum_map[256] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + /** * Functions using locale lowercase: zend_binary_strncasecmp_l diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index d543b7b03c2b..dc16aaa30a33 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -414,6 +414,13 @@ ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2); +/* NOTE: The locale-independent alternatives to ctype(isalpha/isalnum) were added to fix bugs in php 7.3 patch releases, and should not be used externally until php 8.2 */ +ZEND_API extern const bool zend_isalpha_map[256]; +ZEND_API extern const bool zend_isalnum_map[256]; + +#define zend_isalpha_ascii(c) (zend_isalpha_map[(unsigned char)(c)]) +#define zend_isalnum_ascii(c) (zend_isalnum_map[(unsigned char)(c)]) + ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length); ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length); ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length); diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index dfaa95932c3b..4c9b879961de 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -82,7 +82,7 @@ typedef unsigned short mode_t; #define IS_UNC_PATH(path, len) \ (len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1])) #define IS_ABSOLUTE_PATH(path, len) \ - (len >= 2 && (/* is local */isalpha(path[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1]))) + (len >= 2 && (/* is local */zend_isalpha_ascii(path[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1]))) #else #ifdef HAVE_DIRENT_H diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 1bf7c00d13c6..73fb5c7e387b 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -520,21 +520,21 @@ static int _php_filter_validate_domain(char * domain, int len, zend_long flags) } /* First char must be alphanumeric */ - if(*s == '.' || (hostname && !isalnum((int)*(unsigned char *)s))) { + if(*s == '.' || (hostname && !zend_isalnum_ascii((int)*(unsigned char *)s))) { return 0; } while (s < e) { if (*s == '.') { /* The first and the last character of a label must be alphanumeric */ - if (*(s + 1) == '.' || (hostname && (!isalnum((int)*(unsigned char *)(s - 1)) || !isalnum((int)*(unsigned char *)(s + 1))))) { + if (*(s + 1) == '.' || (hostname && (!zend_isalnum_ascii((int)*(unsigned char *)(s - 1)) || !zend_isalnum_ascii((int)*(unsigned char *)(s + 1))))) { return 0; } /* Reset label length counter */ i = 1; } else { - if (i > 63 || (hostname && *s != '-' && !isalnum((int)*(unsigned char *)s))) { + if (i > 63 || (hostname && *s != '-' && !zend_isalnum_ascii((int)*(unsigned char *)s))) { return 0; } @@ -561,7 +561,7 @@ static int is_userinfo_valid(zend_string *str) const char *valid = "-._~!$&'()*+,;=:"; const char *p = ZSTR_VAL(str); while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) { - if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) { + if (zend_isalnum_ascii(*p) || strchr(valid, *p)) { p++; } else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) { p += 3; diff --git a/ext/filter/tests/filter_validate_domain_locale.phpt b/ext/filter/tests/filter_validate_domain_locale.phpt new file mode 100644 index 000000000000..2e8ad014491e --- /dev/null +++ b/ext/filter/tests/filter_validate_domain_locale.phpt @@ -0,0 +1,19 @@ +--TEST-- +FILTER_VALIDATE_DOMAIN FILTER_FLAG_HOSTNAME should not be locale dependent +--EXTENSIONS-- +filter +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(false) +bool(false) diff --git a/ext/standard/tests/streams/locale.phpt b/ext/standard/tests/streams/locale.phpt new file mode 100644 index 000000000000..40f024300517 --- /dev/null +++ b/ext/standard/tests/streams/locale.phpt @@ -0,0 +1,26 @@ +--TEST-- +Stream wrappers should not be locale dependent +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +display_errors=stderr +--FILE-- + +--EXPECTF-- +Warning: stream_wrapper_register(): Invalid protocol scheme specified. Unable to register wrapper class testwrapper to test٪:// in %s on line 6 +bool(false) +stream_open: Warning: fopen(test٪://test): Failed to open stream: No such file or directory in %s on line 9 diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 39a9c82d5984..41523ca465a5 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -481,7 +481,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt } /* Don't resolve paths which contain protocol (except of file://) */ - for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + for (p = filename; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) { wrapper = php_stream_locate_url_wrapper(filename, &actual_path, STREAM_OPEN_FOR_INCLUDE); if (wrapper == &php_plain_files_wrapper) { @@ -517,7 +517,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt /* Check for stream wrapper */ int is_stream_wrapper = 0; - for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + for (p = ptr; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - ptr > 1) && (p[1] == '/') && (p[2] == '/')) { /* .:// or ..:// is not a stream wrapper */ if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) { @@ -586,7 +586,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt actual_path = trypath; /* Check for stream wrapper */ - for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + for (p = trypath; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - trypath > 1) && (p[1] == '/') && (p[2] == '/')) { wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE); if (!wrapper) { diff --git a/main/streams/streams.c b/main/streams/streams.c index 7e023e4593f1..3b222c87d394 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1724,7 +1724,7 @@ static inline int php_stream_wrapper_scheme_validate(const char *protocol, unsig unsigned int i; for(i = 0; i < protocol_len; i++) { - if (!isalnum((int)protocol[i]) && + if (!zend_isalnum_ascii((int)protocol[i]) && protocol[i] != '+' && protocol[i] != '-' && protocol[i] != '.') { @@ -1804,7 +1804,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const return (php_stream_wrapper*)((options & STREAM_LOCATE_WRAPPERS_ONLY) ? NULL : &php_plain_files_wrapper); } - for (p = path; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + for (p = path; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { n++; } diff --git a/main/streams/transports.c b/main/streams/transports.c index fcc3f293300e..13bffa72361c 100644 --- a/main/streams/transports.c +++ b/main/streams/transports.c @@ -93,7 +93,7 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in } } - for (p = name; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + for (p = name; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { n++; } From 0e8d196be06117897c4da135bca97c77338e44f5 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Tue, 28 Dec 2021 11:27:22 -0500 Subject: [PATCH 2/3] Address review comments --- Zend/zend_operators.c | 21 ------------------- Zend/zend_operators.h | 10 ++++++--- .../tests/filter_validate_domain_locale.phpt | 6 +++--- ext/standard/tests/streams/locale.phpt | 6 +++--- 4 files changed, 13 insertions(+), 30 deletions(-) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 75f4fb2fcde5..f001e31dae7e 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -66,27 +66,6 @@ static const unsigned char tolower_map[256] = { #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)]) -/* ctype's isalpha varies based on locale, which is not what we want for many use cases. - * This is what it'd be in the "C" locale. */ -ZEND_API const bool zend_isalpha_map[256] = { -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, -0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -}; - /* ctype's isalnum is isalpha + isdigit(0-9) */ ZEND_API const bool zend_isalnum_map[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index dc16aaa30a33..3b9dd801b4ec 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -414,11 +414,15 @@ ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2); ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2); -/* NOTE: The locale-independent alternatives to ctype(isalpha/isalnum) were added to fix bugs in php 7.3 patch releases, and should not be used externally until php 8.2 */ -ZEND_API extern const bool zend_isalpha_map[256]; +/* NOTE: The locale-independent alternatives to ctype(isalpha/isalnum) were added to fix bugs in php 8.0 patch releases, and should not be used externally until php 8.2 */ ZEND_API extern const bool zend_isalnum_map[256]; -#define zend_isalpha_ascii(c) (zend_isalpha_map[(unsigned char)(c)]) +static zend_always_inline bool zend_isalpha_ascii(unsigned char c) { + /* Returns true for a-z and A-Z in a locale-independent way. + * This is implemented in a way that can avoid branching. Note that ASCII 'a' == 'A' | 0x20. */ + c = (c | 0x20) - 'a'; + return c <= ('z' - 'a' + 1); +} #define zend_isalnum_ascii(c) (zend_isalnum_map[(unsigned char)(c)]) ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length); diff --git a/ext/filter/tests/filter_validate_domain_locale.phpt b/ext/filter/tests/filter_validate_domain_locale.phpt index 2e8ad014491e..2fff716298f2 100644 --- a/ext/filter/tests/filter_validate_domain_locale.phpt +++ b/ext/filter/tests/filter_validate_domain_locale.phpt @@ -4,14 +4,14 @@ FILTER_VALIDATE_DOMAIN FILTER_FLAG_HOSTNAME should not be locale dependent filter --SKIPIF-- --FILE-- --EXPECT-- diff --git a/ext/standard/tests/streams/locale.phpt b/ext/standard/tests/streams/locale.phpt index 40f024300517..602fef56141a 100644 --- a/ext/standard/tests/streams/locale.phpt +++ b/ext/standard/tests/streams/locale.phpt @@ -2,8 +2,8 @@ Stream wrappers should not be locale dependent --SKIPIF-- --INI-- @@ -11,7 +11,7 @@ allow_url_fopen=1 display_errors=stderr --FILE-- Date: Wed, 29 Dec 2021 09:41:15 -0500 Subject: [PATCH 3/3] Address review comments --- Zend/zend_compile.c | 2 +- Zend/zend_operators.h | 2 +- ext/filter/logical_filters.c | 6 +++--- main/fopen_wrappers.c | 6 +++--- main/streams/streams.c | 4 ++-- main/streams/transports.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4a93beea86b7..c20f625b1206 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1941,7 +1941,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len) /* Note that on Win32 CWD is per drive (heritage from CP/M). * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive. */ - if ((2 <= len) && zend_isalpha_ascii((int)((unsigned char *)path)[0]) && (':' == path[1])) { + if ((2 <= len) && zend_isalpha_ascii(((unsigned char *)path)[0]) && (':' == path[1])) { /* Skip over the drive spec (if any) so as not to change */ path += 2; len_adjust += 2; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 3b9dd801b4ec..3082338647a7 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -421,7 +421,7 @@ static zend_always_inline bool zend_isalpha_ascii(unsigned char c) { /* Returns true for a-z and A-Z in a locale-independent way. * This is implemented in a way that can avoid branching. Note that ASCII 'a' == 'A' | 0x20. */ c = (c | 0x20) - 'a'; - return c <= ('z' - 'a' + 1); + return c <= ('z' - 'a'); } #define zend_isalnum_ascii(c) (zend_isalnum_map[(unsigned char)(c)]) diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 73fb5c7e387b..035ca5d6a4d9 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -520,21 +520,21 @@ static int _php_filter_validate_domain(char * domain, int len, zend_long flags) } /* First char must be alphanumeric */ - if(*s == '.' || (hostname && !zend_isalnum_ascii((int)*(unsigned char *)s))) { + if(*s == '.' || (hostname && !zend_isalnum_ascii(*(unsigned char *)s))) { return 0; } while (s < e) { if (*s == '.') { /* The first and the last character of a label must be alphanumeric */ - if (*(s + 1) == '.' || (hostname && (!zend_isalnum_ascii((int)*(unsigned char *)(s - 1)) || !zend_isalnum_ascii((int)*(unsigned char *)(s + 1))))) { + if (*(s + 1) == '.' || (hostname && (!zend_isalnum_ascii(*(unsigned char *)(s - 1)) || !zend_isalnum_ascii(*(unsigned char *)(s + 1))))) { return 0; } /* Reset label length counter */ i = 1; } else { - if (i > 63 || (hostname && *s != '-' && !zend_isalnum_ascii((int)*(unsigned char *)s))) { + if (i > 63 || (hostname && *s != '-' && !zend_isalnum_ascii(*(unsigned char *)s))) { return 0; } diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 41523ca465a5..fe424cd8c780 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -481,7 +481,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt } /* Don't resolve paths which contain protocol (except of file://) */ - for (p = filename; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + for (p = filename; zend_isalnum_ascii(*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) { wrapper = php_stream_locate_url_wrapper(filename, &actual_path, STREAM_OPEN_FOR_INCLUDE); if (wrapper == &php_plain_files_wrapper) { @@ -517,7 +517,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt /* Check for stream wrapper */ int is_stream_wrapper = 0; - for (p = ptr; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + for (p = ptr; zend_isalnum_ascii(*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - ptr > 1) && (p[1] == '/') && (p[2] == '/')) { /* .:// or ..:// is not a stream wrapper */ if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) { @@ -586,7 +586,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt actual_path = trypath; /* Check for stream wrapper */ - for (p = trypath; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + for (p = trypath; zend_isalnum_ascii(*p) || *p == '+' || *p == '-' || *p == '.'; p++); if ((*p == ':') && (p - trypath > 1) && (p[1] == '/') && (p[2] == '/')) { wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE); if (!wrapper) { diff --git a/main/streams/streams.c b/main/streams/streams.c index 3b222c87d394..d3a94fe3ffc5 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1724,7 +1724,7 @@ static inline int php_stream_wrapper_scheme_validate(const char *protocol, unsig unsigned int i; for(i = 0; i < protocol_len; i++) { - if (!zend_isalnum_ascii((int)protocol[i]) && + if (!zend_isalnum_ascii(protocol[i]) && protocol[i] != '+' && protocol[i] != '-' && protocol[i] != '.') { @@ -1804,7 +1804,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const return (php_stream_wrapper*)((options & STREAM_LOCATE_WRAPPERS_ONLY) ? NULL : &php_plain_files_wrapper); } - for (p = path; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + for (p = path; zend_isalnum_ascii(*p) || *p == '+' || *p == '-' || *p == '.'; p++) { n++; } diff --git a/main/streams/transports.c b/main/streams/transports.c index 13bffa72361c..643675965e78 100644 --- a/main/streams/transports.c +++ b/main/streams/transports.c @@ -93,7 +93,7 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in } } - for (p = name; zend_isalnum_ascii((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + for (p = name; zend_isalnum_ascii(*p) || *p == '+' || *p == '-' || *p == '.'; p++) { n++; }