瀏覽代碼

siptrace: fix pkg memory leak when module configured with core callbacks

- Correctly freeng pkg memory in core callbacks when body modifications take place with X-Siptrace headers,
  also fix potential pkg_free with not dynamicaly allocated objects.
Dennis Yurasov 3 年之前
父節點
當前提交
fc50ce1dbd
共有 3 個文件被更改,包括 36 次插入12 次删除
  1. 28 10
      src/modules/siptrace/siptrace.c
  2. 2 0
      src/modules/siptrace/siptrace_data.h
  3. 6 2
      src/modules/siptrace/siptrace_send.c

+ 28 - 10
src/modules/siptrace/siptrace.c

@@ -2118,6 +2118,8 @@ int siptrace_net_data_recv(sr_event_param_t *evp)
 	sr_net_info_t *nd;
 	siptrace_data_t sto;
 	sip_msg_t tmsg;
+	int evcb_ret;
+	int ret = 0;
 
 	if(evp->data == 0)
 		return -1;
@@ -2160,10 +2162,15 @@ int siptrace_net_data_recv(sr_event_param_t *evp)
 
 	sto.dir = "in";
 
-	if(siptrace_exec_evcb_msg(&sto) == DROP_R_F) {
+	evcb_ret=siptrace_exec_evcb_msg(&sto);
+	if(evcb_ret < 0) {
+		ret = -1;
+		goto finish;
+	}
+	if(evcb_ret == DROP_R_F) {
 		/* drop() used in event_route - all done */
 		LM_DBG("skipping processing message due to drop\n");
-		return 0;
+		goto finish;
 	}
 
 	LM_DBG("processing message mode %d\n", _siptrace_mode);
@@ -2223,7 +2230,11 @@ afterdb:
 		trace_send_duplicate(sto.body.s, sto.body.len, NULL);
 	}
 
-	return 0;
+finish:
+	if(sip_trace_xheaders_free(&sto) != 0)
+		return -1;
+
+	return ret;
 }
 
 /**
@@ -2236,6 +2247,8 @@ int siptrace_net_data_sent(sr_event_param_t *evp)
 	siptrace_data_t sto;
 	sip_msg_t tmsg;
 	int proto;
+	int evcb_ret;
+	int ret = 0;
 
 	if(evp->data == 0)
 		return -1;
@@ -2268,7 +2281,7 @@ int siptrace_net_data_sent(sr_event_param_t *evp)
 		if(new_dst.send_sock->sock_str.len>=SIPTRACE_ADDR_MAX-1) {
 			LM_ERR("socket string is too large: %d\n",
 					new_dst.send_sock->sock_str.len);
-			goto error;
+			return -1;
 		}
 		strncpy(sto.fromip_buff, new_dst.send_sock->sock_str.s,
 				new_dst.send_sock->sock_str.len);
@@ -2291,10 +2304,15 @@ int siptrace_net_data_sent(sr_event_param_t *evp)
 
 	sto.dir = "out";
 
-	if(siptrace_exec_evcb_msg(&sto) == DROP_R_F) {
+	evcb_ret=siptrace_exec_evcb_msg(&sto);
+	if(evcb_ret < 0) {
+		ret = -1;
+		goto finish;
+	}
+	if(evcb_ret == DROP_R_F) {
 		/* drop() used in event_route - all done */
 		LM_DBG("skipping processing message due to drop\n");
-		return 0;
+		goto finish;
 	}
 
 	LM_DBG("processing message mode %d\n", _siptrace_mode);
@@ -2353,11 +2371,11 @@ afterdb:
 	if(_siptrace_mode & SIPTRACE_MODE_URI) {
 		trace_send_duplicate(sto.body.s, sto.body.len, NULL);
 	}
+finish:
+	if(sip_trace_xheaders_free(&sto) != 0)
+		return -1;
 
-	return 0;
-
-error:
-	return -1;
+	return ret;
 }
 
 /**

+ 2 - 0
src/modules/siptrace/siptrace_data.h

@@ -40,6 +40,7 @@ typedef struct _siptrace_data
 	int_str avp_value;
 	struct search_state state;
 	str body;
+	int alloc_body;
 	str callid;
 	str method;
 	str status;
@@ -48,6 +49,7 @@ typedef struct _siptrace_data
 	str fromip;
 	str totag;
 	str toip;
+	int alloc_headers;
 	char toip_buff[SIPTRACE_ADDR_MAX];
 	char fromip_buff[SIPTRACE_ADDR_MAX];
 	struct timeval tv;

+ 6 - 2
src/modules/siptrace/siptrace_send.c

@@ -139,6 +139,7 @@ int sip_trace_xheaders_write(struct _siptrace_data *sto)
 	// Change sto to point to the new buffer.
 	sto->body.s = buf;
 	sto->body.len += bytes_written;
+	sto->alloc_body = 1;
 	return 0;
 error:
 	if(buf != NULL) {
@@ -224,6 +225,7 @@ int sip_trace_xheaders_read(struct _siptrace_data *sto)
 	*eoh = '\r';
 	memmove(xheaders, eoh, sto->body.len - (eoh - sto->body.s));
 	sto->body.len -= eoh - xheaders;
+	sto->alloc_headers = 1;
 
 	return 0;
 
@@ -252,14 +254,15 @@ erroraftermalloc:
  */
 int sip_trace_xheaders_free(struct _siptrace_data *sto)
 {
-	if(trace_xheaders_write != 0) {
+	if(sto->alloc_body != 0) {
 		if(sto->body.s) {
 			pkg_free(sto->body.s);
 			sto->body.s = 0;
 		}
+		sto->alloc_body = 0;
 	}
 
-	if(trace_xheaders_read != 0) {
+	if(sto->alloc_headers != 0) {
 		if(sto->fromip.s) {
 			pkg_free(sto->fromip.s);
 			sto->fromip.s = 0;
@@ -272,6 +275,7 @@ int sip_trace_xheaders_free(struct _siptrace_data *sto)
 			pkg_free(sto->dir);
 			sto->dir = 0;
 		}
+		sto->alloc_headers = 0;
 	}
 
 	return 0;