From f22ef10cc0de08c55f8dffbda3a26aba8580b909 Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Thu, 11 Dec 2003 07:21:36 +0000 Subject: [PATCH] ICU-3008 improve udata path name buffer overflow handling X-SVN-Rev: 14098 --- icu4c/source/common/udata.c | 103 +++++++++++++++++++++----- icu4c/source/test/cintltst/udatatst.c | 4 +- 2 files changed, 88 insertions(+), 19 deletions(-) diff --git a/icu4c/source/common/udata.c b/icu4c/source/common/udata.c index 67f0bf5e7e3..cbb5e2f7f75 100644 --- a/icu4c/source/common/udata.c +++ b/icu4c/source/common/udata.c @@ -313,6 +313,61 @@ static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UEr +/*------------------------------------------------------------------------------- + * + * TinyString - a small set of really simple string functions, for + * the purpose of consolidating buffer overflow code in one place + * + * Use wherever you would otherwise declare a fixed sized char[xx] buffer. + * Do non-growing ops by accessing fields of struct directly + * Grow using the append function to automatically extend buffer + * as needed. + * + *-------------------------------------------------------------------------------*/ +typedef struct TinyString { + char *s; + int32_t length; + char fStaticBuf[100]; + int32_t fCapacity; +} TinyString; + +static TinyString_init(TinyString *This) { + This->s = This->fStaticBuf; + *This->s = 0; + This->length = 0; + This->fCapacity = sizeof(This->fStaticBuf)-1; +} + +static TinyString_append(TinyString *This, const char *what) { + int32_t newLen; + newLen = This->length + uprv_strlen(what); + if (newLen >= This->fCapacity) { + int32_t newCapacity = newLen * 2; + char *newBuf = (char *)uprv_malloc(newCapacity+1); + if (newBuf != NULL) { + uprv_strcpy(newBuf, This->s); + if (This->s != This->fStaticBuf) { + uprv_free(This->s); + } + This->s = newBuf; + This->fCapacity = newCapacity; + } + } + if (newLen < This->fCapacity) { + uprv_strcat(This->s, what); + This->length = newLen; + } +} + +static TinyString_dt(TinyString *This) { + if (This->s != This->fStaticBuf) { + uprv_free(This->s); + } + TinyString_init(This); +} + + + /*----------------------------------------------------------------------*============== * * @@ -930,15 +985,18 @@ doOpenChoice(const char *path, const char *type, const char *name, UDataMemoryIsAcceptable *isAcceptable, void *context, UErrorCode *pErrorCode) { - UDataPathIterator iter; - const char *pathBuffer; + UDataMemory *retVal = NULL; - char tocEntryName[100]; + UDataPathIterator iter; + const char *pathBuffer; + + TinyString tocEntryName; char oldStylePath[1024]; char oldStylePathBasename[100]; const char *dataPath; const char *tocEntrySuffix; + int32_t tocEntrySuffixIndex; UDataMemory dataMemory; UDataMemory *pCommonData; UDataMemory *pEntryData; @@ -951,20 +1009,21 @@ doOpenChoice(const char *path, const char *type, const char *name, */ /* prepend the package */ - uprv_strcpy(tocEntryName, packageNameFromPath(path)); + TinyString_init(&tocEntryName); + TinyString_append(&tocEntryName, packageNameFromPath(path)); - tocEntrySuffix = tocEntryName+uprv_strlen(tocEntryName); /* suffix starts here */ + tocEntrySuffixIndex = tocEntryName.length; - uprv_strcat(tocEntryName, "_"); - - uprv_strcat(tocEntryName, name); + TinyString_append(&tocEntryName, "_"); + TinyString_append(&tocEntryName, name); if(type!=NULL && *type!=0) { - uprv_strcat(tocEntryName, "."); - uprv_strcat(tocEntryName, type); + TinyString_append(&tocEntryName, "."); + TinyString_append(&tocEntryName, type); } + tocEntrySuffix = tocEntryName.s+tocEntrySuffixIndex; /* suffix starts here */ #ifdef UDATA_DEBUG - fprintf(stderr, " tocEntryName = %s\n", tocEntryName); + fprintf(stderr, " tocEntryName = %s\n", tocEntryName->s); #endif @@ -1006,7 +1065,8 @@ doOpenChoice(const char *path, const char *type, const char *name, path = oldStylePath; } else { *pErrorCode = U_FILE_ACCESS_ERROR; /* hopelessly bad case */ - return NULL; + retVal = NULL; + goto commonReturn; } } /* End of dealing with a null basename */ @@ -1037,7 +1097,8 @@ doOpenChoice(const char *path, const char *type, const char *name, fprintf(stderr, "** Mapped file: %s\n", pathBuffer); #endif udata_pathiter_dt(&iter); - return pEntryData; + retVal = pEntryData; + goto commonReturn; } /* the data is not acceptable, or some error occured. Either way, unmap the memory */ @@ -1046,7 +1107,8 @@ doOpenChoice(const char *path, const char *type, const char *name, /* If we had a nasty error, bail out completely. */ if (U_FAILURE(*pErrorCode)) { udata_pathiter_dt(&iter); - return NULL; + retVal = NULL; + goto commonReturn; } /* Otherwise remember that we found data but didn't like it for some reason */ @@ -1076,7 +1138,7 @@ doOpenChoice(const char *path, const char *type, const char *name, int32_t length; /* look up the data piece in the common data */ - pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &length, &errorCode); + pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName.s, &length, &errorCode); #ifdef UDATA_DEBUG fprintf(stderr, "pHeader=%p\n", pHeader); #endif @@ -1086,11 +1148,13 @@ doOpenChoice(const char *path, const char *type, const char *name, fprintf(stderr, "pEntryData=%p\n", pEntryData); #endif if (U_FAILURE(*pErrorCode)) { - return NULL; + retVal = NULL; + goto commonReturn; } if (pEntryData != NULL) { pEntryData->length = length; - return pEntryData; + retVal = pEntryData; + goto commonReturn; } } } @@ -1112,7 +1176,10 @@ doOpenChoice(const char *path, const char *type, const char *name, *pErrorCode=errorCode; } } - return NULL; + +commonReturn: + TinyString_dt(&tocEntryName); + return retVal; } diff --git a/icu4c/source/test/cintltst/udatatst.c b/icu4c/source/test/cintltst/udatatst.c index 2ea20c255c8..b5198af957e 100644 --- a/icu4c/source/test/cintltst/udatatst.c +++ b/icu4c/source/test/cintltst/udatatst.c @@ -109,6 +109,8 @@ static void TestUDataOpen(){ const char* name = "test"; const char* type = "icu"; const char dirSepString[] = {U_FILE_SEP_CHAR, 0}; + const char pathSepString[] = {U_PATH_SEP_CHAR, 0}; + char* path=(char*)malloc(sizeof(char) * (strlen(ctest_dataOutDir()) + strlen(U_ICUDATA_NAME) @@ -278,7 +280,7 @@ static void TestUDataOpen(){ * overflow handling code. */ { -#if 0 +#if 1 /* TODO: fix doOpenChoice(). Bug 3121. */ char longTestPath[1024]; /* Implementation goes to heap at length of 128. */ char longName[1024];