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