From 5bba86aff1c5236d9f106e3e13fbfa4954556898 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Wed, 4 Nov 2009 13:17:31 +0000 Subject: Fixed ticket #940: Multiple header rows with the same name may not be completely processed by PJSIP modules - the parser now collect and aggregate all Supported/Require header fields into single header git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2985 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsip/sip_transport.h | 9 ++++++- pjsip/src/pjsip/sip_parser.c | 50 +++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 12 deletions(-) (limited to 'pjsip') diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h index 0e461638..b971762f 100644 --- a/pjsip/include/pjsip/sip_transport.h +++ b/pjsip/include/pjsip/sip_transport.h @@ -385,9 +385,16 @@ struct pjsip_rx_data /** Content-length header. */ pjsip_clen_hdr *clen; - /** The first Require header. */ + /** "Require" header containing aggregates of all Require + * headers found in the message, or NULL. + */ pjsip_require_hdr *require; + /** "Supported" header containing aggregates of all Supported + * headers found in the message, or NULL. + */ + pjsip_supported_hdr *supported; + /** The list of error generated by the parser when parsing this message. */ diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index a5a8e033..5f004ca1 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -1007,11 +1007,17 @@ parse_headers: if (handler) { hdr = (*handler)(ctx); + /* Note: + * hdr MAY BE NULL, if parsing does not yield a new header + * instance, e.g. the values have been added to existing + * header. See http://trac.pjsip.org/repos/ticket/940 + */ + /* Check if we've just parsed a Content-Type header. * We will check for a message body if we've got Content-Type * header. */ - if (hdr->type == PJSIP_H_CONTENT_TYPE) { + if (hdr && hdr->type == PJSIP_H_CONTENT_TYPE) { ctype_hdr = (pjsip_ctype_hdr*)hdr; } @@ -1027,7 +1033,8 @@ parse_headers: * different Contact headers. * So here we must insert list instead of just insert one header. */ - pj_list_insert_nodes_before(&msg->hdr, hdr); + if (hdr) + pj_list_insert_nodes_before(&msg->hdr, hdr); /* Parse until EOF or an empty line is found. */ } while (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)); @@ -1639,7 +1646,14 @@ static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr, goto end; } - pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE, &hdr->values[0]); + if (hdr->count >= PJ_ARRAY_SIZE(hdr->values)) { + /* Too many elements */ + on_syntax_error(scanner); + return; + } + + pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE, + &hdr->values[hdr->count]); hdr->count++; while (*scanner->curptr == ',') { @@ -1917,13 +1931,19 @@ static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx ) /* Parse Require: header. */ static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx ) { - pjsip_require_hdr *hdr = pjsip_require_hdr_create(ctx->pool); - parse_generic_array_hdr(hdr, ctx->scanner); + pjsip_require_hdr *hdr; + pj_bool_t new_hdr = (ctx->rdata->msg_info.require == NULL); + + if (ctx->rdata && ctx->rdata->msg_info.require) { + hdr = ctx->rdata->msg_info.require; + } else { + hdr = pjsip_require_hdr_create(ctx->pool); + ctx->rdata->msg_info.require = hdr; + } - if (ctx->rdata && ctx->rdata->msg_info.require == NULL) - ctx->rdata->msg_info.require = hdr; + parse_generic_array_hdr(hdr, ctx->scanner); - return (pjsip_hdr*)hdr; + return new_hdr ? (pjsip_hdr*)hdr : NULL; } /* Parse Retry-After: header. */ @@ -1960,12 +1980,20 @@ static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx) /* Parse Supported: header. */ static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx) { - pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(ctx->pool); + pjsip_supported_hdr *hdr; + pj_bool_t new_hdr = (ctx->rdata->msg_info.supported == NULL); + + if (ctx->rdata && ctx->rdata->msg_info.supported) { + hdr = ctx->rdata->msg_info.supported; + } else { + hdr = pjsip_supported_hdr_create(ctx->pool); + ctx->rdata->msg_info.supported = hdr; + } + parse_generic_array_hdr(hdr, ctx->scanner); - return (pjsip_hdr*)hdr; + return new_hdr ? (pjsip_hdr*)hdr : NULL; } - /* Parse To: header. */ static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx ) { -- cgit v1.2.3