stanza: fix memory leaks

Free attribute "to" before replacing it in xmpp_stanza_reply().
Free value on insertion error in xmpp_stanza_set_attribute().
Don't copy attributes manually. Use xmpp_stanza_set_attribute() instead.
This commit is contained in:
Dmitry Podgorny
2017-07-05 20:20:45 +03:00
parent 15e7032f0d
commit 456083d878

View File

@@ -76,35 +76,27 @@ xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t * const stanza)
static int _stanza_copy_attributes(xmpp_stanza_t * dst, static int _stanza_copy_attributes(xmpp_stanza_t * dst,
const xmpp_stanza_t * const src) const xmpp_stanza_t * const src)
{ {
hash_iterator_t *iter = NULL; hash_iterator_t *iter;
const char *key; const char *key;
void *val; const char *val;
int rc = XMPP_EOK;
dst->attributes = hash_new(src->ctx, 8, xmpp_free);
if (!dst->attributes)
return -1;
iter = hash_iter_new(src->attributes); iter = hash_iter_new(src->attributes);
if (!iter) if (!iter) rc = XMPP_EMEM;
goto error;
while ((key = hash_iter_next(iter))) {
val = xmpp_strdup(src->ctx,
(char *)hash_get(src->attributes, key));
if (!val)
goto error;
if (hash_add(dst->attributes, key, val)) { while (rc == XMPP_EOK && (key = hash_iter_next(iter))) {
xmpp_free(src->ctx, val); val = hash_get(src->attributes, key);
goto error; if (!val) rc = XMPP_EINT;
} if (rc == XMPP_EOK)
rc = xmpp_stanza_set_attribute(dst, key, val);
} }
hash_iter_release(iter); hash_iter_release(iter);
return 0;
error: if (rc != XMPP_EOK && dst->attributes) {
if (iter != NULL) hash_release(dst->attributes);
hash_iter_release(iter); dst->attributes = NULL;
hash_release(dst->attributes); }
return -1; return rc;
} }
/** Copy a stanza and its children. /** Copy a stanza and its children.
@@ -570,6 +562,7 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
const char * const value) const char * const value)
{ {
char *val; char *val;
int rc;
if (stanza->type != XMPP_STANZA_TAG) return XMPP_EINVOP; if (stanza->type != XMPP_STANZA_TAG) return XMPP_EINVOP;
@@ -584,7 +577,11 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
return XMPP_EMEM; return XMPP_EMEM;
} }
hash_add(stanza->attributes, key, val); rc = hash_add(stanza->attributes, key, val);
if (rc < 0) {
xmpp_free(stanza->ctx, val);
return XMPP_EMEM;
}
return XMPP_EOK; return XMPP_EOK;
} }
@@ -1047,7 +1044,12 @@ int xmpp_stanza_del_attribute(xmpp_stanza_t * const stanza,
*/ */
xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza) xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza)
{ {
xmpp_stanza_t *copy; xmpp_stanza_t *copy = NULL;
const char *from;
int rc;
from = xmpp_stanza_get_from(stanza);
if (!from) goto copy_error;
copy = xmpp_stanza_new(stanza->ctx); copy = xmpp_stanza_new(stanza->ctx);
if (!copy) goto copy_error; if (!copy) goto copy_error;
@@ -1060,12 +1062,14 @@ xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza)
} }
if (stanza->attributes) { if (stanza->attributes) {
if (_stanza_copy_attributes(copy, stanza) == -1) if (_stanza_copy_attributes(copy, stanza) < 0)
goto copy_error; goto copy_error;
} }
xmpp_stanza_set_to(copy, xmpp_stanza_get_from(stanza)); xmpp_stanza_del_attribute(copy, "to");
xmpp_stanza_del_attribute(copy, "from"); xmpp_stanza_del_attribute(copy, "from");
rc = xmpp_stanza_set_to(copy, from);
if (rc != XMPP_EOK) goto copy_error;
return copy; return copy;