freeswitch/sofia-sip

heap buffer underflow in TAG_TYPE_OF(t)

kamalesh-p opened this issue · 0 comments

ISSUE:
when using mod_sofia with Address Sanitizer causes a stack-buffer-underflow error

ERROR: AddressSanitizer: stack-buffer-underflow
READ of size 8 at 0x7f3bfcdc0420 thread T14
#0     t_len                       sofia-sip/su_tag_inline.h:140
#1     tl_len                      sofia-sip/libsofia-sip-ua/su/su_taglist.c:250
#2     tl_adup                     sofia-sip/libsofia-sip-ua/su/su_taglist.c:315
#3     nua_create                  sofia-sip/libsofia-sip-ua/nua/nua.c:154
#4     sofia_profile_thread_run    src/mod/endpoints/mod_sofia/sofia.c:3220

This frame has 1 object(s):
    [32, 88) 'ta'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
    (longjmp and C++ exceptions are supported)

TEMPORARY FIX:
I added the below code to temporarily avoid this error

#if SU_HAVE_TAGSTACK
 /* All arguments are saved into stack (left-to-right) */
#define ta_start(ta, t, v)						\
   do {									\
    tag_type_t ta_start__tag = (t); tag_value_t ta_start__value = (v);	\
    va_start((ta).ap, (v));						\
    while ((ta_start__tag) == tag_next && (ta_start__value) != 0) {	\
      ta_start__tag = ((tagi_t *)ta_start__value)->t_tag;		\
      if (ta_start__tag == tag_null || ta_start__tag == NULL)		\
	break;								\
      if (ta_start__tag == tag_next) {					\
	ta_start__value = ((tagi_t *)ta_start__value)->t_value; }	\
      else {								\
	ta_start__tag = tag_next;					\
	break;								\
      }									\
    }									\
    (ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value;	\
    if (ta_start__tag != NULL &&					\
	ta_start__tag != tag_null &&					\
	ta_start__tag != tag_next) {					\
      (ta).tl[1].t_tag = 0;					        \  //EDITED_BY_KAMALESH
      (ta).tl[1].t_value = (tag_value_t)(&(v) + 1);			\
    } else {								\
      (ta).tl[1].t_tag = 0; (ta).tl[1].t_value = (tag_value_t)0;	\
    }									\
  } while(0)
#else
 /* Tagged arguments are in registers - copy all of them. */
#define ta_start(ta, t, v)						\
   do {									\
    tag_type_t ta_start__tag = (t); tag_value_t ta_start__value = (v);	\
    va_start((ta).ap, (v));						\
    while ((ta_start__tag) == tag_next && (ta_start__value) != 0) {	\
      ta_start__tag = ((tagi_t *)ta_start__value)->t_tag;		\
      if (ta_start__tag == tag_null || ta_start__tag == NULL)		\
	break;								\
      if (ta_start__tag == tag_next) {					\
	ta_start__value = ((tagi_t *)ta_start__value)->t_value;		\
      } else {								\
	ta_start__tag = tag_next;					\
	break;								\
      }									\
    }									\
    (ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value;	\
    if (ta_start__tag != NULL &&					\
	ta_start__tag != tag_null &&					\
	ta_start__tag != tag_next) {					\
      va_list ta_start__ap;						\
      su_va_copy(ta_start__ap, (ta).ap);				\
      (ta).tl[1].t_tag = 0;				        	\  //EDITED_BY_KAMALESH
      (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap);		\
      va_end(ta_start__ap);						\
    } else {								\
      (ta).tl[1].t_tag = 0; (ta).tl[1].t_value = (tag_value_t)0;	\  //EDITED_BY_KAMALESH
    }									\
  } while(0)
#endif