Plug memory leak found by IBM checker (and try to please it).

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@16923 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2006-04-02 00:01:55 +00:00
parent 2b6c24ce1a
commit 16a5f30931

View File

@@ -99,6 +99,16 @@ dns_type_to_string(int type)
#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND) #if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)
static void
dns_free_rr(struct resource_record *rr)
{
if(rr->domain)
free(rr->domain);
if(rr->u.data)
free(rr->u.data);
free(rr);
}
void ROKEN_LIB_FUNCTION void ROKEN_LIB_FUNCTION
dns_free_data(struct dns_reply *r) dns_free_data(struct dns_reply *r)
{ {
@@ -107,29 +117,30 @@ dns_free_data(struct dns_reply *r)
free(r->q.domain); free(r->q.domain);
for(rr = r->head; rr;){ for(rr = r->head; rr;){
struct resource_record *tmp = rr; struct resource_record *tmp = rr;
if(rr->domain)
free(rr->domain);
if(rr->u.data)
free(rr->u.data);
rr = rr->next; rr = rr->next;
free(tmp); dns_free_rr(tmp);
} }
free (r); free (r);
} }
static int static int
parse_record(const unsigned char *data, const unsigned char *end_data, parse_record(const unsigned char *data, const unsigned char *end_data,
const unsigned char **pp, struct resource_record **rr) const unsigned char **pp, struct resource_record **ret_rr)
{ {
struct resource_record *rr;
int type, class, ttl, size; int type, class, ttl, size;
int status; int status;
char host[MAXDNAME]; char host[MAXDNAME];
const unsigned char *p = *pp; const unsigned char *p = *pp;
*ret_rr = NULL;
status = dn_expand(data, end_data, p, host, sizeof(host)); status = dn_expand(data, end_data, p, host, sizeof(host));
if(status < 0) if(status < 0)
return -1; return -1;
if (p + status + 10 > end_data) if (p + status + 10 > end_data)
return -1; return -1;
p += status; p += status;
type = (p[0] << 8) | p[1]; type = (p[0] << 8) | p[1];
p += 2; p += 2;
@@ -143,30 +154,30 @@ parse_record(const unsigned char *data, const unsigned char *end_data,
if (p + size > end_data) if (p + size > end_data)
return -1; return -1;
*rr = calloc(1, sizeof(**rr)); rr = calloc(1, sizeof(*rr));
if(*rr == NULL) if(rr == NULL)
return -1; return -1;
(*rr)->domain = strdup(host); rr->domain = strdup(host);
if((*rr)->domain == NULL) { if(rr->domain == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->type = type; rr->type = type;
(*rr)->class = class; rr->class = class;
(*rr)->ttl = ttl; rr->ttl = ttl;
(*rr)->size = size; rr->size = size;
switch(type){ switch(type){
case rk_ns_t_ns: case rk_ns_t_ns:
case rk_ns_t_cname: case rk_ns_t_cname:
case rk_ns_t_ptr: case rk_ns_t_ptr:
status = dn_expand(data, end_data, p, host, sizeof(host)); status = dn_expand(data, end_data, p, host, sizeof(host));
if(status < 0) { if(status < 0) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.txt = strdup(host); rr->u.txt = strdup(host);
if((*rr)->u.txt == NULL) { if(rr->u.txt == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
break; break;
@@ -176,101 +187,101 @@ parse_record(const unsigned char *data, const unsigned char *end_data,
status = dn_expand(data, end_data, p + 2, host, sizeof(host)); status = dn_expand(data, end_data, p + 2, host, sizeof(host));
if(status < 0){ if(status < 0){
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
if (status + 2 > size) { if (status + 2 > size) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
hostlen = strlen(host); hostlen = strlen(host);
(*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + rr->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
hostlen); hostlen);
if((*rr)->u.mx == NULL) { if(rr->u.mx == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.mx->preference = (p[0] << 8) | p[1]; rr->u.mx->preference = (p[0] << 8) | p[1];
strlcpy((*rr)->u.mx->domain, host, hostlen + 1); strlcpy(rr->u.mx->domain, host, hostlen + 1);
break; break;
} }
case rk_ns_t_srv:{ case rk_ns_t_srv:{
size_t hostlen; size_t hostlen;
status = dn_expand(data, end_data, p + 6, host, sizeof(host)); status = dn_expand(data, end_data, p + 6, host, sizeof(host));
if(status < 0){ if(status < 0){
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
if (status + 6 > size) { if (status + 6 > size) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
hostlen = strlen(host); hostlen = strlen(host);
(*rr)->u.srv = rr->u.srv =
(struct srv_record*)malloc(sizeof(struct srv_record) + (struct srv_record*)malloc(sizeof(struct srv_record) +
hostlen); hostlen);
if((*rr)->u.srv == NULL) { if(rr->u.srv == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.srv->priority = (p[0] << 8) | p[1]; rr->u.srv->priority = (p[0] << 8) | p[1];
(*rr)->u.srv->weight = (p[2] << 8) | p[3]; rr->u.srv->weight = (p[2] << 8) | p[3];
(*rr)->u.srv->port = (p[4] << 8) | p[5]; rr->u.srv->port = (p[4] << 8) | p[5];
strlcpy((*rr)->u.srv->target, host, hostlen + 1); strlcpy(rr->u.srv->target, host, hostlen + 1);
break; break;
} }
case rk_ns_t_txt:{ case rk_ns_t_txt:{
if(size == 0 || size < *p + 1) { if(size == 0 || size < *p + 1) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.txt = (char*)malloc(*p + 1); rr->u.txt = (char*)malloc(*p + 1);
if((*rr)->u.txt == NULL) { if(rr->u.txt == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
strncpy((*rr)->u.txt, (const char*)(p + 1), *p); strncpy(rr->u.txt, (const char*)(p + 1), *p);
(*rr)->u.txt[*p] = '\0'; rr->u.txt[*p] = '\0';
break; break;
} }
case rk_ns_t_key : { case rk_ns_t_key : {
size_t key_len; size_t key_len;
if (size < 4) { if (size < 4) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
key_len = size - 4; key_len = size - 4;
(*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1); rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
if ((*rr)->u.key == NULL) { if (rr->u.key == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.key->flags = (p[0] << 8) | p[1]; rr->u.key->flags = (p[0] << 8) | p[1];
(*rr)->u.key->protocol = p[2]; rr->u.key->protocol = p[2];
(*rr)->u.key->algorithm = p[3]; rr->u.key->algorithm = p[3];
(*rr)->u.key->key_len = key_len; rr->u.key->key_len = key_len;
memcpy ((*rr)->u.key->key_data, p + 4, key_len); memcpy (rr->u.key->key_data, p + 4, key_len);
break; break;
} }
case rk_ns_t_sig : { case rk_ns_t_sig : {
size_t sig_len, hostlen; size_t sig_len, hostlen;
if(size <= 18) { if(size <= 18) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
status = dn_expand (data, end_data, p + 18, host, sizeof(host)); status = dn_expand (data, end_data, p + 18, host, sizeof(host));
if (status < 0) { if (status < 0) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
if (status + 18 > size) { if (status + 18 > size) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
@@ -281,26 +292,26 @@ parse_record(const unsigned char *data, const unsigned char *end_data,
*/ */
sig_len = size - 18 - status; sig_len = size - 18 - status;
hostlen = strlen(host); hostlen = strlen(host);
(*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig) rr->u.sig = malloc(sizeof(*rr->u.sig)
+ hostlen + sig_len); + hostlen + sig_len);
if ((*rr)->u.sig == NULL) { if (rr->u.sig == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.sig->type = (p[0] << 8) | p[1]; rr->u.sig->type = (p[0] << 8) | p[1];
(*rr)->u.sig->algorithm = p[2]; rr->u.sig->algorithm = p[2];
(*rr)->u.sig->labels = p[3]; rr->u.sig->labels = p[3];
(*rr)->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16) rr->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16)
| (p[6] << 8) | p[7]; | (p[6] << 8) | p[7];
(*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16) rr->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
| (p[10] << 8) | p[11]; | (p[10] << 8) | p[11];
(*rr)->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16) rr->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16)
| (p[14] << 8) | p[15]; | (p[14] << 8) | p[15];
(*rr)->u.sig->key_tag = (p[16] << 8) | p[17]; rr->u.sig->key_tag = (p[16] << 8) | p[17];
(*rr)->u.sig->sig_len = sig_len; rr->u.sig->sig_len = sig_len;
memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len); memcpy (rr->u.sig->sig_data, p + 18 + status, sig_len);
(*rr)->u.sig->signer = &(*rr)->u.sig->sig_data[sig_len]; rr->u.sig->signer = &rr->u.sig->sig_data[sig_len];
strlcpy((*rr)->u.sig->signer, host, hostlen + 1); strlcpy(rr->u.sig->signer, host, hostlen + 1);
break; break;
} }
@@ -308,78 +319,81 @@ parse_record(const unsigned char *data, const unsigned char *end_data,
size_t cert_len; size_t cert_len;
if (size < 5) { if (size < 5) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
cert_len = size - 5; cert_len = size - 5;
(*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1); rr->u.cert = malloc (sizeof(*rr->u.cert) + cert_len - 1);
if ((*rr)->u.cert == NULL) { if (rr->u.cert == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.cert->type = (p[0] << 8) | p[1]; rr->u.cert->type = (p[0] << 8) | p[1];
(*rr)->u.cert->tag = (p[2] << 8) | p[3]; rr->u.cert->tag = (p[2] << 8) | p[3];
(*rr)->u.cert->algorithm = p[4]; rr->u.cert->algorithm = p[4];
(*rr)->u.cert->cert_len = cert_len; rr->u.cert->cert_len = cert_len;
memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len); memcpy (rr->u.cert->cert_data, p + 5, cert_len);
break; break;
} }
case rk_ns_t_sshfp : { case rk_ns_t_sshfp : {
size_t sshfp_len; size_t sshfp_len;
if (size < 2) { if (size < 2) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
sshfp_len = size - 2; sshfp_len = size - 2;
(*rr)->u.sshfp = malloc (sizeof(*(*rr)->u.sshfp) + sshfp_len - 1); rr->u.sshfp = malloc (sizeof(*rr->u.sshfp) + sshfp_len - 1);
if ((*rr)->u.sshfp == NULL) { if (rr->u.sshfp == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.sshfp->algorithm = p[0]; rr->u.sshfp->algorithm = p[0];
(*rr)->u.sshfp->type = p[1]; rr->u.sshfp->type = p[1];
(*rr)->u.sshfp->sshfp_len = sshfp_len; rr->u.sshfp->sshfp_len = sshfp_len;
memcpy ((*rr)->u.sshfp->sshfp_data, p + 2, sshfp_len); memcpy (rr->u.sshfp->sshfp_data, p + 2, sshfp_len);
break; break;
} }
case rk_ns_t_ds: { case rk_ns_t_ds: {
size_t digest_len; size_t digest_len;
if (size < 4) { if (size < 4) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
digest_len = size - 4; digest_len = size - 4;
(*rr)->u.ds = malloc (sizeof(*(*rr)->u.ds) + digest_len - 1); rr->u.ds = malloc (sizeof(*rr->u.ds) + digest_len - 1);
if ((*rr)->u.ds == NULL) { if (rr->u.ds == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
(*rr)->u.ds->key_tag = (p[0] << 8) | p[1]; rr->u.ds->key_tag = (p[0] << 8) | p[1];
(*rr)->u.ds->algorithm = p[2]; rr->u.ds->algorithm = p[2];
(*rr)->u.ds->digest_type = p[3]; rr->u.ds->digest_type = p[3];
(*rr)->u.ds->digest_len = digest_len; rr->u.ds->digest_len = digest_len;
memcpy ((*rr)->u.ds->digest_data, p + 4, digest_len); memcpy (rr->u.ds->digest_data, p + 4, digest_len);
break; break;
} }
default: default:
(*rr)->u.data = (unsigned char*)malloc(size); rr->u.data = (unsigned char*)malloc(size);
if(size != 0 && (*rr)->u.data == NULL) { if(size != 0 && rr->u.data == NULL) {
free(*rr); dns_free_rr(rr);
return -1; return -1;
} }
memcpy((*rr)->u.data, p, size); if (size)
memcpy(rr->u.data, p, size);
} }
*pp = p + size; *pp = p + size;
*ret_rr = rr;
return 0; return 0;
} }