diff options
author | Tony Cook <tony@develop-help.com> | 2015-12-16 11:13:30 +1100 |
---|---|---|
committer | Ricardo Signes <rjbs@cpan.org> | 2016-01-11 08:01:48 -0500 |
commit | 52236464559c6e410a4587d3c6da9639e75f3ec1 (patch) | |
tree | 91f97467e5bf793e22e03cbd278686df42de42d7 /win32/vdir.h | |
parent | 130509aa42a87eef258fab0182ee2c7ad16baa8b (diff) | |
download | perl-52236464559c6e410a4587d3c6da9639e75f3ec1.tar.gz |
avoid invalid memory access in MapPath[AW]
This issue was assigned CVE-2015-8608. [perl #126755]
Diffstat (limited to 'win32/vdir.h')
-rw-r--r-- | win32/vdir.h | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/win32/vdir.h b/win32/vdir.h index 42c306b779..b5c6bc6f45 100644 --- a/win32/vdir.h +++ b/win32/vdir.h @@ -15,6 +15,7 @@ * and one additional slot for a UNC name */ const int driveCount = ('Z'-'A')+1+1; +const int driveLetterCount = ('Z'-'A')+1; class VDir { @@ -383,6 +384,7 @@ char *VDir::MapPathA(const char *pInName) * possiblities -- relative path or absolute path with or without drive letter * OR UNC name */ + int driveIndex; char szBuffer[(MAX_PATH+1)*2]; char szlBuf[MAX_PATH+1]; int length = strlen(pInName); @@ -402,15 +404,18 @@ char *VDir::MapPathA(const char *pInName) } /* strlen(pInName) is now <= MAX_PATH */ - if (pInName[1] == ':') { + if (length > 1 && pInName[1] == ':') { /* has drive letter */ - if (IsPathSep(pInName[2])) { + if (length > 2 && IsPathSep(pInName[2])) { /* absolute with drive letter */ DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA); } else { /* relative path with drive letter */ - strcpy(szBuffer, GetDirA(DriveIndex(*pInName))); + driveIndex = DriveIndex(*pInName); + if (driveIndex < 0 || driveIndex >= driveLetterCount) + return (char *)pInName; + strcpy(szBuffer, GetDirA(driveIndex)); strcat(szBuffer, &pInName[2]); if(strlen(szBuffer) > MAX_PATH) szBuffer[MAX_PATH] = '\0'; @@ -420,7 +425,7 @@ char *VDir::MapPathA(const char *pInName) } else { /* no drive letter */ - if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { + if (length > 1 && IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { /* UNC name */ DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA); } @@ -611,6 +616,7 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName) * possiblities -- relative path or absolute path with or without drive letter * OR UNC name */ + int driveIndex; WCHAR szBuffer[(MAX_PATH+1)*2]; WCHAR szlBuf[MAX_PATH+1]; int length = wcslen(pInName); @@ -630,7 +636,7 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName) } /* strlen(pInName) is now <= MAX_PATH */ - if (pInName[1] == ':') { + if (length > 1 && pInName[1] == ':') { /* has drive letter */ if (IsPathSep(pInName[2])) { /* absolute with drive letter */ @@ -638,7 +644,10 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName) } else { /* relative path with drive letter */ - wcscpy(szBuffer, GetDirW(DriveIndex((char)*pInName))); + driveIndex = DriveIndex(*pInName); + if (driveIndex < 0 || driveIndex >= driveLetterCount) + return (WCHAR *)pInName; + wcscpy(szBuffer, GetDirW(driveIndex)); wcscat(szBuffer, &pInName[2]); if(wcslen(szBuffer) > MAX_PATH) szBuffer[MAX_PATH] = '\0'; @@ -648,7 +657,7 @@ WCHAR* VDir::MapPathW(const WCHAR *pInName) } else { /* no drive letter */ - if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { + if (length > 1 && IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { /* UNC name */ DoGetFullPathNameW((WCHAR*)pInName, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); } |