Skip to content

Commit

Permalink
mi_xmlrpc: fix crash when flushing complex MI trees as strings
Browse files Browse the repository at this point in the history
	* crash was replicated with "ul_dump" command at 51+ contacts
		- "reply_option" must be disabled

This patch solves a couple of other issues:
	* properly mark completed nodes when "reply_option" = 0
	* a rare memory leak when flushing empty "mi_node"s
(cherry picked from commit f5da89d)
  • Loading branch information
liviuchircu committed Apr 3, 2014
1 parent bead016 commit 4b22509
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 16 deletions.
2 changes: 2 additions & 0 deletions modules/mi_xmlrpc/xr_server.c
Expand Up @@ -177,6 +177,8 @@ xmlrpc_value* default_method (xmlrpc_env* env,

LM_DBG("starting up.....\n");

xr_writer_reset();

f = lookup_mi_cmd((char*)methodName, strlen(methodName));

if ( f == 0 ) {
Expand Down
44 changes: 28 additions & 16 deletions modules/mi_xmlrpc/xr_writer.c
Expand Up @@ -49,6 +49,11 @@ int xr_writer_init( unsigned int size )
return 0;
}

void xr_writer_reset(void)
{
*reply_buffer = '\0';
}

#ifndef XMLRPC_HAS_FORCE_CHARS

#define XMLRPC_NONXML_CHAR 0x7F
Expand Down Expand Up @@ -217,10 +222,7 @@ static int recur_flush_response_array(xmlrpc_env * env, struct mi_node *tree,
kid = kid->next;
tree->kids = kid;

if(!tmp->kids){
/* this node does not have any kids */
free_mi_node(tmp);
}
free_mi_node(tmp);
}
else{
/* the node will have more kids => to keep the tree shape, do not
Expand Down Expand Up @@ -286,11 +288,11 @@ static int recur_build_response( xmlrpc_env * env, struct mi_node * tree,
LM_ERR("failed to get MI node data!\n");
return -1;
}

/* we are sure that this node has been written
* => avoid writing it again */
tree->flags |= MI_WRITTEN;
}

/* we are sure that this node has been written
* => avoid writing it again */
tree->flags |= MI_WRITTEN;
}

if ( tree->kids ) {
Expand All @@ -305,9 +307,11 @@ static int recur_build_response( xmlrpc_env * env, struct mi_node * tree,
char* xr_build_response( xmlrpc_env * env, struct mi_root * tree )
{
str buf;
int len;

buf.s = reply_buffer;
buf.len = reply_buffer_len;
len = strlen(reply_buffer);
buf.s = reply_buffer + len;
buf.len = reply_buffer_len - len;

if ( tree->code<200 || tree->code>=300 ){
LM_DBG("command processing failure: %s\n", tree->reason.s);
Expand Down Expand Up @@ -335,6 +339,15 @@ static int recur_flush_response(xmlrpc_env * env, struct mi_node *tree, str *buf
struct mi_node *kid, *tmp;
int ret;

if (!rpl_opt) {
if (recur_build_response(env, tree, buf) != 0) {
LM_ERR("failed to read from the MI tree!\n");
return -1;
}

return 0;
}

for(kid = tree->kids ; kid ; ){
/* write the current kid */
if (!(kid->flags & MI_WRITTEN)){
Expand Down Expand Up @@ -371,10 +384,7 @@ static int recur_flush_response(xmlrpc_env * env, struct mi_node *tree, str *buf
kid = kid->next;
tree->kids = kid;

if(!tmp->kids){
/* this node does not have any kids */
free_mi_node(tmp);
}
free_mi_node(tmp);
}
else{
/* the node will have more kids => to keep the tree shape, do not
Expand All @@ -389,9 +399,11 @@ static int recur_flush_response(xmlrpc_env * env, struct mi_node *tree, str *buf
char* xr_flush_response( xmlrpc_env * env, struct mi_root * tree )
{
str buf;
int len;

buf.s = reply_buffer;
buf.len = reply_buffer_len;
len = strlen(reply_buffer);
buf.s = reply_buffer + len;
buf.len = reply_buffer_len - len;

if ( tree->code<200 || tree->code>=300 ){
LM_DBG("command processing failure: %s\n", tree->reason.s);
Expand Down
1 change: 1 addition & 0 deletions modules/mi_xmlrpc/xr_writer.h
Expand Up @@ -34,6 +34,7 @@
#include "../../mi/tree.h"

int xr_writer_init( unsigned int size );
void xr_writer_reset(void);
char * xr_build_response( xmlrpc_env * env, struct mi_root * tree );
char * xr_flush_response( xmlrpc_env * env, struct mi_root * tree );
int xr_build_response_array( xmlrpc_env * env, struct mi_root * tree );
Expand Down

0 comments on commit 4b22509

Please sign in to comment.