Index: channels/sip/include/reqresp_parser.h =================================================================== --- channels/sip/include/reqresp_parser.h (revision 378204) +++ channels/sip/include/reqresp_parser.h (working copy) @@ -90,6 +90,14 @@ */ char *get_in_brackets(char *tmp); +/*! \brief Get text in brackets on a const without copy + * + * \retval 0 success + * \retval -1 failure + * \retval 1 no brackets so got all + */ +int get_in_brackets_const(const char *src,const char **start,int *length); + /*! \brief Get text in brackets and any trailing residue * * \retval 0 success Index: channels/sip/reqresp_parser.c =================================================================== --- channels/sip/reqresp_parser.c (revision 378204) +++ channels/sip/reqresp_parser.c (working copy) @@ -948,6 +948,59 @@ return res; } +int get_in_brackets_const(const char *src,const char **start,int *length) +{ + const char *parse = src; + const char *first_bracket; + const char *second_bracket; + + if (start == NULL) { + return -1; + } + if (length == NULL) { + return -1; + } + *start = NULL; + *length = -1; + if (ast_strlen_zero(src)) { + return 1; + } + + /* + * Skip any quoted text until we find the part in brackets. + * On any error give up and return -1 + */ + while ( (first_bracket = strchr(parse, '<')) ) { + const char *first_quote = strchr(parse, '"'); + first_bracket++; + if (!first_quote || first_quote >= first_bracket) { + break; /* no need to look at quoted part */ + } + /* the bracket is within quotes, so ignore it */ + parse = find_closing_quote(first_quote + 1, NULL); + if (!*parse) { + ast_log(LOG_WARNING, "No closing quote found in '%s'\n", src); + return -1; + } + parse++; + } + + /* Require a first bracket. Unlike get_in_brackets_full, this procedure is passed a const, + * so it can expect a pointer to an original value */ + if (!first_bracket) { + ast_log(LOG_WARNING, "No opening bracket found in '%s'\n", src); + return 1; + } + + if ((second_bracket = strchr(first_bracket, '>'))) { + *start = first_bracket; + *length = second_bracket - first_bracket; + return 0; + } + ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", src); + return -1; +} + int get_in_brackets_full(char *tmp,char **out,char **residue) { const char *parse = tmp; Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 378204) +++ channels/chan_sip.c (working copy) @@ -16134,21 +16134,25 @@ /* 1st we pass through all the hops in any Record-Route headers */ for (;;) { /* Each Record-Route header */ - char rr_copy[256]; - char *rr_copy_ptr; - char *rr_iter; + int len = 0; + const char *uri; rr = __get_header(req, "Record-Route", &start); if (*rr == '\0') { break; } - ast_copy_string(rr_copy, rr, sizeof(rr_copy)); - rr_copy_ptr = rr_copy; - while ((rr_iter = strsep(&rr_copy_ptr, ","))) { /* Each route entry */ - char *uri = get_in_brackets(rr_iter); - len = strlen(uri) + 1; - /* Make a struct route */ + while (!get_in_brackets_const(rr, &uri, &len)) { + len++; + rr = strchr(rr, ','); + if(rr >= uri && rr < (uri + len)) { + /* comma beforeinside brackets*/ + const char *next_br = strchr(rr, '<'); + if (next_br && next_br < (uri + len)) { + rr++; + continue; + } + continue; + } if ((thishop = ast_malloc(sizeof(*thishop) + len))) { - /* ast_calloc is not needed because all fields are initialized in this block */ ast_copy_string(thishop->hop, uri, len); ast_debug(2, "build_route: Record-Route hop: <%s>\n", thishop->hop); /* Link in */ @@ -16171,6 +16175,13 @@ tail = thishop; } } + rr = strchr(uri + len, ','); + if (rr == NULL) { + /* No more field-values, we're done with this header */ + break; + } + /* Advance past comma */ + rr++; } }