diff --git a/NEWS b/NEWS index f6b866b7bcd..f162756d4c5 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ PHP NEWS . Fixed bug GH-16344 (setRawValueWithoutLazyInitialization() and skipLazyInitialization() may change initialized proxy). (Arnaud) . Fix is_zend_ptr() huge block comparison. (nielsdos) + . Fixed potential OOB read in zend_dirname() on Windows. (cmb) - Curl: . Fix various memory leaks in curl mime handling. (nielsdos) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 15ff271c103..2d1a50191ff 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2201,7 +2201,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len) } /* Strip trailing slashes */ - while (end >= path && IS_SLASH_P(end)) { + while (end >= path && IS_SLASH_P_EX(end, end == path)) { end--; } if (end < path) { @@ -2212,7 +2212,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len) } /* Strip filename */ - while (end >= path && !IS_SLASH_P(end)) { + while (end >= path && !IS_SLASH_P_EX(end, end == path)) { end--; } if (end < path) { @@ -2223,7 +2223,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len) } /* Strip slashes which came before the file name */ - while (end >= path && IS_SLASH_P(end)) { + while (end >= path && IS_SLASH_P_EX(end, end == path)) { end--; } if (end < path) { diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index 0fc27991186..21735f6dfae 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -75,8 +75,11 @@ typedef unsigned short mode_t; #define DEFAULT_SLASH '\\' #define DEFAULT_DIR_SEPARATOR ';' #define IS_SLASH(c) ((c) == '/' || (c) == '\\') +// IS_SLASH_P() may read the previous char on Windows, which may be OOB; use IS_SLASH_P_EX() instead #define IS_SLASH_P(c) (*(c) == '/' || \ (*(c) == '\\' && !IsDBCSLeadByte(*(c-1)))) +#define IS_SLASH_P_EX(c, first_byte) (*(c) == '/' || \ + (*(c) == '\\' && ((first_byte) || !IsDBCSLeadByte(*(c-1))))) /* COPY_WHEN_ABSOLUTE is 2 under Win32 because by chance both regular absolute paths in the file system and UNC paths need copying of two characters */ @@ -110,7 +113,9 @@ typedef unsigned short mode_t; #endif #define IS_SLASH(c) ((c) == '/') +// IS_SLASH_P() may read the previous char on Windows, which may be OOB; use IS_SLASH_P_EX() instead #define IS_SLASH_P(c) (*(c) == '/') +#define IS_SLASH_P_EX(c, first_byte) IS_SLASH_P(c) #endif