Author: coreyfarrell Date: Mon Nov 17 09:56:11 2014 New Revision: 428117 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=428117 Log: 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/ Modified: branches/11/channels/chan_sip.c Modified: branches/11/channels/chan_sip.c URL: http://svnview.digium.com/svn/asterisk/branches/11/channels/chan_sip.c?view=diff&rev=428117&r1=428116&r2=428117 ============================================================================== --- branches/11/channels/chan_sip.c (original) +++ branches/11/channels/chan_sip.c Mon Nov 17 09:56:11 2014 @@ -1431,6 +1431,7 @@ 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 void ast_quiet_chan(struct ast_channel *chan); static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target); @@ -6405,14 +6406,7 @@ ast_udptl_destroy(p->udptl); p->udptl = NULL; } - if (p->refer) { - if (p->refer->refer_call) { - p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); - } - 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; @@ -15374,8 +15368,22 @@ /*! \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) { + if (p->refer->refer_call) { + p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); + } + ast_string_field_free_memory(p->refer); + ast_free(p->refer); + p->refer = NULL; + } } /*! \brief Allocate SIP refer structure */ @@ -17862,8 +17870,9 @@ 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; @@ -25342,7 +25351,7 @@ 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); @@ -26302,7 +26311,7 @@ } /* 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."); res = -3; -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits
