ICU-12798 directory traversal code assumes that path length is less than PATH_MAX
X-SVN-Rev: 39468
This commit is contained in:
parent
a8e45e3d32
commit
16b73a36ca
@ -834,7 +834,6 @@ static const char* remapShortTimeZone(const char *stdID, const char *dstID, int3
|
||||
#endif
|
||||
|
||||
#ifdef SEARCH_TZFILE
|
||||
#define MAX_PATH_SIZE PATH_MAX /* Set the limit for the size of the path. */
|
||||
#define MAX_READ_SIZE 512
|
||||
|
||||
typedef struct DefaultTZInfo {
|
||||
@ -910,15 +909,19 @@ static UBool compareBinaryFiles(const char* defaultTZFileName, const char* TZFil
|
||||
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
* This method recursively traverses the directory given for a matching TZ file and returns the first match.
|
||||
*/
|
||||
|
||||
|
||||
/* dirent also lists two entries: "." and ".." that we can safely ignore. */
|
||||
#define SKIP1 "."
|
||||
#define SKIP2 ".."
|
||||
static char SEARCH_TZFILE_RESULT[MAX_PATH_SIZE] = "";
|
||||
static UBool U_CALLCONV putil_cleanup(void);
|
||||
static CharString *gSearchTZFileResult = NULL;
|
||||
|
||||
/*
|
||||
* This method recursively traverses the directory given for a matching TZ file and returns the first match.
|
||||
* This function is not thread safe - it uses a global, gSearchTZFileResult, to hold its results.
|
||||
*/
|
||||
static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) {
|
||||
char curpath[MAX_PATH_SIZE];
|
||||
DIR* dirp = opendir(path);
|
||||
DIR* subDirp = NULL;
|
||||
struct dirent* dirEntry = NULL;
|
||||
@ -928,24 +931,40 @@ static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (gSearchTZFileResult == NULL) {
|
||||
gSearchTZFileResult = new CharString;
|
||||
if (gSearchTZFileResult == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
|
||||
}
|
||||
|
||||
/* Save the current path */
|
||||
uprv_memset(curpath, 0, MAX_PATH_SIZE);
|
||||
uprv_strcpy(curpath, path);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
CharString curpath(path, -1, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check each entry in the directory. */
|
||||
while((dirEntry = readdir(dirp)) != NULL) {
|
||||
const char* dirName = dirEntry->d_name;
|
||||
if (uprv_strcmp(dirName, SKIP1) != 0 && uprv_strcmp(dirName, SKIP2) != 0) {
|
||||
/* Create a newpath with the new entry to test each entry in the directory. */
|
||||
char newpath[MAX_PATH_SIZE];
|
||||
uprv_strcpy(newpath, curpath);
|
||||
uprv_strcat(newpath, dirName);
|
||||
CharString newpath(curpath, status);
|
||||
newpath.append(dirName, -1, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((subDirp = opendir(newpath)) != NULL) {
|
||||
if ((subDirp = opendir(newpath.data())) != NULL) {
|
||||
/* If this new path is a directory, make a recursive call with the newpath. */
|
||||
closedir(subDirp);
|
||||
uprv_strcat(newpath, "/");
|
||||
result = searchForTZFile(newpath, tzInfo);
|
||||
newpath.append('/', status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
result = searchForTZFile(newpath.data(), tzInfo);
|
||||
/*
|
||||
Have to get out here. Otherwise, we'd keep looking
|
||||
and return the first match in the top-level directory
|
||||
@ -957,11 +976,19 @@ static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) {
|
||||
if (result != NULL)
|
||||
break;
|
||||
} else if (uprv_strcmp(TZFILE_SKIP, dirName) != 0 && uprv_strcmp(TZFILE_SKIP2, dirName) != 0) {
|
||||
if(compareBinaryFiles(TZDEFAULT, newpath, tzInfo)) {
|
||||
const char* zoneid = newpath + (sizeof(TZZONEINFO)) - 1;
|
||||
if(compareBinaryFiles(TZDEFAULT, newpath.data(), tzInfo)) {
|
||||
int32_t amountToSkip = sizeof(TZZONEINFO) - 1;
|
||||
if (amountToSkip > newpath.length()) {
|
||||
amountToSkip = newpath.length();
|
||||
}
|
||||
const char* zoneid = newpath.data() + amountToSkip;
|
||||
skipZoneIDPrefix(&zoneid);
|
||||
uprv_strcpy(SEARCH_TZFILE_RESULT, zoneid);
|
||||
result = SEARCH_TZFILE_RESULT;
|
||||
gSearchTZFileResult->clear();
|
||||
gSearchTZFileResult->append(zoneid, -1, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
result = gSearchTZFileResult->data();
|
||||
/* Get out after the first one found. */
|
||||
break;
|
||||
}
|
||||
@ -1150,6 +1177,9 @@ static UBool U_CALLCONV putil_cleanup(void)
|
||||
gTimeZoneFilesDirectory = NULL;
|
||||
gTimeZoneFilesInitOnce.reset();
|
||||
|
||||
delete gSearchTZFileResult;
|
||||
gSearchTZFileResult = NULL;
|
||||
|
||||
#if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API
|
||||
if (gCorrectedPOSIXLocale) {
|
||||
uprv_free(gCorrectedPOSIXLocale);
|
||||
|
@ -6,6 +6,7 @@
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#include "unicode/platform.h"
|
||||
#if U_PLATFORM == U_PF_MINGW
|
||||
// *cough* - for struct stat
|
||||
#ifdef __STRICT_ANSI__
|
||||
@ -15,6 +16,7 @@
|
||||
|
||||
#include "filetools.h"
|
||||
#include "filestrm.h"
|
||||
#include "charstr.h"
|
||||
#include "cstring.h"
|
||||
#include "unicode/putil.h"
|
||||
#include "putilimp.h"
|
||||
@ -29,8 +31,6 @@
|
||||
#include <dirent.h>
|
||||
typedef struct dirent DIRENT;
|
||||
|
||||
#define MAX_PATH_SIZE 4096 /* Set the limit for the size of the path. */
|
||||
|
||||
#define SKIP1 "."
|
||||
#define SKIP2 ".."
|
||||
#endif
|
||||
@ -58,20 +58,24 @@ isFileModTimeLater(const char *filePath, const char *checkAgainst, UBool isDir)
|
||||
|
||||
while ((dirEntry = readdir(pDir)) != NULL) {
|
||||
if (uprv_strcmp(dirEntry->d_name, SKIP1) != 0 && uprv_strcmp(dirEntry->d_name, SKIP2) != 0) {
|
||||
char newpath[MAX_PATH_SIZE] = "";
|
||||
uprv_strcpy(newpath, checkAgainst);
|
||||
uprv_strcat(newpath, U_FILE_SEP_STRING);
|
||||
uprv_strcat(newpath, dirEntry->d_name);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::CharString newpath(checkAgainst, -1, status);
|
||||
newpath.append(U_FILE_SEP_STRING, -1, status);
|
||||
newpath.append(dirEntry->d_name, -1, status);
|
||||
if (U_FAILURE(status)) {
|
||||
fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, u_errorName(status));
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
if ((subDirp = opendir(newpath)) != NULL) {
|
||||
if ((subDirp = opendir(newpath.data())) != NULL) {
|
||||
/* If this new path is a directory, make a recursive call with the newpath. */
|
||||
closedir(subDirp);
|
||||
isLatest = isFileModTimeLater(filePath, newpath, isDir);
|
||||
isLatest = isFileModTimeLater(filePath, newpath.data(), isDir);
|
||||
if (!isLatest) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int32_t latest = whichFileModTimeIsLater(filePath, newpath);
|
||||
int32_t latest = whichFileModTimeIsLater(filePath, newpath.data());
|
||||
if (latest < 0 || latest == 2) {
|
||||
isLatest = FALSE;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user