From 225453f12f3adaf90c05fe9b2c1d9af06fa26e09 Mon Sep 17 00:00:00 2001 From: Dennis Heimbigner Date: Tue, 27 Feb 2018 15:46:19 -0700 Subject: [PATCH] Fix memory leaks re utf8_normalize --- libsrc/attr.m4 | 138 +++++++++++++++++++++++-------------------------- libsrc/dim.c | 51 +++++++++--------- libsrc/var.c | 70 ++++++++++--------------- 3 files changed, 118 insertions(+), 141 deletions(-) diff --git a/libsrc/attr.m4 b/libsrc/attr.m4 index 5f31726ea..835eb65b0 100644 --- a/libsrc/attr.m4 +++ b/libsrc/attr.m4 @@ -118,29 +118,29 @@ new_NC_attr( nc_type type, size_t nelems) { - NC_string *strp; - NC_attr *attrp; - char *name; - int stat; + NC_string *strp = NULL; + NC_attr *attrp = NULL; + char *name = NULL; + int stat = NC_NOERR; stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name); if(stat != NC_NOERR) - return NULL; + goto done; assert(name != NULL && *name != 0); strp = new_NC_string(strlen(name), name); - free(name); if(strp == NULL) - return NULL; + goto done; attrp = new_x_NC_attr(strp, type, nelems); if(attrp == NULL) { free_NC_string(strp); - return NULL; + goto done; } - - return(attrp); +done: + if(name) free(name); + return (attrp); } @@ -345,36 +345,34 @@ NC_attrarray0(NC3_INFO* ncp, int varid) NC_attr ** NC_findattr(const NC_attrarray *ncap, const char *uname) { - NC_attr **attrpp; + NC_attr **attrpp = NULL; size_t attrid; size_t slen; - char *name; - int stat; + char *name = NULL; + int stat = NC_NOERR; assert(ncap != NULL); if(ncap->nelems == 0) - return NULL; - - attrpp = (NC_attr **) ncap->value; + goto done; /* normalized version of uname */ stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name); if(stat != NC_NOERR) - return NULL; /* TODO: need better way to indicate no memory */ + goto done; /* TODO: need better way to indicate no memory */ slen = strlen(name); + attrpp = (NC_attr **) ncap->value; for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++) { if(strlen((*attrpp)->name->cp) == slen && strncmp((*attrpp)->name->cp, name, slen) == 0) - { - free(name); - return(attrpp); /* Normal return */ - } + goto done; } - free(name); - return(NULL); + attrpp = NULL; /* not found */ +done: + if(name) free(name); + return (attrpp); /* Normal return */ } @@ -501,71 +499,65 @@ NC3_inq_att(int ncid, int NC3_rename_att( int ncid, int varid, const char *name, const char *unewname) { - int status; - NC *nc; - NC3_INFO* ncp; - NC_attrarray *ncap; - NC_attr **tmp; - NC_attr *attrp; + int status = NC_NOERR; + NC *nc = NULL; + NC3_INFO* ncp = NULL; + NC_attrarray *ncap = NULL; + NC_attr **tmp = NULL; + NC_attr *attrp = NULL; NC_string *newStr, *old; - char *newname; /* normalized version */ + char *newname = NULL; /* normalized version */ + +/* start sortof inline clone of NC_lookupattr() */ - /* sortof inline clone of NC_lookupattr() */ status = NC_check_id(ncid, &nc); if(status != NC_NOERR) - return status; + goto done; ncp = NC3_DATA(nc); if(NC_readonly(ncp)) - return NC_EPERM; + {status = NC_EPERM; goto done;} ncap = NC_attrarray0(ncp, varid); if(ncap == NULL) - return NC_ENOTVAR; + {status = NC_ENOTVAR; goto done;} status = NC_check_name(unewname); if(status != NC_NOERR) - return status; + goto done; tmp = NC_findattr(ncap, name); if(tmp == NULL) - return NC_ENOTATT; + {status = NC_ENOTATT; goto done;} attrp = *tmp; - /* end inline clone NC_lookupattr() */ +/* end inline clone NC_lookupattr() */ if(NC_findattr(ncap, unewname) != NULL) - { - /* name in use */ - return NC_ENAMEINUSE; - } + {status = NC_ENAMEINUSE; goto done;} /* name in use */ old = attrp->name; status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char**)&newname); if(status != NC_NOERR) - return status; + goto done; if(NC_indef(ncp)) { newStr = new_NC_string(strlen(newname), newname); - free(newname); if( newStr == NULL) - return NC_ENOMEM; + {status = NC_ENOMEM; goto done;} attrp->name = newStr; free_NC_string(old); - return NC_NOERR; + goto done; } /* else not in define mode */ /* If new name is longer than old, then complain, but otherwise, no change (test is same as set_NC_string)*/ - if(old->nchars < strlen(newname)) { - free(newname); - return NC_ENOTINDEFINE; - } + if(old->nchars < strlen(newname)) + {status = NC_ENOTINDEFINE; goto done;} status = set_NC_string(old, newname); - free(newname); if( status != NC_NOERR) - return status; + goto done; set_NC_hdirty(ncp); @@ -573,43 +565,43 @@ NC3_rename_att( int ncid, int varid, const char *name, const char *unewname) { status = NC_sync(ncp); if(status != NC_NOERR) - return status; + goto done; } - - return NC_NOERR; +done: + if(newname) free(newname); + return status; } int NC3_del_att(int ncid, int varid, const char *uname) { - int status; - NC *nc; - NC3_INFO* ncp; - NC_attrarray *ncap; - NC_attr **attrpp; + int status = NC_NOERR; + NC *nc = NULL; + NC3_INFO* ncp = NULL; + NC_attrarray *ncap = NULL; + NC_attr **attrpp = NULL; NC_attr *old = NULL; int attrid; size_t slen; + char* name = NULL; status = NC_check_id(ncid, &nc); if(status != NC_NOERR) - return status; + goto done; ncp = NC3_DATA(nc); if(!NC_indef(ncp)) - return NC_ENOTINDEFINE; + {status = NC_ENOTINDEFINE; goto done;} ncap = NC_attrarray0(ncp, varid); if(ncap == NULL) - return NC_ENOTVAR; + {status = NC_ENOTVAR; goto done;} - { - char* name; - int stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name); - if(stat != NC_NOERR) - return stat; + status = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name); + if(status != NC_NOERR) + goto done; - /* sortof inline NC_findattr() */ +/* start sortof inline NC_findattr() */ slen = strlen(name); attrpp = (NC_attr **) ncap->value; @@ -622,11 +614,9 @@ NC3_del_att(int ncid, int varid, const char *uname) break; } } - free(name); - } if( (size_t) attrid == ncap->nelems ) - return NC_ENOTATT; - /* end inline NC_findattr() */ + {status = NC_ENOTATT; goto done;} +/* end inline NC_findattr() */ /* shuffle down */ for(attrid++; (size_t) attrid < ncap->nelems; attrid++) @@ -640,7 +630,9 @@ NC3_del_att(int ncid, int varid, const char *uname) free_NC_attr(old); - return NC_NOERR; +done: + if(name) free(name); + return status; } dnl diff --git a/libsrc/dim.c b/libsrc/dim.c index 5fe0ffdb2..14114ec06 100644 --- a/libsrc/dim.c +++ b/libsrc/dim.c @@ -55,28 +55,29 @@ static NC_dim * new_NC_dim(const char *uname, size_t size) { NC_string *strp; - NC_dim *dimp; - int stat; - char* name; + NC_dim *dimp = NULL; + int stat = NC_NOERR; + char* name = NULL; stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name); if(stat != NC_NOERR) - return NULL; + goto done; strp = new_NC_string(strlen(name), name); - free(name); if(strp == NULL) - return NULL; + {stat = NC_ENOMEM; goto done;} dimp = new_x_NC_dim(strp); if(dimp == NULL) { free_NC_string(strp); - return NULL; + goto done; } dimp->size = size; - return(dimp); +done: + if(name) free(name); + return (dimp); } @@ -432,46 +433,45 @@ NC3_inq_dim(int ncid, int dimid, char *name, size_t *sizep) int NC3_rename_dim( int ncid, int dimid, const char *unewname) { - int status; + int status = NC_NOERR; NC *nc; NC3_INFO* ncp; int existid; NC_dim *dimp; - char *newname; /* normalized */ + char *newname = NULL; /* normalized */ NC_string *old = NULL; uintptr_t intdata; status = NC_check_id(ncid, &nc); if(status != NC_NOERR) - return status; + goto done; ncp = NC3_DATA(nc); if(NC_readonly(ncp)) - return NC_EPERM; + {status = NC_EPERM; goto done;} status = NC_check_name(unewname); if(status != NC_NOERR) - return status; + goto done; existid = NC_finddim(&ncp->dims, unewname, &dimp); if(existid != -1) - return NC_ENAMEINUSE; + {status = NC_ENAMEINUSE; goto done;} dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid); if(dimp == NULL) - return NC_EBADDIM; + {status = NC_EBADDIM; goto done;} old = dimp->name; status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char **)&newname); if(status != NC_NOERR) - return status; + goto done; if(NC_indef(ncp)) { NC_string *newStr = new_NC_string(strlen(newname), newname); - free(newname); if(newStr == NULL) - return NC_ENOMEM; + {status = NC_ENOMEM; goto done;} /* Remove old name from hashmap; add new... */ NC_hashmapremove(ncp->dims.hashmap, old->cp, strlen(old->cp), NULL); @@ -480,8 +480,7 @@ NC3_rename_dim( int ncid, int dimid, const char *unewname) intdata = dimid; NC_hashmapadd(ncp->dims.hashmap, intdata, newStr->cp, strlen(newStr->cp)); free_NC_string(old); - - return NC_NOERR; + goto done; } /* else, not in define mode */ @@ -489,8 +488,7 @@ NC3_rename_dim( int ncid, int dimid, const char *unewname) /* If new name is longer than old, then complain, but otherwise, no change (test is same as set_NC_string)*/ if(dimp->name->nchars < strlen(newname)) { - free(newname); - return NC_ENOTINDEFINE; + {status = NC_ENOTINDEFINE; goto done;} } /* Remove old name from hashmap; add new... */ @@ -499,9 +497,8 @@ NC3_rename_dim( int ncid, int dimid, const char *unewname) /* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */ status = set_NC_string(dimp->name, newname); - free(newname); if(status != NC_NOERR) - return status; + goto done; intdata = (uintptr_t)dimid; NC_hashmapadd(ncp->dims.hashmap, intdata, dimp->name->cp, strlen(dimp->name->cp)); @@ -512,8 +509,10 @@ NC3_rename_dim( int ncid, int dimid, const char *unewname) { status = NC_sync(ncp); if(status != NC_NOERR) - return status; + goto done; } - return NC_NOERR; +done: + if(newname) free(newname); + return status; } diff --git a/libsrc/var.c b/libsrc/var.c index 00719799e..bb0505edc 100644 --- a/libsrc/var.c +++ b/libsrc/var.c @@ -353,34 +353,32 @@ elem_NC_vararray(const NC_vararray *ncap, size_t elem) * Step thru NC_VARIABLE array, seeking match on name. * Return varid or -1 on not found. * *varpp is set to the appropriate NC_var. - * Formerly (sort of) -NC_hvarid + * Formerly (sort of) NC_hvarid */ int NC_findvar(const NC_vararray *ncap, const char *uname, NC_var **varpp) { - uintptr_t hash_var_id; + int hash_var_id = -1; uintptr_t data; - char *name; - int stat; + char *name = NULL; assert(ncap != NULL); if(ncap->nelems == 0) - return -1; - + goto done; /* normalized version of uname */ - stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name); - if(stat != NC_NOERR) - return stat; + if(nc_utf8_normalize((const unsigned char *)uname,(unsigned char **)&name)) + goto done; if(NC_hashmapget(ncap->hashmap, name, strlen(name), &data) == 0) - return -1; - hash_var_id = data; - free(name); + goto done; + + hash_var_id = (int)data; if (varpp != NULL) *varpp = ncap->value[hash_var_id]; +done: + if(name != NULL) free(name); return(hash_var_id); /* Normal return */ } @@ -734,71 +732,60 @@ NC3_inq_var(int ncid, int NC3_rename_var(int ncid, int varid, const char *unewname) { - int status; + int status = NC_NOERR; NC *nc; NC3_INFO* ncp; uintptr_t intdata; NC_var *varp; NC_string *old, *newStr; int other; - char *newname; /* normalized */ + char *newname = NULL; /* normalized */ status = NC_check_id(ncid, &nc); if(status != NC_NOERR) - return status; + goto done; ncp = NC3_DATA(nc); if(NC_readonly(ncp)) - { - return NC_EPERM; - } + {status = NC_EPERM; goto done;} status = NC_check_name(unewname); if(status != NC_NOERR) - return status; + goto done; /* check for name in use */ other = NC_findvar(&ncp->vars, unewname, &varp); if(other != -1) - { - return NC_ENAMEINUSE; - } + {status = NC_ENAMEINUSE; goto done;} status = NC_lookupvar(ncp, varid, &varp); if(status != NC_NOERR) - { - /* invalid varid */ - return status; - } - + goto done; /* invalid varid */ old = varp->name; status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char **)&newname); if(status != NC_NOERR) - return status; + goto done; if(NC_indef(ncp)) { /* Remove old name from hashmap; add new... */ /* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */ NC_hashmapremove(ncp->vars.hashmap,old->cp,strlen(old->cp),NULL); newStr = new_NC_string(strlen(newname),newname); - free(newname); if(newStr == NULL) - return(-1); + {status = NC_ENOMEM; goto done;} varp->name = newStr; intdata = (uintptr_t)varid; NC_hashmapadd(ncp->vars.hashmap, intdata, varp->name->cp, strlen(varp->name->cp)); free_NC_string(old); - return NC_NOERR; + goto done; } /* else, not in define mode */ /* If new name is longer than old, then complain, but otherwise, no change (test is same as set_NC_string)*/ - if(varp->name->nchars < strlen(newname)) { - free(newname); - return NC_ENOTINDEFINE; - } + if(varp->name->nchars < strlen(newname)) + {status = NC_ENOTINDEFINE; goto done;} /* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */ /* Remove old name from hashmap; add new... */ @@ -806,10 +793,8 @@ NC3_rename_var(int ncid, int varid, const char *unewname) /* WARNING: strlen(NC_string.cp) may be less than NC_string.nchars */ status = set_NC_string(varp->name, newname); - free(newname); - if(status != NC_NOERR) - return status; + goto done; intdata = (uintptr_t)varid; NC_hashmapadd(ncp->vars.hashmap, intdata, varp->name->cp, strlen(varp->name->cp)); @@ -820,10 +805,11 @@ NC3_rename_var(int ncid, int varid, const char *unewname) { status = NC_sync(ncp); if(status != NC_NOERR) - return status; + goto done; } - - return NC_NOERR; +done: + if(newname) free(newname); + return status; } int