From c4d34984ec92b3d5252a7d5cddd85a1d3a8001ae Mon Sep 17 00:00:00 2001
From: sauwming <ming@teluu.com>
Date: Mon, 3 Oct 2022 08:07:22 +0800
Subject: [PATCH] Merge pull request from GHSA-fq45-m3f7-3mhj

* Initial patch

* Use 'pj_scan_is_eof(scanner)'

Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>

* Use 'pj_scan_is_eof(scanner)'

Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>

* Use 'pj_scan_is_eof(scanner)'

Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>

* Use `!pj_scan_is_eof` instead of manually checking `scanner->curptr < scanner->end`

Co-authored-by: Maksim Mukosey <mmukosey@gmail.com>

* Update pjlib-util/src/pjlib-util/scanner.c

Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>

* Update pjlib-util/src/pjlib-util/scanner.c

Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>

* Update pjlib-util/src/pjlib-util/scanner.c

Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>

* Revert '>=' back to '>' in pj_scan_stricmp_alnum()

* Fix error compiles.

Co-authored-by: Nanang Izzuddin <nanang@teluu.com>
Co-authored-by: Aaron Lichtman <aaronlichtman@gmail.com>
Co-authored-by: Maksim Mukosey <mmukosey@gmail.com>
---
 pjlib-util/src/pjlib-util/scanner.c | 41 +++++++++++++++++++----------
 pjmedia/src/pjmedia/rtp.c           | 11 +++++---
 pjmedia/src/pjmedia/sdp.c           | 24 ++++++++++-------
 3 files changed, 48 insertions(+), 28 deletions(-)

