Changeset 5682 for pjproject/trunk/pjsip/src/pjsip/sip_parser.c
- Timestamp:
- Nov 8, 2017 2:58:18 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip/sip_parser.c
r5280 r5682 35 35 #include <pj/ctype.h> 36 36 #include <pj/assert.h> 37 #include <pj/limits.h> 37 38 38 39 #define THIS_FILE "sip_parser.c" … … 94 95 */ 95 96 int PJSIP_SYN_ERR_EXCEPTION = -1; 97 int PJSIP_EINVAL_ERR_EXCEPTION = -2; 96 98 97 99 /* Parser constants */ … … 206 208 #define parser_stricmp(s1, s2) (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2)) 207 209 208 209 210 /* Get a token and unescape */ 210 211 PJ_INLINE(void) parser_get_and_unescape(pj_scanner *scanner, pj_pool_t *pool, … … 224 225 } 225 226 226 227 228 227 /* Syntax error handler for parser. */ 229 228 static void on_syntax_error(pj_scanner *scanner) … … 231 230 PJ_UNUSED_ARG(scanner); 232 231 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); 232 } 233 234 /* Syntax error handler for parser. */ 235 static void on_str_parse_error(const pj_str_t *str, int rc) 236 { 237 char *s; 238 239 switch(rc) { 240 case PJ_EINVAL: 241 s = "NULL input string, invalid input string, or NULL return "\ 242 "value pointer"; 243 break; 244 case PJ_ETOOSMALL: 245 s = "String value was less than the minimum allowed value."; 246 break; 247 case PJ_ETOOBIG: 248 s = "String value was greater than the maximum allowed value."; 249 break; 250 default: 251 s = "Unknown error"; 252 } 253 254 if (str) { 255 PJ_LOG(1, (THIS_FILE, "Error parsing '%.*s': %s", 256 (int)str->slen, str->ptr, s)); 257 } else { 258 PJ_LOG(1, (THIS_FILE, "Can't parse input string: %s", s)); 259 } 260 PJ_THROW(PJSIP_EINVAL_ERR_EXCEPTION); 261 } 262 263 static void strtoi_validate(const pj_str_t *str, int min_val, 264 int max_val, int *value) 265 { 266 long retval; 267 pj_status_t status; 268 269 if (!str || !value) { 270 on_str_parse_error(str, PJ_EINVAL); 271 } 272 status = pj_strtol2(str, &retval); 273 if (status != PJ_EINVAL) { 274 if (min_val > retval) { 275 *value = min_val; 276 status = PJ_ETOOSMALL; 277 } else if (retval > max_val) { 278 *value = max_val; 279 status = PJ_ETOOBIG; 280 } else 281 *value = (int)retval; 282 } 283 284 if (status != PJ_SUCCESS) 285 on_str_parse_error(str, status); 233 286 } 234 287 … … 286 339 287 340 /* 341 * Invalid value exception. 342 */ 343 pj_assert (PJSIP_EINVAL_ERR_EXCEPTION == -2); 344 status = pj_exception_id_alloc("PJSIP invalid value error", 345 &PJSIP_EINVAL_ERR_EXCEPTION); 346 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 347 348 /* 288 349 * Init character input spec (cis) 289 350 */ … … 503 564 pj_exception_id_free(PJSIP_SYN_ERR_EXCEPTION); 504 565 PJSIP_SYN_ERR_EXCEPTION = -1; 566 567 pj_exception_id_free(PJSIP_EINVAL_ERR_EXCEPTION); 568 PJSIP_EINVAL_ERR_EXCEPTION = -2; 505 569 } 506 570 pj_leave_critical_section(); … … 767 831 768 832 /* Determine if a message has been received. */ 769 PJ_DEF(pj_ bool_t) pjsip_find_msg( const char *buf, pj_size_t size,833 PJ_DEF(pj_status_t) pjsip_find_msg( const char *buf, pj_size_t size, 770 834 pj_bool_t is_datagram, pj_size_t *msg_size) 771 835 { … … 777 841 int content_length = -1; 778 842 pj_str_t cur_msg; 843 pj_status_t status = PJ_SUCCESS; 779 844 const pj_str_t end_hdr = { "\n\r\n", 3}; 780 845 … … 837 902 838 903 /* Found a valid Content-Length header. */ 839 content_length = pj_strtoul(&str_clen); 904 strtoi_validate(&str_clen, PJSIP_MIN_CONTENT_LENGTH, 905 PJSIP_MAX_CONTENT_LENGTH, &content_length); 840 906 } 841 907 PJ_CATCH_ANY { 908 int eid = PJ_GET_EXCEPTION(); 909 if (eid == PJSIP_SYN_ERR_EXCEPTION) { 910 status = PJSIP_EMISSINGHDR; 911 } else if (eid == PJSIP_EINVAL_ERR_EXCEPTION) { 912 status = PJSIP_EINVALIDHDR; 913 } 842 914 content_length = -1; 843 915 } … … 859 931 /* Found Content-Length? */ 860 932 if (content_length == -1) { 861 return PJSIP_EMISSINGHDR;933 return status; 862 934 } 863 935 … … 939 1011 pjsip_parser_err_report *err_list) 940 1012 { 941 pj_bool_t parsing_headers; 942 pjsip_msg *msg = NULL; 1013 /* These variables require "volatile" so their values get 1014 * preserved when re-entering the PJ_TRY block after an error. 1015 */ 1016 volatile pj_bool_t parsing_headers; 1017 pjsip_msg *volatile msg = NULL; 1018 pjsip_ctype_hdr *volatile ctype_hdr = NULL; 1019 943 1020 pj_str_t hname; 944 pjsip_ctype_hdr *ctype_hdr = NULL;945 1021 pj_scanner *scanner = ctx->scanner; 946 1022 pj_pool_t *pool = ctx->pool; … … 1024 1100 } 1025 1101 1026 1027 1102 /* Single parse of header line can produce multiple headers. 1028 1103 * For example, if one Contact: header contains Contact list … … 1268 1343 pj_scan_get_char(scanner); 1269 1344 pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &port); 1270 *p_port = pj_strtoul(&port);1345 strtoi_validate(&port, PJSIP_MIN_PORT, PJSIP_MAX_PORT, p_port); 1271 1346 } else { 1272 1347 *p_port = 0; … … 1459 1534 1460 1535 } else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) { 1461 url->ttl_param = pj_strtoul(&pvalue);1462 1536 strtoi_validate(&pvalue, PJSIP_MIN_TTL, PJSIP_MAX_TTL, 1537 &url->ttl_param); 1463 1538 } else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) { 1464 1539 url->maddr_param = pvalue; … … 1596 1671 parse_sip_version(scanner); 1597 1672 pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &token); 1598 status_line->code = pj_strtoul(&token); 1673 strtoi_validate(&token, PJSIP_MIN_STATUS_CODE, PJSIP_MAX_STATUS_CODE, 1674 &status_line->code); 1599 1675 if (*scanner->curptr != '\r' && *scanner->curptr != '\n') 1600 1676 pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &status_line->reason); … … 1781 1857 char *dot_pos = (char*) pj_memchr(pvalue.ptr, '.', pvalue.slen); 1782 1858 if (!dot_pos) { 1783 hdr->q1000 = pj_strtoul(&pvalue) * 1000; 1859 strtoi_validate(&pvalue, PJSIP_MIN_Q1000, PJSIP_MAX_Q1000, 1860 &hdr->q1000); 1861 hdr->q1000 *= 1000; 1784 1862 } else { 1785 1863 pj_str_t tmp = pvalue; 1864 unsigned long qval_frac; 1786 1865 1787 1866 tmp.slen = dot_pos - pvalue.ptr; 1788 hdr->q1000 = pj_strtoul(&tmp) * 1000; 1867 strtoi_validate(&tmp, PJSIP_MIN_Q1000, PJSIP_MAX_Q1000, 1868 &hdr->q1000); 1869 hdr->q1000 *= 1000; 1789 1870 1790 1871 pvalue.slen = (pvalue.ptr+pvalue.slen) - (dot_pos+1); 1791 1872 pvalue.ptr = dot_pos + 1; 1792 hdr->q1000 += pj_strtoul_mindigit(&pvalue, 3); 1873 if (pvalue.slen > 3) { 1874 pvalue.slen = 3; 1875 } 1876 qval_frac = pj_strtoul_mindigit(&pvalue, 3); 1877 if ((unsigned)hdr->q1000 > (PJ_MAXINT32 - qval_frac)) { 1878 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); 1879 } 1880 hdr->q1000 += qval_frac; 1793 1881 } 1794 } else if (!parser_stricmp(pname, pconst.pjsip_EXPIRES_STR) && pvalue.slen) { 1795 hdr->expires = pj_strtoul(&pvalue); 1796 1882 } else if (!parser_stricmp(pname, pconst.pjsip_EXPIRES_STR) && 1883 pvalue.slen) 1884 { 1885 strtoi_validate(&pvalue, PJSIP_MIN_EXPIRES, PJSIP_MAX_EXPIRES, 1886 &hdr->expires); 1797 1887 } else { 1798 1888 pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param); … … 1891 1981 { 1892 1982 pj_str_t cseq, method; 1893 pjsip_cseq_hdr *hdr; 1983 pjsip_cseq_hdr *hdr = NULL; 1984 int cseq_val = 0; 1985 1986 pj_scan_get( ctx->scanner, &pconst.pjsip_DIGIT_SPEC, &cseq); 1987 strtoi_validate(&cseq, PJSIP_MIN_CSEQ, PJSIP_MAX_CSEQ, &cseq_val); 1894 1988 1895 1989 hdr = pjsip_cseq_hdr_create(ctx->pool); 1896 pj_scan_get( ctx->scanner, &pconst.pjsip_DIGIT_SPEC, &cseq); 1897 hdr->cseq = pj_strtoul(&cseq); 1990 hdr->cseq = cseq_val; 1898 1991 1899 1992 pj_scan_get( ctx->scanner, &pconst.pjsip_TOKEN_SPEC, &method); 1993 parse_hdr_end( ctx->scanner ); 1994 1900 1995 pjsip_method_init_np(&hdr->method, &method); 1901 1902 parse_hdr_end( ctx->scanner ); 1903 1904 if (ctx->rdata) 1996 if (ctx->rdata) { 1905 1997 ctx->rdata->msg_info.cseq = hdr; 1998 } 1906 1999 1907 2000 return (pjsip_hdr*)hdr; … … 1985 2078 1986 2079 pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &tmp); 1987 hdr->ivalue = pj_strtoul(&tmp); 2080 strtoi_validate(&tmp, PJSIP_MIN_RETRY_AFTER, PJSIP_MAX_RETRY_AFTER, 2081 &hdr->ivalue); 1988 2082 1989 2083 while (!pj_scan_is_eof(scanner) && *scanner->curptr!='\r' && … … 2074 2168 2075 2169 } else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) { 2076 hdr->ttl_param = pj_strtoul(&pvalue); 2170 strtoi_validate(&pvalue, PJSIP_MIN_TTL, PJSIP_MAX_TTL, 2171 &hdr->ttl_param); 2077 2172 2078 2173 } else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) { … … 2083 2178 2084 2179 } else if (!parser_stricmp(pname, pconst.pjsip_RPORT_STR)) { 2085 if (pvalue.slen) 2086 hdr->rport_param = pj_strtoul(&pvalue); 2087 else 2180 if (pvalue.slen) { 2181 strtoi_validate(&pvalue, PJSIP_MIN_PORT, PJSIP_MAX_PORT, 2182 &hdr->rport_param); 2183 } else 2088 2184 hdr->rport_param = 0; 2089 2185 } else { … … 2214 2310 pj_scan_get_char(scanner); 2215 2311 pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &digit); 2216 hdr->sent_by.port = pj_strtoul(&digit); 2312 strtoi_validate(&digit, PJSIP_MIN_PORT, PJSIP_MAX_PORT, 2313 &hdr->sent_by.port); 2217 2314 } 2218 2315 … … 2299 2396 { 2300 2397 enum { STOP_ON_ERROR = 1 }; 2398 pj_str_t hname; 2301 2399 pj_scanner scanner; 2302 2400 pjsip_parse_ctx ctx; 2303 pj_str_t hname; 2401 2304 2402 PJ_USE_EXCEPTION; 2305 2403 … … 2324 2422 hname.slen = 0; 2325 2423 2326 /* Get hname. */ 2424 /* Get hname. */ 2327 2425 pj_scan_get( &scanner, &pconst.pjsip_TOKEN_SPEC, &hname); 2328 2426 if (pj_scan_get_char( &scanner ) != ':') {
Note: See TracChangeset
for help on using the changeset viewer.