From 03ba861433b511a8b7f77f340e06b1c20d94d33e Mon Sep 17 00:00:00 2001 From: Simon Morlat <simon.morlat@linphone.org> Date: Thu, 2 Jan 2025 05:46:05 +0100 Subject: [PATCH] Fix parsing issue when reading a hostname with a trailling dot (which is meaningfull and accepted). Remove "fast-*" variants of SIP URI, which were usefull at the time of antlr parser, but no longer now. --- src/belle_sip_headers_impl.cc | 15 ++++++++--- src/belle_sip_uri_impl.cc | 7 ++--- src/sip/sip.txt | 41 +++++++++++++++-------------- src/sip/sip_grammar.belr | Bin 20550 -> 19797 bytes src/sip/sip_parser.cc | 16 ----------- tester/belle_sip_base_uri_tester.c | 20 +++++++++++--- tester/belle_sip_tester_runtime.c | 2 +- 7 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/belle_sip_headers_impl.cc b/src/belle_sip_headers_impl.cc index 7c7da15e..5d8f6aa4 100644 --- a/src/belle_sip_headers_impl.cc +++ b/src/belle_sip_headers_impl.cc @@ -393,10 +393,17 @@ int belle_sip_header_address_equals(const belle_sip_header_address_t *addr_a, } /*fast header address implementation*/ -typedef belle_sip_header_address_t belle_sip_fast_header_address_t; -#define belle_sip_fast_header_address_parse belle_sip_header_address_fast_parse -#define belle_sip_try_fast_header_address_parse belle_sip_header_address_try_fast_parse -BELLE_SIP_ADDRESS_PARSE(fast_header_address); + +belle_sip_header_address_t *belle_sip_header_address_fast_parse(const char *address) { + return belle_sip_header_address_parse(address); +} + +/* + same as belle_sip_header_address_fast_parse but with no error messagging + */ +belle_sip_header_address_t *belle_sip_header_address_try_fast_parse(const char *address) { + return belle_sip_header_address_parse(address); +} /****************************** * Allow header inherits from header diff --git a/src/belle_sip_uri_impl.cc b/src/belle_sip_uri_impl.cc index 80652a14..39213db4 100644 --- a/src/belle_sip_uri_impl.cc +++ b/src/belle_sip_uri_impl.cc @@ -573,6 +573,7 @@ int belle_sip_uri_check_components_from_context(const belle_sip_uri_t *uri, return check_uri_components(uri, &uri_component_use_for_header_refer_to); else return check_uri_components(uri, &uri_component_use_for_external); } -/*fast uri implemenation*/ -typedef belle_sip_uri_t belle_sip_fast_uri_t; -BELLE_SIP_PARSE(fast_uri); + +BELLESIP_EXPORT belle_sip_uri_t *belle_sip_fast_uri_parse(const char *uri) { + return belle_sip_uri_parse(uri); +} diff --git a/src/sip/sip.txt b/src/sip/sip.txt index dfc56908..8d09a490 100644 --- a/src/sip/sip.txt +++ b/src/sip/sip.txt @@ -1,3 +1,16 @@ +; +; Modified rules for 'hostname' +; Indeed, the official definitions is not straightforward and are not compatible with +; the consume as much as possible belr's Loop behavior, leading to failed recognition of syntaxically correct inputs. +; + +domainlabel = alphanum / (alphanum *( alphanum / ( *("-") alphanum) ) ) ; modified to avoid an ambiguity +toplabel = alphanum / (alphanum *( alphanum / ( *("-") alphanum) ) ) ; modified to avoid an ambiguity & to relax the restriction on the 1st character as stated in RFC 1123 2.1 +fqdn = *( domainlabel "." ) toplabel ; classic fqdn, for example 'sip.example.org' +afqdn = *( domainlabel "." ) ; absolute fully qualified domain name, for example 'sip.example.org.' . This exists. +simplified-hostname = fqdn / afqdn + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Rules from RFC 3261 with IPv6Address fix from RFC 5954, changes from RFC 7235 and changes from RFC 8760 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -58,7 +71,7 @@ user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" password = *( unreserved / escaped / "&" / "=" / "+" / "$" / "," ) hostport = host [ ":" port ] host = hostname / IPv4address / IPv6reference -hostname = *( domainlabel "." ) toplabel [ "." ] +hostname = simplified-hostname ; was initially *( domainlabel "." ) toplabel [ "." ] IPv6reference = "[" IPv6address "]" h16 = 1*4HEXDIG ls32 = ( h16 ":" h16 ) / IPv4address @@ -392,16 +405,10 @@ sips-scheme = "sips:" userinfo = user [ ":" password ] "@" uri-parameters = *( (SEMI uri-parameter) / SEMI ) ; allow semi only even if not in the RFC uri-parameter = other-param ; all parameters are considered as other -domainlabel = alphanum / (alphanum *( alphanum / ( *("-") alphanum) ) ) ; modified to avoid an ambiguity -toplabel = alphanum / (alphanum *( alphanum / (*("-") alphanum ) ) ) ; modified to avoid an ambiguity & to relax the restriction on the 1st character as stated in RFC 1123 2.1 - -fast-uri = sip-uri-scheme [ userinfo ] fast-hostport uri-parameters [ headers ] -fast-hostport = fast-host [ ":" port ] -fast-host = fast-hostname / IPv6reference ; IPv4address not included because cannot discriminate quickly between 192.168.0.1 and 192.168.0.com -fast-hostname = alphanum *( alphanum / "-" / "." ) paramless-uri = sip-uri-scheme [ userinfo ] hostport [ headers ] + generic-uri = hier-part / absoluteURI generic-uri-for-from-to-contact-addr-spec = scheme ":" opaque-part-for-from-to-contact-addr-spec @@ -410,24 +417,18 @@ uric-no-slash-for-from-to-contact-addr-spec = unreserved / escaped / ":" / "@" / uric-for-from-to-contact-addr-spec = reserved-for-from-to-contact-addr-spec / unreserved / escaped reserved-for-from-to-contact-addr-spec = ":" / "@" / "&" / "=" / "+" / "$" / "/" +name-addr-with-generic-uri = [ display-name ] LAQUOT addr-spec-with-generic-uri RAQUOT +paramless-name-addr-with-generic-uri = [ quoted-display-name ] addr-spec-with-generic-uri +addr-spec-with-generic-uri = [ LWS ] ( uri / generic-uri ) [ LWS ] +paramless-addr-spec-with-generic-uri = paramless-uri / generic-uri-for-from-to-contact-addr-spec + header-address-base = name-addr-with-generic-uri / addr-spec-with-generic-uri header-address = [ LWS ] ( ( name-addr-with-generic-uri *( SEMI generic-param ) ) / paramless-name-addr-with-generic-uri / addr-spec-with-generic-uri ) [ LWS ] -name-addr-with-generic-uri = [ display-name ] LAQUOT addr-spec-with-generic-uri RAQUOT -paramless-name-addr-with-generic-uri = [ quoted-display-name ] addr-spec-with-generic-uri -addr-spec-with-generic-uri = [ LWS ] ( uri / generic-uri ) [ LWS ] -paramless-addr-spec-with-generic-uri = paramless-uri / generic-uri-for-from-to-contact-addr-spec -fast-header-address = [ LWS ] ( ( fast-name-addr-with-generic-uri *( SEMI generic-param ) ) - / fast-paramless-name-addr-with-generic-uri - / fast-addr-spec-with-generic-uri ) - [ LWS ] -fast-name-addr-with-generic-uri = [ display-name ] LAQUOT fast-addr-spec-with-generic-uri RAQUOT -fast-paramless-name-addr-with-generic-uri = [ quoted-display-name ] fast-addr-spec-with-generic-uri -fast-addr-spec-with-generic-uri = [ LWS ] ( fast-uri / generic-uri ) [ LWS ] ;;;;;;;;;;;;;;;;;;;;;;; @@ -540,5 +541,5 @@ refresher-param = "refresher" EQUAL ("uas" / "uac") ;;;;;;;;;;;;;;;;;;;;;;; header-diversion = "Diversion" ":" diversion-spec -diversion-spec = ( name-addr-with-generic-uri / paramless-addr-spec-with-generic-uri) *( SEMI diversion-params) ; Initially 1# (name-addr *( ";" diversion_params )) +diversion-spec = name-addr-with-generic-uri *( SEMI diversion-params) ; Initially 1# (name-addr *( ";" diversion_params )) diversion-params = generic-param diff --git a/src/sip/sip_grammar.belr b/src/sip/sip_grammar.belr index feda31855290004522e56bd81779a7cd3c4c520a..532f835dbf11d381237e2365a4a0113092daf51d 100644 GIT binary patch delta 161 zcmX@Mfbr@q#tm7FY^;fCg(-QHXR9b|&SLE1nq1^AGuc2`d~*noFEa;Fh5-neCeKpQ z-n>_6H!~x{<UDu9&9lTl@oI2p<QJFZCFZ6wa203f7UX26Wu~U+!Ub7Ctb+WalF1XC eq&I(8v6oY0!ln*v0T;*-3|wHhY&LZk<OKjC1vMi8 delta 389 zcmcaQi}Bb3#tm7Fn<p@KaWOM7Fifs>iQVkW<IBvPSX?rBouSNReMV{4G$2QJvKONQ z8w-TFNyq>y_@7^TvV(y5<O!C1Y+MjYE+bV|FcYlbL4a*?mM~X6SS};KxP*a`fq{Vu zq87x@OUzAW;L0p0Gb>6>OD#&xOHO5gSOb>@Ye>u~$Vkj9&1GN(av2!@0|67*EM_ja z6eEK!BO`+zBSL>ceo+ZXIXl$G$)^<MVZH#lT})RMtQh20KCYs~!qWT_sP&V%j6C6T zFg@qobfG@~?WVi=9RDun$u%xYn^y^c;^k*Sb}%#R<N`(o39gd-f}F&p)Eua@fldLt PaPw}(WVy|*4g$OY6)kf+ diff --git a/src/sip/sip_parser.cc b/src/sip/sip_parser.cc index d1395163..42bf3f76 100644 --- a/src/sip/sip_parser.cc +++ b/src/sip/sip_parser.cc @@ -150,15 +150,6 @@ bellesip::SIP::Parser::Parser() { ->setCollector("uri-parameter", make_fn(&belle_sip_parameters_add_escaped)) ->setCollector("header", make_fn(&belle_sip_uri_add_escaped_header)); - _parser->setHandler("fast-uri", make_fn(&belle_sip_uri_new)) - ->setCollector("sip-uri-scheme", make_fn(&belle_sip_uri_set_scheme)) - ->setCollector("user", make_fn(&belle_sip_uri_set_escaped_user)) - ->setCollector("password", make_fn(&belle_sip_uri_set_escaped_user_password)) - ->setCollector("fast-host", make_fn(&belle_sip_uri_set_host)) - ->setCollector("port", make_fn(&belle_sip_uri_set_port)) - ->setCollector("uri-parameter", make_fn(&belle_sip_parameters_add_escaped)) - ->setCollector("header", make_fn(&belle_sip_uri_add_escaped_header)); - _parser->setHandler("paramless-uri", make_fn(&belle_sip_uri_new)) ->setCollector("sip-uri-scheme", make_fn(&belle_sip_uri_set_scheme)) ->setCollector("user", make_fn(&belle_sip_uri_set_escaped_user)) @@ -174,13 +165,6 @@ bellesip::SIP::Parser::Parser() { ->setCollector("generic-uri", make_fn(&belle_sip_header_address_set_generic_uri)) ->setCollector("generic-param", make_fn(&belle_sip_parameters_add)); - _parser->setHandler("fast-header-address", make_fn(&belle_sip_header_address_new)) - ->setCollector("display-name", make_fn(&belle_sip_header_address_set_quoted_displayname_with_slashes)) - ->setCollector("quoted-display-name", make_fn(&belle_sip_header_address_set_quoted_displayname_with_slashes)) - ->setCollector("fast-uri", make_fn(&belle_sip_header_address_set_uri)) - ->setCollector("generic-uri", make_fn(&belle_sip_header_address_set_generic_uri)) - ->setCollector("generic-param", make_fn(&belle_sip_parameters_add)); - _parser->setHandler("generic-uri", make_fn(&belle_generic_uri_new)) ->setCollector("scheme", make_fn(&belle_generic_uri_set_scheme)) ->setCollector("user", make_fn(&belle_generic_uri_set_escaped_user)) diff --git a/tester/belle_sip_base_uri_tester.c b/tester/belle_sip_base_uri_tester.c index 60cfb6f0..3e3f3c2f 100644 --- a/tester/belle_sip_base_uri_tester.c +++ b/tester/belle_sip_base_uri_tester.c @@ -120,6 +120,19 @@ static void test_ip_host(void) { belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); } +static void testAFQDN(void) { + /* Notice the trailing dot at the end of the domain name. This is legal. */ + belle_sip_uri_t *L_uri = belle_sip_uri_parse("sip:bob@example.net."); + if (BC_ASSERT_PTR_NOT_NULL(L_uri)) { + char *l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri)); + belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); + L_uri = belle_sip_uri_parse(l_raw_uri); + belle_sip_free(l_raw_uri); + BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "example.net."); + belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); + } +} + static void test_lr(void) { belle_sip_uri_t *L_uri = belle_sip_uri_parse("sip:192.168.0.1;lr"); char *l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri)); @@ -476,10 +489,10 @@ static void test_unescaping_good_chars(void) { belle_sip_free(unescaped); char username[10] = {'F', 'r', 'a', 'n', (char)0xc3, (char)0xa7, 'o', 'i', 's', 0x0}; - unescaped = belle_sip_username_unescape_unnecessary_characters(username); - // 'ç' needs to be kept escaped + char *escaped = belle_sip_uri_to_escaped_username(username); + // 'ç' needs to be escaped const char *expected2 = "Fran%c3%a7ois"; - BC_ASSERT_STRING_EQUAL(unescaped, expected2); + BC_ASSERT_STRING_EQUAL(escaped, expected2); belle_sip_free(unescaped); } @@ -517,6 +530,7 @@ static void test_empty_password(void) { static test_t uri_tests[] = { TEST_NO_TAG("Simple URI", testSIMPLEURI), + TEST_NO_TAG("Uri with absolute fully qualified domain name", testAFQDN), TEST_NO_TAG("Complex URI", testCOMPLEXURI), TEST_NO_TAG("Escaped username", test_escaped_username), TEST_NO_TAG("Escaped username with bad chars", test_escaping_bad_chars), diff --git a/tester/belle_sip_tester_runtime.c b/tester/belle_sip_tester_runtime.c index 03450264..2680aa10 100644 --- a/tester/belle_sip_tester_runtime.c +++ b/tester/belle_sip_tester_runtime.c @@ -217,7 +217,7 @@ void belle_sip_tester_after_each(void) { bc_tester_current_suite_name(), bc_tester_current_test_name()); belle_sip_object_dump_active_objects(); belle_sip_object_flush_active_objects(); - bc_tester_printf(BELLE_SIP_LOG_MESSAGE, format); + bc_tester_printf(BELLE_SIP_LOG_MESSAGE, "%s", format); belle_sip_error("%s", format); belle_sip_free(format); -- GitLab