--- a/pjlib-util/src/pjlib-util/scanner.c
+++ b/pjlib-util/src/pjlib-util/scanner.c
@@ -195,7 +195,13 @@ PJ_DEF(void) pj_scan_skip_whitespace( pj
 
 PJ_DEF(void) pj_scan_skip_line( pj_scanner *scanner )
 {
-    char *s = pj_memchr(scanner->curptr, '\n', scanner->end - scanner->curptr);
+    char *s;
+
+    if (pj_scan_is_eof(scanner)) {
+        return;
+    }
+
+    s = pj_memchr(scanner->curptr, '\n', scanner->end - scanner->curptr);
     if (!s) {
 	scanner->curptr = scanner->end;
     } else {
@@ -264,8 +270,7 @@ PJ_DEF(void) pj_scan_get( pj_scanner *sc
 
     pj_assert(pj_cis_match(spec,0)==0);
 
-    /* EOF is detected implicitly */
-    if (!pj_cis_match(spec, *s)) {
+    if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s)) {
 	pj_scan_syntax_err(scanner);
 	return;
     }
@@ -299,8 +304,7 @@ PJ_DEF(void) pj_scan_get_unescape( pj_sc
     /* Must not match character '%' */
     pj_assert(pj_cis_match(spec,'%')==0);
 
-    /* EOF is detected implicitly */
-    if (!pj_cis_match(spec, *s) && *s != '%') {
+    if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s) && *s != '%') {
 	pj_scan_syntax_err(scanner);
 	return;
     }
@@ -436,7 +440,9 @@ PJ_DEF(void) pj_scan_get_n( pj_scanner *
     
     scanner->curptr += N;
 
-    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
+    if (!pj_scan_is_eof(scanner) &&
+	PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws)
+    {
 	pj_scan_skip_whitespace(scanner);
     }
 }
@@ -467,15 +473,16 @@ PJ_DEF(int) pj_scan_get_char( pj_scanner
 
 PJ_DEF(void) pj_scan_get_newline( pj_scanner *scanner )
 {
-    if (!PJ_SCAN_IS_NEWLINE(*scanner->curptr)) {
+    if (pj_scan_is_eof(scanner) || !PJ_SCAN_IS_NEWLINE(*scanner->curptr)) {
 	pj_scan_syntax_err(scanner);
 	return;
     }
 
+    /* We have checked scanner->curptr validity above */
     if (*scanner->curptr == '\r') {
 	++scanner->curptr;
     }
-    if (*scanner->curptr == '\n') {
+    if (!pj_scan_is_eof(scanner) && *scanner->curptr == '\n') {
 	++scanner->curptr;
     }
 
@@ -520,7 +527,9 @@ PJ_DEF(void) pj_scan_get_until( pj_scann
 
     scanner->curptr = s;
 
-    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
+    if (!pj_scan_is_eof(scanner) && PJ_SCAN_IS_PROBABLY_SPACE(*s) &&
+	scanner->skip_ws)
+    {
 	pj_scan_skip_whitespace(scanner);
     }
 }
@@ -544,7 +553,9 @@ PJ_DEF(void) pj_scan_get_until_ch( pj_sc
 
     scanner->curptr = s;
 
-    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
+    if (!pj_scan_is_eof(scanner) && PJ_SCAN_IS_PROBABLY_SPACE(*s) &&
+	scanner->skip_ws)
+    {
 	pj_scan_skip_whitespace(scanner);
     }
 }
@@ -570,7 +581,9 @@ PJ_DEF(void) pj_scan_get_until_chr( pj_s
 
     scanner->curptr = s;
 
-    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
+    if (!pj_scan_is_eof(scanner) && PJ_SCAN_IS_PROBABLY_SPACE(*s) &&
+	scanner->skip_ws)
+    {
 	pj_scan_skip_whitespace(scanner);
     }
 }
@@ -585,7 +598,9 @@ PJ_DEF(void) pj_scan_advance_n( pj_scann
 
     scanner->curptr += N;
 
-    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws) {
+    if (!pj_scan_is_eof(scanner) && 
+	PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws)
+    {
 	pj_scan_skip_whitespace(scanner);
     }
 }
@@ -636,5 +651,3 @@ PJ_DEF(void) pj_scan_restore_state( pj_s
     scanner->line = state->line;
     scanner->start_line = state->start_line;
 }
-
-
--- a/pjmedia/src/pjmedia/rtp.c
+++ b/pjmedia/src/pjmedia/rtp.c
@@ -188,6 +188,11 @@ PJ_DEF(pj_status_t) pjmedia_rtp_decode_r
     /* Payload is located right after header plus CSRC */
     offset = sizeof(pjmedia_rtp_hdr) + ((*hdr)->cc * sizeof(pj_uint32_t));
 
+    /* Check that offset is less than packet size */
+    if (offset >= pkt_len) {
+        return PJMEDIA_RTP_EINLEN;
+    }
+
     /* Decode RTP extension. */
     if ((*hdr)->x) {
         if (offset + sizeof (pjmedia_rtp_ext_hdr) > (unsigned)pkt_len)
@@ -202,8 +207,8 @@ PJ_DEF(pj_status_t) pjmedia_rtp_decode_r
 	dec_hdr->ext_len = 0;
     }
 
-    /* Check that offset is less than packet size */
-    if (offset > pkt_len)
+    /* Check again that offset is still less than packet size */
+    if (offset >= pkt_len)
 	return PJMEDIA_RTP_EINLEN;
 
     /* Find and set payload. */
@@ -393,5 +398,3 @@ void pjmedia_rtp_seq_update( pjmedia_rtp
 	seq_status->status.value = st.status.value;
     }
 }
-
-
--- a/pjmedia/src/pjmedia/sdp.c
+++ b/pjmedia/src/pjmedia/sdp.c
@@ -983,13 +983,13 @@ static void parse_version(pj_scanner *sc
     ctx->last_error = PJMEDIA_SDP_EINVER;
 
     /* check equal sign */
-    if (*(scanner->curptr+1) != '=') {
+    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
 	on_scanner_error(scanner);
 	return;
     }
 
     /* check version is 0 */
-    if (*(scanner->curptr+2) != '0') {
+    if (scanner->curptr+2 >= scanner->end || *(scanner->curptr+2) != '0') {
 	on_scanner_error(scanner);
 	return;
     }
@@ -1006,7 +1006,7 @@ static void parse_origin(pj_scanner *sca
     ctx->last_error = PJMEDIA_SDP_EINORIGIN;
 
     /* check equal sign */
-    if (*(scanner->curptr+1) != '=') {
+    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
 	on_scanner_error(scanner);
 	return;
     }
@@ -1052,7 +1052,7 @@ static void parse_time(pj_scanner *scann
     ctx->last_error = PJMEDIA_SDP_EINTIME;
 
     /* check equal sign */
-    if (*(scanner->curptr+1) != '=') {
+    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
 	on_scanner_error(scanner);
 	return;
     }
@@ -1080,7 +1080,7 @@ static void parse_generic_line(pj_scanne
     ctx->last_error = PJMEDIA_SDP_EINSDP;
 
     /* check equal sign */
-    if (*(scanner->curptr+1) != '=') {
+    if ((scanner->curptr+1 >= scanner->end) || *(scanner->curptr+1) != '=') {
 	on_scanner_error(scanner);
 	return;
     }
@@ -1149,7 +1149,7 @@ static void parse_media(pj_scanner *scan
     ctx->last_error = PJMEDIA_SDP_EINMEDIA;
 
     /* check the equal sign */
-    if (*(scanner->curptr+1) != '=') {
+    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
 	on_scanner_error(scanner);
 	return;
     }
@@ -1164,6 +1164,10 @@ static void parse_media(pj_scanner *scan
     /* port */
     pj_scan_get(scanner, &cs_token, &str);
     med->desc.port = (unsigned short)pj_strtoul(&str);
+    if (pj_scan_is_eof(scanner)) {
+        on_scanner_error(scanner);
+        return;
+    }
     if (*scanner->curptr == '/') {
 	/* port count */
 	pj_scan_get_char(scanner);
@@ -1175,7 +1179,7 @@ static void parse_media(pj_scanner *scan
     }
 
     if (pj_scan_get_char(scanner) != ' ') {
-	PJ_THROW(SYNTAX_ERROR);
+	on_scanner_error(scanner);
     }
 
     /* transport */
@@ -1183,7 +1187,7 @@ static void parse_media(pj_scanner *scan
 
     /* format list */
     med->desc.fmt_count = 0;
-    while (*scanner->curptr == ' ') {
+    while (scanner->curptr < scanner->end && *scanner->curptr == ' ') {
 	pj_str_t fmt;
 
 	pj_scan_get_char(scanner);
@@ -1223,7 +1227,7 @@ static pjmedia_sdp_attr *parse_attr( pj_
     attr = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_attr);
 
     /* check equal sign */
-    if (*(scanner->curptr+1) != '=') {
+    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
 	on_scanner_error(scanner);
 	return NULL;
     }
@@ -1242,7 +1246,7 @@ static pjmedia_sdp_attr *parse_attr( pj_
 	    pj_scan_get_char(scanner);
 
 	/* get value */
-	if (*scanner->curptr != '\r' && *scanner->curptr != '\n') {
+	if (!pj_scan_is_eof(scanner) && *scanner->curptr != '\r' && *scanner->curptr != '\n') {
 	    pj_scan_get_until_chr(scanner, "\r\n", &attr->value);
 	} else {
 	    attr->value.ptr = NULL;
