From: Corey Farrell Date: Mon, 17 Nov 2014 15:59:04 +0000 (+0000) Subject: chan_sip: Fix theoretical leak of p->refer. X-Git-Tag: 12.8.0-rc1~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5246c90ae71236d7ec4286349b765fbf443de162;p=thirdparty%2Fasterisk.git chan_sip: Fix theoretical leak of p->refer. If transmit_refer is called when p->refer is already allocated, it leaks the previous allocation. Updated code to always free previous allocation during a new allocation. Also instead of checking if we have a previous allocation, always create a clean record. ASTERISK-15242 #close Reported by: David Woolley Review: https://reviewboard.asterisk.org/r/4160/ ........ Merged revisions 428117 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@428118 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index d26429e2b3..90ef284efc 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1297,6 +1297,7 @@ static int dialog_find_multiple(void *obj, void *arg, int flags); static struct ast_channel *sip_pvt_lock_full(struct sip_pvt *pvt); /* static int sip_addrcmp(char *name, struct sockaddr_in *sin); Support for peer matching */ static int sip_refer_alloc(struct sip_pvt *p); +static void sip_refer_destroy(struct sip_pvt *p); static int sip_notify_alloc(struct sip_pvt *p); static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context); static void set_peer_nat(const struct sip_pvt *p, struct sip_peer *peer); @@ -6530,11 +6531,7 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) ast_udptl_destroy(p->udptl); p->udptl = NULL; } - if (p->refer) { - ast_string_field_free_memory(p->refer); - ast_free(p->refer); - p->refer = NULL; - } + sip_refer_destroy(p); if (p->route) { free_old_route(p->route); p->route = NULL; @@ -15546,10 +15543,21 @@ static int transmit_message(struct sip_pvt *p, int init, int auth) /*! \brief Allocate SIP refer structure */ static int sip_refer_alloc(struct sip_pvt *p) { + sip_refer_destroy(p); p->refer = ast_calloc_with_stringfields(1, struct sip_refer, 512); return p->refer ? 1 : 0; } +/*! \brief Destroy SIP refer structure */ +static void sip_refer_destroy(struct sip_pvt *p) +{ + if (p->refer) { + ast_string_field_free_memory(p->refer); + ast_free(p->refer); + p->refer = NULL; + } +} + /*! \brief Allocate SIP refer structure */ static int sip_notify_alloc(struct sip_pvt *p) { @@ -18278,8 +18286,9 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq) struct sip_refer *refer = NULL; const char *transfer_context = NULL; - if (!p->refer && !sip_refer_alloc(p)) + if (!sip_refer_alloc(p)) { return -1; + } refer = p->refer; @@ -25494,7 +25503,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str replace_id = ast_strdupa(p_replaces); ast_uri_decode(replace_id, ast_uri_sip_user); - if (!p->refer && !sip_refer_alloc(p)) { + if (!sip_refer_alloc(p)) { transmit_response_reliable(p, "500 Server Internal Error", req); append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory."); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); @@ -26351,7 +26360,7 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, uint } /* Allocate memory for call transfer data */ - if (!p->refer && !sip_refer_alloc(p)) { + if (!sip_refer_alloc(p)) { transmit_response(p, "500 Internal Server Error", req); append_history(p, "Xfer", "Refer failed. Memory allocation error."); return -3;