]> granicus.if.org Git - php/commitdiff
rework long path normalization stuf
authorAnatol Belski <ab@php.net>
Sun, 24 Jul 2016 01:43:17 +0000 (03:43 +0200)
committerAnatol Belski <ab@php.net>
Sun, 24 Jul 2016 01:51:47 +0000 (03:51 +0200)
Simplify, set error codes, ensure 32-bit is ok as well. The
canonicalization part is still an issue on win7 as the API
is missing there. However a partial improvement is reached
there as well thanks to the slash conversion.

win32/ioutil.c
win32/ioutil.h

index 1bf88c44b8d7ff6b92ea91d246ee9e0ce2ac8a8b..fc4413b2dd7dbad52da470a4f705e599b159cfad 100644 (file)
@@ -66,7 +66,7 @@
 #include <winnls.h>
 */
 
-typedef HRESULT (WINAPI *MyPathCchCanonicalizeEx)(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags);
+typedef HRESULT (__stdcall *MyPathCchCanonicalizeEx)(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags);
 
 static MyPathCchCanonicalizeEx canonicalize_path_w = NULL;
 
@@ -506,14 +506,14 @@ PW32IO size_t php_win32_ioutil_dirname(char *path, size_t len)
        return ret_len;
 }/*}}}*/
 
-PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len)
+PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len)
 {/*{{{*/
        wchar_t *pos, *idx = *buf, canonicalw[MAXPATHLEN];
-       size_t ret_len = len, canonicalw_len, shift;
+       size_t ret_len = len;
 
        if (len >= MAXPATHLEN) {
-               SET_ERRNO_FROM_WIN32_CODE(ERROR_BUFFER_OVERFLOW);
-               return FALSE;
+               SET_ERRNO_FROM_WIN32_CODE(ERROR_BAD_LENGTH);
+               return PHP_WIN32_IOUTIL_NORM_FAIL;
        }
 
        while (NULL != (pos = wcschr(idx, PHP_WIN32_IOUTIL_FW_SLASHW)) && idx - *buf <= len) {
@@ -521,30 +521,29 @@ PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t
                idx = pos++;
        }
 
-       shift = PHP_WIN32_IOUTIL_IS_LONG_PATHW(*buf, len) ? PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW : 0;
-       if (S_OK != canonicalize_path_w(canonicalw, MAXPATHLEN, *buf + shift, PATHCCH_ALLOW_LONG_PATHS)) {
-               *new_len = ret_len;
-               return FALSE;
+       if (S_OK != canonicalize_path_w(canonicalw, MAXPATHLEN, *buf, PATHCCH_ALLOW_LONG_PATHS)) {
+               return PHP_WIN32_IOUTIL_NORM_PARTIAL;
        }
-       canonicalw_len = wcslen(canonicalw);
-       if (canonicalw_len + shift != len) {
-               if (canonicalw_len > len) {
-                       *buf = realloc(*buf, (canonicalw_len + 1) * sizeof(wchar_t));
+       ret_len = wcslen(canonicalw);
+       if (ret_len != len) {
+               if (ret_len > len) {
+                       wchar_t *tmp = realloc(*buf, (ret_len + 1) * sizeof(wchar_t));
+                       if (!tmp) {
+                               SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY);
+                               return PHP_WIN32_IOUTIL_NORM_PARTIAL;
+                       }
+                       *buf = tmp;
                }
-               memmove(*buf + shift, canonicalw, (canonicalw_len + 1) * sizeof(wchar_t));
-               ret_len = canonicalw_len + shift;
+               memmove(*buf, canonicalw, (ret_len + 1) * sizeof(wchar_t));
        }
        *new_len = ret_len;
 
-       return TRUE;
+       return PHP_WIN32_IOUTIL_NORM_OK;
 }/*}}}*/
 
-static HRESULT MyPathCchCanonicalizeExFallback(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags)
+static HRESULT __stdcall MyPathCchCanonicalizeExFallback(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags)
 {/*{{{*/
-       cchPathOut = wcslen(pszPathIn);
-       memmove(pszPathOut, pszPathIn, (cchPathOut + 1) * sizeof(wchar_t));
-
-       return S_OK;
+       return -42;
 }/*}}}*/
 
 BOOL php_win32_ioutil_init(void)
index a11c64912e412e9ac051e291617444a604059763..a97bbd7f56fba08e55e0bcaa8a582610f45f6684 100644 (file)
@@ -87,6 +87,11 @@ typedef enum {
        PHP_WIN32_IOUTIL_IS_UTF8
 } php_win32_ioutil_encoding;
 
+typedef enum {
+       PHP_WIN32_IOUTIL_NORM_OK,
+       PHP_WIN32_IOUTIL_NORM_PARTIAL,
+       PHP_WIN32_IOUTIL_NORM_FAIL,
+} php_win32_ioutil_normalization_result;
 
 #define PHP_WIN32_IOUTIL_FW_SLASHW L'/'
 #define PHP_WIN32_IOUTIL_FW_SLASH '/'
@@ -133,7 +138,7 @@ typedef enum {
                } \
 } while (0);
 
-PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
+PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
 #ifdef PHP_EXPORTS
 /* This symbols are needed only for the DllMain, but should not be exported 
        or be available when used with PHP binaries. */
@@ -160,6 +165,11 @@ __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, siz
                        return NULL;
                }
 
+               /* The return can be ignored here, as the normalization can fail for
+                  various reasons not directly related to the operation itself.
+                  Partial normalization could still do a better job further. And
+                  otherwise, the path might be unchanged which is ok if the path
+                  was valid long one. */
                (void)php_win32_ioutil_normalize_path_w(&mb, mb_len, &mb_len);
 
                if (PHP_WIN32_IOUTIL_IS_LONG_PATHW(mb, mb_len)) {