Browse code

presence_dialoginfo: safety checks to avoid accessing null values

Daniel-Constantin Mierla authored on 31/07/2017 13:33:57
Showing 1 changed files
... ...
@@ -274,108 +274,128 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
274 274
 		if (p_root->children) {
275 275
 			for (node = p_root->children; node; node = next_node) {
276 276
 				next_node = node->next;
277
-				if (node->type == XML_ELEMENT_NODE) {
278
-					LM_DBG("node type: Element, name: %s\n", node->name);
279
-					/* we do not copy the node, but unlink it and then add it ot the new node
280
-					 * this destroys the original document but we do not need it anyway.
281
-					 * using "copy" instead of "unlink" would also copy the namespace which 
282
-					 * would then be declared redundant (libxml unfortunately can not remove 
283
-					 * namespaces)
277
+				if (node->type != XML_ELEMENT_NODE) {
278
+					continue;
279
+				}
280
+				LM_DBG("node type: Element, name: %s\n", node->name);
281
+				/* we do not copy the node, but unlink it and then add it ot the new node
282
+				 * this destroys the original document but we do not need it anyway.
283
+				 * using "copy" instead of "unlink" would also copy the namespace which 
284
+				 * would then be declared redundant (libxml unfortunately can not remove 
285
+				 * namespaces)
286
+				 */
287
+				if(!force_single_dialog || (j == 1)) {
288
+					xmlUnlinkNode(node);
289
+					if(xmlAddChild(root_node, node) == NULL) {
290
+						xmlFreeNode(node);
291
+						LM_ERR("while adding child\n");
292
+						goto error;
293
+					}
294
+				} else {
295
+					/* try to put only the most important into the XML document
296
+					 * order of importance: terminated->trying->proceeding->confirmed->early
297
+					 * - check first the relevant states and jump priority for them
284 298
 					 */
285
-					if (!force_single_dialog || (j==1)) {
286
-						xmlUnlinkNode(node);
287
-						if(xmlAddChild(root_node, node)== NULL) {
288
-							xmlFreeNode(node);
289
-							LM_ERR("while adding child\n");
290
-							goto error;
299
+					if(strcasecmp((char *)node->name, "dialog") == 0) {
300
+						if(dialog_id) {
301
+							xmlFree(dialog_id);
291 302
 						}
292
-					} else {
293
-						/* try to put only the most important into the XML document
294
-						 * order of importance: terminated->trying->proceeding->confirmed->early
295
-						 * - check first the relevant states and jump priority for them
296
-						 */
297
-						if(strcasecmp((char*)node->name,"dialog") == 0)
298
-						{
299
-							if(dialog_id) xmlFree(dialog_id);
300
-							dialog_id = xmlGetProp(node,(const xmlChar *)"id");
301
-							if(dialog_id) {
302
-								node_id = i;
303
-								LM_DBG("Dialog id for this node : %s\n", dialog_id);
304
-							} else {
305
-								LM_DBG("No dialog id for this node - index: %d\n", i);
306
-							}
303
+						dialog_id = xmlGetProp(node, (const xmlChar *)"id");
304
+						if(dialog_id) {
305
+							node_id = i;
306
+							LM_DBG("Dialog id for this node : %s\n", dialog_id);
307
+						} else {
308
+							LM_DBG("No dialog id for this node - index: %d\n",
309
+									i);
307 310
 						}
308
-						state = xmlNodeGetNodeContentByName(node, "state", NULL);
309
-						if(state) {
310
-							LM_DBG("state element content = %s\n", state);
311
-							if (strcasecmp(state,"terminated") == 0)
312
-							{
313
-								LM_DBG("found terminated state\n" );
314
-								terminated_node = node;
315
-							} else if (strcasecmp(state,"confirmed") == 0 && node_id == i) {
316
-								/*  here we check if confirmed is terminated or not
311
+					}
312
+					state = xmlNodeGetNodeContentByName(node, "state", NULL);
313
+					if(state) {
314
+						LM_DBG("state element content = %s\n", state);
315
+						if(strcasecmp(state, "terminated") == 0) {
316
+							LM_DBG("found terminated state\n");
317
+							terminated_node = node;
318
+						} else if(strcasecmp(state, "confirmed") == 0
319
+								  && node_id == i) {
320
+							/*  here we check if confirmed is terminated or not
317 321
 								 *  if it is not we are in the middle of the conversation
318 322
 								 */
319
-								if(check_relevant_state(dialog_id, xml_array, j) >= DEF_TERMINATED_NODE)
320
-								{
321
-									LM_DBG("confirmed state for dialog %s, but it is not latest state\n", dialog_id );
322
-								}else{
323
-									LM_DBG("confirmed state for dialog %s and latest state for this dialog\n", dialog_id );
324
-									confirmed_node = node;
325
-								}
326
-
327
-
328
-							} else if (strcasecmp(state,"early") == 0 && node_id == i) {
329
-								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_CONFIRMED_NODE)
330
-								{
331
-									LM_DBG("early state for dialog %s, but it is not latest state\n", dialog_id );
332
-								}else{
333
-									LM_DBG("early state for dialog %s and latest state for this dialog\n", dialog_id );
334
-									early_node = node;
335
-								}
336
-							} else if (strcasecmp(state,"proceeding") == 0 && node_id == i) {
337
-								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_EARLY_NODE)
338
-								{
339
-									LM_DBG("proceeding state for dialog %s, but it is not latest state\n", dialog_id );
340
-								}else{
341
-									LM_DBG("proceeding state for dialog %s and latest state for this dialog\n", dialog_id );
342
-									proceed_node = node;
343
-								}
344
-							} else if (strcasecmp(state,"trying") == 0 && node_id == i) {
345
-								if(check_relevant_state(dialog_id, xml_array, j)  >= DEF_PROCEEDING_NODE)
346
-								{
347
-									LM_DBG("trying state for dialog %s, but it is not latest state\n", dialog_id );
348
-								}else{
349
-									LM_DBG("trying state for dialog %s and latest state for this dialog\n", dialog_id );
350
-									trying_node = node;
351
-								}
323
+							if(check_relevant_state(dialog_id, xml_array, j)
324
+									>= DEF_TERMINATED_NODE) {
325
+								LM_DBG("confirmed state for dialog %s, but it "
326
+									   "is not latest state\n",
327
+										dialog_id);
328
+							} else {
329
+								LM_DBG("confirmed state for dialog %s and "
330
+									   "latest state for this dialog\n",
331
+										dialog_id);
332
+								confirmed_node = node;
352 333
 							}
353
-							if(early_node != NULL) {
354
-								winner_dialog_node = early_node;
355
-							} else if(confirmed_node != NULL) {
356
-									winner_dialog_node = confirmed_node;
357
-							} else if(proceed_node != NULL) {
358
-									winner_dialog_node = proceed_node;
359
-							} else if(trying_node != NULL) {
360
-									winner_dialog_node = trying_node;
361
-							} else if(terminated_node != NULL) {
362
-									winner_dialog_node = terminated_node;
334
+						} else if(strcasecmp(state, "early") == 0
335
+								  && node_id == i) {
336
+							if(check_relevant_state(dialog_id, xml_array, j)
337
+									>= DEF_CONFIRMED_NODE) {
338
+								LM_DBG("early state for dialog %s, but it is "
339
+									   "not latest state\n",
340
+										dialog_id);
363 341
 							} else {
364
-								/* assume a failure somewhere and all above nodes are NULL */
365
-								winner_dialog_node = node;
342
+								LM_DBG("early state for dialog %s and latest "
343
+									   "state for this dialog\n",
344
+										dialog_id);
345
+								early_node = node;
346
+							}
347
+						} else if(strcasecmp(state, "proceeding") == 0
348
+								  && node_id == i) {
349
+							if(check_relevant_state(dialog_id, xml_array, j)
350
+									>= DEF_EARLY_NODE) {
351
+								LM_DBG("proceeding state for dialog %s, but it "
352
+									   "is not latest state\n",
353
+										dialog_id);
354
+							} else {
355
+								LM_DBG("proceeding state for dialog %s and "
356
+									   "latest state for this dialog\n",
357
+										dialog_id);
358
+								proceed_node = node;
366 359
 							}
367
-							/*
368
-							if(winner_dialog_node == NULL) {
369
-								priority = get_dialog_state_priority(state);
370
-								if (priority > winner_priority) {
371
-									winner_priority = priority;
372
-									LM_DBG("new winner priority = %s (%d)\n", state, winner_priority);
373
-									winner_dialog_node = node;
374
-								}
360
+						} else if(strcasecmp(state, "trying") == 0
361
+								  && node_id == i) {
362
+							if(check_relevant_state(dialog_id, xml_array, j)
363
+									>= DEF_PROCEEDING_NODE) {
364
+								LM_DBG("trying state for dialog %s, but it is "
365
+									   "not latest state\n",
366
+										dialog_id);
367
+							} else {
368
+								LM_DBG("trying state for dialog %s and latest "
369
+									   "state for this dialog\n",
370
+										dialog_id);
371
+								trying_node = node;
372
+							}
373
+						}
374
+						if(early_node != NULL) {
375
+							winner_dialog_node = early_node;
376
+						} else if(confirmed_node != NULL) {
377
+							winner_dialog_node = confirmed_node;
378
+						} else if(proceed_node != NULL) {
379
+							winner_dialog_node = proceed_node;
380
+						} else if(trying_node != NULL) {
381
+							winner_dialog_node = trying_node;
382
+						} else if(terminated_node != NULL) {
383
+							winner_dialog_node = terminated_node;
384
+						} else {
385
+							/* assume a failure somewhere and all above nodes are NULL */
386
+							winner_dialog_node = node;
387
+						}
388
+						/*
389
+						if(winner_dialog_node == NULL) {
390
+							priority = get_dialog_state_priority(state);
391
+							if (priority > winner_priority) {
392
+								winner_priority = priority;
393
+								LM_DBG("new winner priority = %s (%d)\n", state, winner_priority);
394
+								winner_dialog_node = node;
375 395
 							}
376
-							*/
377
-							xmlFree(state);
378 396
 						}
397
+						*/
398
+						xmlFree(state);
379 399
 					}
380 400
 				}
381 401
 			}
... ...
@@ -460,6 +480,12 @@ int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_
460 460
 	xmlChar *dialog_id_tmp = NULL;
461 461
 	xmlNodePtr p_root;
462 462
 	xmlNodePtr node = NULL;
463
+
464
+	if(dialog_id==NULL) {
465
+		LM_WARN("dialog id is null\n");
466
+		return 0;
467
+	}
468
+
463 469
 	for (i = 0; i < total_nodes; i++)
464 470
 	{
465 471
 		p_root = xmlDocGetRootElement (xml_array[i]);
... ...
@@ -467,65 +493,74 @@ int check_relevant_state (xmlChar * dialog_id, xmlDocPtr * xml_array, int total_
467 467
 		{
468 468
 			LM_DBG ("the xml_tree root element is null\n");
469 469
 		} else {
470
-			if (p_root->children)
470
+			if (p_root->children) {
471 471
 				for (node = p_root->children; node; node = node->next)
472 472
 				{
473
-					if (node->type == XML_ELEMENT_NODE)
474
-					{
475
-						if (strcasecmp ((char*)node->name, "dialog") == 0)
476
-						{
477
-							/* Getting the node id so we would be sure
473
+					if (node->type != XML_ELEMENT_NODE) {
474
+						continue;
475
+					}
476
+					if(strcasecmp((char *)node->name, "dialog") == 0) {
477
+						/* Getting the node id so we would be sure
478 478
 							 * that terminate state from same one the same */
479
-							if(dialog_id_tmp) xmlFree(dialog_id_tmp);
480
-							dialog_id_tmp = xmlGetProp (node, (const xmlChar *) "id");
481
-							if(dialog_id_tmp) node_id = i;
479
+						if(dialog_id_tmp)
480
+							xmlFree(dialog_id_tmp);
481
+						dialog_id_tmp = xmlGetProp(node, (const xmlChar *)"id");
482
+						if(dialog_id_tmp)
483
+							node_id = i;
484
+					}
485
+					if(dialog_id_tmp == NULL) {
486
+						continue;
487
+					}
488
+					state = xmlNodeGetNodeContentByName(node, "state", NULL);
489
+					if(state) {
490
+						/* check if state is terminated for this dialog. */
491
+						if((strcasecmp(state, "terminated") == 0)
492
+								&& (node_id == i) && (node_id >= 0)
493
+								&& (strcasecmp((char *)dialog_id_tmp,
494
+											(char *)dialog_id)
495
+										   == 0)) {
496
+							LM_DBG("Found terminated in dialog %s\n",
497
+									dialog_id);
498
+							result += DEF_TERMINATED_NODE;
482 499
 						}
483
-						state = xmlNodeGetNodeContentByName (node, "state", NULL);
484
-						if (state)
485
-						{
486
-							/* check if state is terminated for this dialog. */
487
-							if ((strcasecmp (state, "terminated") == 0)
488
-									&& (node_id == i) && (node_id >= 0)
489
-									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
490
-							{
491
-								LM_DBG ("Found terminated in dialog %s\n",
492
-										dialog_id);
493
-								result += DEF_TERMINATED_NODE;
494
-							}
495
-							/* check if state is confirmed for this dialog. */
496
-							if ((strcasecmp (state, "confirmed") == 0)
497
-									&& (node_id == i) && (node_id >= 0)
498
-									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
499
-							{
500
-								LM_DBG ("Found confirmed in dialog %s\n", dialog_id);
501
-								result += DEF_CONFIRMED_NODE;
502
-							}
503
-							if ((strcasecmp (state, "early") == 0)
504
-									&& (node_id == i) && (node_id >= 0)
505
-									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
506
-							{
507
-								LM_DBG ("Found early in dialog %s\n", dialog_id);
508
-								result += DEF_EARLY_NODE;
509
-							}
510
-							if ((strcasecmp (state, "proceeding") == 0)
511
-									&& (node_id == i) && (node_id >= 0)
512
-									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
513
-							{
514
-								LM_DBG ("Found proceeding in dialog %s\n", dialog_id);
515
-								result += DEF_PROCEEDING_NODE;
516
-							}
517
-							if ((strcasecmp (state, "trying") == 0)
518
-									&& (node_id == i) && (node_id >= 0)
519
-									&& (strcasecmp ((char*)dialog_id_tmp, (char*)dialog_id) == 0))
520
-							{
521
-								LM_DBG ("Found trying in dialog %s\n", dialog_id);
522
-								result += DEF_TRYING_NODE;
523
-							}
524
-
525
-							xmlFree (state);
500
+						/* check if state is confirmed for this dialog. */
501
+						if((strcasecmp(state, "confirmed") == 0)
502
+								&& (node_id == i) && (node_id >= 0)
503
+								&& (strcasecmp((char *)dialog_id_tmp,
504
+											(char *)dialog_id)
505
+										   == 0)) {
506
+							LM_DBG("Found confirmed in dialog %s\n", dialog_id);
507
+							result += DEF_CONFIRMED_NODE;
508
+						}
509
+						if((strcasecmp(state, "early") == 0) && (node_id == i)
510
+								&& (node_id >= 0)
511
+								&& (strcasecmp((char *)dialog_id_tmp,
512
+											(char *)dialog_id)
513
+										   == 0)) {
514
+							LM_DBG("Found early in dialog %s\n", dialog_id);
515
+							result += DEF_EARLY_NODE;
516
+						}
517
+						if((strcasecmp(state, "proceeding") == 0)
518
+								&& (node_id == i) && (node_id >= 0)
519
+								&& (strcasecmp((char *)dialog_id_tmp,
520
+											(char *)dialog_id)
521
+										   == 0)) {
522
+							LM_DBG("Found proceeding in dialog %s\n",
523
+									dialog_id);
524
+							result += DEF_PROCEEDING_NODE;
526 525
 						}
526
+						if((strcasecmp(state, "trying") == 0) && (node_id == i)
527
+								&& (node_id >= 0)
528
+								&& (strcasecmp((char *)dialog_id_tmp,
529
+											(char *)dialog_id)
530
+										   == 0)) {
531
+							LM_DBG("Found trying in dialog %s\n", dialog_id);
532
+							result += DEF_TRYING_NODE;
533
+						}
534
+						xmlFree(state);
527 535
 					}
528 536
 				}
537
+			}
529 538
 		}
530 539
 	}
531 540
 	if(dialog_id_tmp) xmlFree(dialog_id_tmp);