ICU-1008 Fix memory leak in ISO-2022 SafeClone
X-SVN-Rev: 5689
This commit is contained in:
parent
c179a60a6f
commit
a118536e31
@ -210,7 +210,7 @@ void ucnv_close (UConverter * converter)
|
|||||||
};
|
};
|
||||||
UErrorCode errorCode;
|
UErrorCode errorCode;
|
||||||
|
|
||||||
if (converter == NULL || converter->isCopyLocal)
|
if (converter == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -224,16 +224,16 @@ void ucnv_close (UConverter * converter)
|
|||||||
if (converter->sharedData->impl->close != NULL) {
|
if (converter->sharedData->impl->close != NULL) {
|
||||||
converter->sharedData->impl->close(converter);
|
converter->sharedData->impl->close(converter);
|
||||||
}
|
}
|
||||||
|
if(!converter->isCopyLocal){
|
||||||
if (converter->sharedData->referenceCounter != ~0) {
|
if (converter->sharedData->referenceCounter != ~0) {
|
||||||
umtx_lock (NULL);
|
umtx_lock (NULL);
|
||||||
if (converter->sharedData->referenceCounter != 0) {
|
if (converter->sharedData->referenceCounter != 0) {
|
||||||
converter->sharedData->referenceCounter--;
|
converter->sharedData->referenceCounter--;
|
||||||
}
|
}
|
||||||
umtx_unlock (NULL);
|
umtx_unlock (NULL);
|
||||||
|
}
|
||||||
|
uprv_free (converter);
|
||||||
}
|
}
|
||||||
uprv_free (converter);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,6 @@ typedef struct{
|
|||||||
uint32_t version;
|
uint32_t version;
|
||||||
char locale[3];
|
char locale[3];
|
||||||
char name[30];
|
char name[30];
|
||||||
|
|
||||||
}UConverterDataISO2022;
|
}UConverterDataISO2022;
|
||||||
|
|
||||||
/* ISO-2022 ----------------------------------------------------------------- */
|
/* ISO-2022 ----------------------------------------------------------------- */
|
||||||
@ -673,19 +672,25 @@ _ISO2022Close(UConverter *converter) {
|
|||||||
UConverter **array = myData->myConverterArray;
|
UConverter **array = myData->myConverterArray;
|
||||||
|
|
||||||
if (converter->extraInfo != NULL) {
|
if (converter->extraInfo != NULL) {
|
||||||
|
if(!converter->isCopyLocal){
|
||||||
|
/*close the array of converter pointers and free the memory*/
|
||||||
|
while(*array!=NULL){
|
||||||
|
if(*array==myData->currentConverter){
|
||||||
|
myData->currentConverter=NULL;
|
||||||
|
}
|
||||||
|
ucnv_close(*array++);
|
||||||
|
|
||||||
/*close the array of converter pointers and free the memory*/
|
|
||||||
while(*array!=NULL){
|
|
||||||
if(*array==myData->currentConverter){
|
|
||||||
myData->currentConverter=NULL;
|
|
||||||
}
|
}
|
||||||
ucnv_close(*array++);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(myData->currentConverter){
|
|
||||||
ucnv_close(myData->currentConverter);
|
ucnv_close(myData->currentConverter);
|
||||||
|
uprv_free (converter->extraInfo);
|
||||||
|
}else{
|
||||||
|
/* close the currentConverter if and only if the
|
||||||
|
* ISO-2022 framework converter
|
||||||
|
*/
|
||||||
|
if(!myData->isLocaleSpecified){
|
||||||
|
ucnv_close(myData->currentConverter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uprv_free (converter->extraInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,6 +704,7 @@ _ISO2022Reset(UConverter *converter, UConverterResetChoice choice) {
|
|||||||
ucnv_close (myConverterData->currentConverter);
|
ucnv_close (myConverterData->currentConverter);
|
||||||
myConverterData->currentConverter=NULL;
|
myConverterData->currentConverter=NULL;
|
||||||
}
|
}
|
||||||
|
converter->mode = UCNV_SI;
|
||||||
}
|
}
|
||||||
if(choice!=UCNV_RESET_TO_UNICODE) {
|
if(choice!=UCNV_RESET_TO_UNICODE) {
|
||||||
/* re-append UTF-8 escape sequence */
|
/* re-append UTF-8 escape sequence */
|
||||||
@ -949,7 +955,8 @@ T_UConverter_getNextUChar_ISO_2022(UConverterToUnicodeArgs* args,
|
|||||||
|
|
||||||
mySourceLimit = getEndOfBuffer_2022(&(args->source), args->sourceLimit, TRUE);
|
mySourceLimit = getEndOfBuffer_2022(&(args->source), args->sourceLimit, TRUE);
|
||||||
/*Find the end of the buffer e.g : Next Escape Seq | end of Buffer*/
|
/*Find the end of the buffer e.g : Next Escape Seq | end of Buffer*/
|
||||||
if (args->converter->mode == UCNV_SO) /*Already doing some conversion*/{
|
if (args->converter->mode == UCNV_SO && mySourceLimit!=args->source)
|
||||||
|
/*Already doing some conversion*/{
|
||||||
|
|
||||||
return ucnv_getNextUChar(myData->currentConverter,
|
return ucnv_getNextUChar(myData->currentConverter,
|
||||||
&(args->source),
|
&(args->source),
|
||||||
@ -3263,9 +3270,9 @@ struct cloneStruct
|
|||||||
{
|
{
|
||||||
UConverter cnv;
|
UConverter cnv;
|
||||||
UConverterDataISO2022 mydata;
|
UConverterDataISO2022 mydata;
|
||||||
|
UConverter currentCnv; /**< for ISO_2022 converter if the current converter is open */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
U_CFUNC UConverter *
|
U_CFUNC UConverter *
|
||||||
_ISO_2022_SafeClone(
|
_ISO_2022_SafeClone(
|
||||||
const UConverter *cnv,
|
const UConverter *cnv,
|
||||||
@ -3275,6 +3282,7 @@ _ISO_2022_SafeClone(
|
|||||||
{
|
{
|
||||||
struct cloneStruct * localClone;
|
struct cloneStruct * localClone;
|
||||||
int32_t bufferSizeNeeded = sizeof(struct cloneStruct);
|
int32_t bufferSizeNeeded = sizeof(struct cloneStruct);
|
||||||
|
UConverterDataISO2022* cnvData = (UConverterDataISO2022*)cnv->extraInfo;
|
||||||
|
|
||||||
if (U_FAILURE(*status)){
|
if (U_FAILURE(*status)){
|
||||||
return 0;
|
return 0;
|
||||||
@ -3287,9 +3295,25 @@ _ISO_2022_SafeClone(
|
|||||||
|
|
||||||
localClone = (struct cloneStruct *)stackBuffer;
|
localClone = (struct cloneStruct *)stackBuffer;
|
||||||
uprv_memcpy(&localClone->cnv, cnv, sizeof(UConverter));
|
uprv_memcpy(&localClone->cnv, cnv, sizeof(UConverter));
|
||||||
localClone->cnv.isCopyLocal = TRUE;
|
|
||||||
|
|
||||||
uprv_memcpy(&localClone->mydata, cnv->extraInfo, sizeof(UConverterDataISO2022));
|
uprv_memcpy(&localClone->mydata, cnv->extraInfo, sizeof(UConverterDataISO2022));
|
||||||
|
|
||||||
|
localClone->cnv.isCopyLocal = TRUE;
|
||||||
|
|
||||||
|
/* clone the current converter if it is open in ISO-2022 converter and since it
|
||||||
|
* preserves conversion state in currentConverter object we need to clone it
|
||||||
|
*/
|
||||||
|
if((!cnvData->isLocaleSpecified && cnvData->currentConverter!=NULL) ||
|
||||||
|
/* KR version 1 also uses the state in currentConverter for preserving state
|
||||||
|
* so we need to clone it too!
|
||||||
|
*/
|
||||||
|
(cnvData->locale[0]=='k' && cnvData->version==1)){
|
||||||
|
|
||||||
|
uprv_memcpy(&localClone->currentCnv, cnvData->currentConverter, sizeof(UConverter));
|
||||||
|
|
||||||
|
localClone->mydata.currentConverter = &localClone->currentCnv;
|
||||||
|
}
|
||||||
|
|
||||||
localClone->cnv.extraInfo = &localClone->mydata;
|
localClone->cnv.extraInfo = &localClone->mydata;
|
||||||
|
|
||||||
return &localClone->cnv;
|
return &localClone->cnv;
|
||||||
|
@ -594,7 +594,7 @@ _LMBCSOpenWorker(UConverter* _this,
|
|||||||
static void
|
static void
|
||||||
_LMBCSClose(UConverter * _this)
|
_LMBCSClose(UConverter * _this)
|
||||||
{
|
{
|
||||||
if (_this->extraInfo != NULL)
|
if (_this->extraInfo != NULL && !_this->isCopyLocal)
|
||||||
{
|
{
|
||||||
ulmbcs_byte_t Ix;
|
ulmbcs_byte_t Ix;
|
||||||
UConverterDataLMBCS * extraInfo = (UConverterDataLMBCS *) _this->extraInfo;
|
UConverterDataLMBCS * extraInfo = (UConverterDataLMBCS *) _this->extraInfo;
|
||||||
|
@ -156,9 +156,10 @@ _HZOpen(UConverter *cnv, const char *name,const char *locale,uint32_t options, U
|
|||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
_HZClose(UConverter *cnv){
|
_HZClose(UConverter *cnv){
|
||||||
|
if((cnv->extraInfo != NULL) && !cnv->isCopyLocal){
|
||||||
ucnv_close (((UConverterDataHZ *) (cnv->extraInfo))->gbConverter);
|
ucnv_close (((UConverterDataHZ *) (cnv->extraInfo))->gbConverter);
|
||||||
uprv_free(cnv->extraInfo);
|
uprv_free(cnv->extraInfo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ _ISCIIOpen(UConverter *cnv, const char *name,const char *locale,uint32_t options
|
|||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
_ISCIIClose(UConverter *cnv){
|
_ISCIIClose(UConverter *cnv){
|
||||||
if(cnv->extraInfo){
|
if(cnv->extraInfo && !cnv->isCopyLocal){
|
||||||
uprv_free(cnv->extraInfo);
|
uprv_free(cnv->extraInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,9 +242,11 @@ _SCSUOpen(UConverter *cnv,
|
|||||||
|
|
||||||
U_CFUNC void
|
U_CFUNC void
|
||||||
_SCSUClose(UConverter *cnv) {
|
_SCSUClose(UConverter *cnv) {
|
||||||
if(cnv->extraInfo!=NULL) {
|
if(!cnv->isCopyLocal){
|
||||||
uprv_free(cnv->extraInfo);
|
if(cnv->extraInfo!=NULL) {
|
||||||
cnv->extraInfo=NULL;
|
uprv_free(cnv->extraInfo);
|
||||||
|
cnv->extraInfo=NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,13 +1084,19 @@ static void TestAlias() {
|
|||||||
|
|
||||||
static void TestConvertSafeClone()
|
static void TestConvertSafeClone()
|
||||||
{
|
{
|
||||||
#define CLONETEST_CONVERTER_COUNT 6
|
#define CLONETEST_CONVERTER_COUNT 8
|
||||||
|
|
||||||
char charBuffer [10];
|
char charBuffer [20];
|
||||||
char *pCharBuffer;
|
char *pCharBuffer;
|
||||||
const char *pConstCharBuffer;
|
const char *pConstCharBuffer;
|
||||||
const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
|
const char *charBufferLimit = charBuffer + sizeof(charBuffer)/sizeof(*charBuffer);
|
||||||
UChar uniBuffer [] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
|
UChar uniBuffer [] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */
|
||||||
|
UChar uniCharBuffer [20];
|
||||||
|
char charSourceBuffer [] = { 0x1b, 0x24, 0x42 };
|
||||||
|
char *pCharSource = charSourceBuffer;
|
||||||
|
char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer);
|
||||||
|
UChar *pUCharTarget = uniCharBuffer;
|
||||||
|
UChar *pUCharTargetLimit = uniCharBuffer + sizeof(uniCharBuffer);
|
||||||
const UChar * pUniBuffer;
|
const UChar * pUniBuffer;
|
||||||
const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer);
|
const UChar *uniBufferLimit = uniBuffer + sizeof(uniBuffer)/sizeof(*uniBuffer);
|
||||||
int index;
|
int index;
|
||||||
@ -1109,7 +1115,9 @@ static void TestConvertSafeClone()
|
|||||||
someConverters[3] = ucnv_open("HZ", &err);
|
someConverters[3] = ucnv_open("HZ", &err);
|
||||||
someConverters[4] = ucnv_open("lmbcs", &err);
|
someConverters[4] = ucnv_open("lmbcs", &err);
|
||||||
someConverters[5] = ucnv_open("ISCII,version=0",&err);
|
someConverters[5] = ucnv_open("ISCII,version=0",&err);
|
||||||
|
someConverters[6] = ucnv_open("ISO_2022,locale=kr,version=1",&err);
|
||||||
|
someConverters[7] = ucnv_open("ISO_2022,locale=jp,version=1",&err);
|
||||||
|
|
||||||
/* Check the various error & informational states: */
|
/* Check the various error & informational states: */
|
||||||
|
|
||||||
/* Null status - just returns NULL */
|
/* Null status - just returns NULL */
|
||||||
@ -1195,11 +1203,27 @@ static void TestConvertSafeClone()
|
|||||||
NULL,
|
NULL,
|
||||||
TRUE,
|
TRUE,
|
||||||
&err);
|
&err);
|
||||||
|
if(U_FAILURE(err)){
|
||||||
|
log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err));
|
||||||
|
}
|
||||||
|
ucnv_toUnicode(someClonedConverters[index],
|
||||||
|
&pUCharTarget,
|
||||||
|
pUCharTargetLimit,
|
||||||
|
&pCharSource,
|
||||||
|
pCharSourceLimit,
|
||||||
|
NULL,
|
||||||
|
TRUE,
|
||||||
|
&err
|
||||||
|
);
|
||||||
|
|
||||||
|
if(U_FAILURE(err)){
|
||||||
|
log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err));
|
||||||
|
}
|
||||||
|
|
||||||
pConstCharBuffer = charBuffer;
|
pConstCharBuffer = charBuffer;
|
||||||
if (uniBuffer [0] != ucnv_getNextUChar(someClonedConverters[index], &pConstCharBuffer, pCharBuffer, &err))
|
if (uniBuffer [0] != ucnv_getNextUChar(someClonedConverters[index], &pConstCharBuffer, pCharBuffer, &err))
|
||||||
{
|
{
|
||||||
log_err("FAIL: Cloned converter failed to do conversion\n");
|
log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err));
|
||||||
}
|
}
|
||||||
ucnv_close(someClonedConverters[index]);
|
ucnv_close(someClonedConverters[index]);
|
||||||
ucnv_close(someConverters[index]);
|
ucnv_close(someConverters[index]);
|
||||||
|
Loading…
Reference in New Issue
Block a user