CVE-2022-24786: Out-of-bounds Write (CWE-787)
value: PJSIP is a free and open source multimedia communication library written in C. PJSIP versions 2.12 and prior do not parse incoming RTCP feedback RPSI (Reference Picture Selection Indication) packet, but any app that directly uses pjmedia_rtcp_fb_parse_rpsi() will be affected. A patch is available in the `master` branch of the `pjsip/pjproject` GitHub repository. There are currently no known workarounds.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 9.8
Published: 2022-04-06T14:15Z
Repository: https://github.com/pjsip/pjproject
Language: C
Files changed: pjmedia/include/pjmedia/rtcp.h, pjmedia/src/pjmedia/rtcp.c, pjmedia/src/pjmedia/rtcp_fb.c
Commit date: 2022-04-06 11:40:09 +0800
Commit message: Merge pull request from GHSA-vhxv-phmx-g52q

* Prevent OOB read/write when parsing RTCP FB RPSI

* Add log information

* Modification based on comments.
Diff: diff --git a/pjmedia/include/pjmedia/rtcp.h b/pjmedia/include/pjmedia/rtcp.h
index 9fc53657ae..f4bff12cda 100644
--- a/pjmedia/include/pjmedia/rtcp.h
+++ b/pjmedia/include/pjmedia/rtcp.h
@@ -113,10 +113,19 @@ typedef struct pjmedia_rtcp_common
     unsigned	    length:16;	/**< packet length          */
     pj_uint32_t	    ssrc;	/**< SSRC identification    */
 } pjmedia_rtcp_common;
 
 
+/**
+ * RTCP feedback common header.
+ */
+typedef struct pjmedia_rtcp_fb_common
+{
+    pjmedia_rtcp_common rtcp_common;
+    pj_uint32_t	    ssrc_src;	/**< SSRC media source	    */
+} pjmedia_rtcp_fb_common;
+
 /**
  * This structure declares default RTCP packet (SR) that is sent by pjmedia.
  * Incoming RTCP packet may have different format, and must be parsed
  * manually by application.
  */
@@ -232,10 +241,12 @@ typedef struct pjmedia_rtcp_stat
 typedef struct pjmedia_rtcp_session
 {
     char		   *name;	/**< Name identification.	    */
     pjmedia_rtcp_sr_pkt	    rtcp_sr_pkt;/**< Cached RTCP SR packet.	    */
     pjmedia_rtcp_rr_pkt	    rtcp_rr_pkt;/**< Cached RTCP RR packet.	    */
+    pjmedia_rtcp_fb_common  rtcp_fb_com;/**< Cached RTCP feedback common 
+					     header packet.		    */
     
     pjmedia_rtp_seq_session seq_ctrl;	/**< RTCP sequence number control.  */
     unsigned		    rtp_last_ts;/**< Last timestamp in RX RTP pkt.  */
 
     unsigned		    clock_rate;	/**< Clock rate of the stream	    */
diff --git a/pjmedia/src/pjmedia/rtcp.c b/pjmedia/src/pjmedia/rtcp.c
index 4f40e7fe10..ceb1b78fcd 100644
--- a/pjmedia/src/pjmedia/rtcp.c
+++ b/pjmedia/src/pjmedia/rtcp.c
@@ -240,10 +240,15 @@ PJ_DEF(void) pjmedia_rtcp_init2( pjmedia_rtcp_session *sess,
     pj_memcpy(&sess->rtcp_rr_pkt.common, &sr_pkt->common, 
 	      sizeof(pjmedia_rtcp_common));
     sess->rtcp_rr_pkt.common.pt = RTCP_RR;
     sess->rtcp_rr_pkt.common.length = pj_htons(7);
 
+    /* Copy to RTCP FB common header */
+    pj_memcpy(&sess->rtcp_fb_com, &sr_pkt->common, 
+	      sizeof(pjmedia_rtcp_common));
+    sess->rtcp_fb_com.ssrc_src = 0;
+
     /* Get time and timestamp base and frequency */
     pj_gettimeofday(&now);
     sess->tv_base = now;
     pj_get_timestamp(&sess->ts_base);
     pj_get_timestamp_freq(&sess->ts_freq);
diff --git a/pjmedia/src/pjmedia/rtcp_fb.c b/pjmedia/src/pjmedia/rtcp_fb.c
index a2a0140f34..d4e444caab 100644
--- a/pjmedia/src/pjmedia/rtcp_fb.c
+++ b/pjmedia/src/pjmedia/rtcp_fb.c
@@ -41,26 +41,26 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_build_nack(
 					void *buf,
 					pj_size_t *length,
 					unsigned nack_cnt,
 					const pjmedia_rtcp_fb_nack nack[])
 {
-    pjmedia_rtcp_common *hdr;
+    pjmedia_rtcp_fb_common *hdr;
     pj_uint8_t *p;
     unsigned len, i;
 
     PJ_ASSERT_RETURN(session && buf && length && nack_cnt && nack, PJ_EINVAL);
 
     len = (3 + nack_cnt) * 4;
     if (len > *length)
 	return PJ_ETOOSMALL;
 
     /* Build RTCP-FB NACK header */
-    hdr = (pjmedia_rtcp_common*)buf;
-    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
-    hdr->pt = RTCP_RTPFB;
-    hdr->count = 1; /* FMT = 1 */
-    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
+    hdr = (pjmedia_rtcp_fb_common*)buf;
+    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
+    hdr->rtcp_common.pt = RTCP_RTPFB;
+    hdr->rtcp_common.count = 1; /* FMT = 1 */
+    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
 
     /* Build RTCP-FB NACK FCI */
     p = (pj_uint8_t*)hdr + sizeof(*hdr);
     for (i = 0; i < nack_cnt; ++i) {
 	pj_uint16_t val;
@@ -84,25 +84,25 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_build_nack(
 PJ_DEF(pj_status_t) pjmedia_rtcp_fb_build_pli(
 					pjmedia_rtcp_session *session, 
 					void *buf,
 					pj_size_t *length)
 {
-    pjmedia_rtcp_common *hdr;
+    pjmedia_rtcp_fb_common *hdr;
     unsigned len;
 
     PJ_ASSERT_RETURN(session && buf && length, PJ_EINVAL);
 
     len = 12;
     if (len > *length)
 	return PJ_ETOOSMALL;
 
     /* Build RTCP-FB PLI header */
-    hdr = (pjmedia_rtcp_common*)buf;
-    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
-    hdr->pt = RTCP_PSFB;
-    hdr->count = 1; /* FMT = 1 */
-    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
+    hdr = (pjmedia_rtcp_fb_common*)buf;
+    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
+    hdr->rtcp_common.pt = RTCP_PSFB;
+    hdr->rtcp_common.count = 1; /* FMT = 1 */
+    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
 
     /* Finally */
     *length = len;
 
     return PJ_SUCCESS;
@@ -117,26 +117,26 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_build_sli(
 					void *buf,
 					pj_size_t *length,
 					unsigned sli_cnt,
 					const pjmedia_rtcp_fb_sli sli[])
 {
-    pjmedia_rtcp_common *hdr;
+    pjmedia_rtcp_fb_common *hdr;
     pj_uint8_t *p;
     unsigned len, i;
 
     PJ_ASSERT_RETURN(session && buf && length && sli_cnt && sli, PJ_EINVAL);
 
     len = (3 + sli_cnt) * 4;
     if (len > *length)
 	return PJ_ETOOSMALL;
 
     /* Build RTCP-FB SLI header */
-    hdr = (pjmedia_rtcp_common*)buf;
-    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
-    hdr->pt = RTCP_PSFB;
-    hdr->count = 2; /* FMT = 2 */
-    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
+    hdr = (pjmedia_rtcp_fb_common*)buf;
+    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
+    hdr->rtcp_common.pt = RTCP_PSFB;
+    hdr->rtcp_common.count = 2; /* FMT = 2 */
+    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
 
     /* Build RTCP-FB SLI FCI */
     p = (pj_uint8_t*)hdr + sizeof(*hdr);
     for (i = 0; i < sli_cnt; ++i) {
 	/* 'first' takes 13 bit */
@@ -164,11 +164,11 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_build_rpsi(
 					    pjmedia_rtcp_session *session, 
 					    void *buf,
 					    pj_size_t *length,
 					    const pjmedia_rtcp_fb_rpsi *rpsi)
 {
-    pjmedia_rtcp_common *hdr;
+    pjmedia_rtcp_fb_common *hdr;
     pj_uint8_t *p;
     unsigned bitlen, padlen, len;
 
     PJ_ASSERT_RETURN(session && buf && length && rpsi, PJ_EINVAL);
 
@@ -177,15 +177,15 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_build_rpsi(
     len = (3 + (bitlen+padlen)/32) * 4;
     if (len > *length)
 	return PJ_ETOOSMALL;
 
     /* Build RTCP-FB RPSI header */
-    hdr = (pjmedia_rtcp_common*)buf;
-    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
-    hdr->pt = RTCP_PSFB;
-    hdr->count = 3; /* FMT = 3 */
-    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
+    hdr = (pjmedia_rtcp_fb_common*)buf;
+    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
+    hdr->rtcp_common.pt = RTCP_PSFB;
+    hdr->rtcp_common.count = 3; /* FMT = 3 */
+    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
 
     /* Build RTCP-FB RPSI FCI */
     p = (pj_uint8_t*)hdr + sizeof(*hdr);
     /* PB (number of padding bits) */
     *p++ = (pj_uint8_t)padlen;
@@ -618,22 +618,22 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_nack(
 					const void *buf,
 					pj_size_t length,
 					unsigned *nack_cnt,
 					pjmedia_rtcp_fb_nack nack[])
 {
-    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
+    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
     pj_uint8_t *p;
     unsigned cnt, i;
 
     PJ_ASSERT_RETURN(buf && nack_cnt && nack, PJ_EINVAL);
-    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL);
+    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_fb_common), PJ_ETOOSMALL);
 
     /* Generic NACK uses pt==RTCP_RTPFB and FMT==1 */
-    if (hdr->pt != RTCP_RTPFB || hdr->count != 1)
+    if (hdr->rtcp_common.pt != RTCP_RTPFB || hdr->rtcp_common.count != 1)
 	return PJ_ENOTFOUND;
 
-    cnt = pj_ntohs((pj_uint16_t)hdr->length);
+    cnt = pj_ntohs((pj_uint16_t)hdr->rtcp_common.length);
     if (cnt > 2) cnt -= 2; else cnt = 0;
     if (length < (cnt+3)*4)
 	return PJ_ETOOSMALL;
 
     *nack_cnt = PJ_MIN(*nack_cnt, cnt);
@@ -659,19 +659,19 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_nack(
  */
 PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_pli(
 					const void *buf,
 					pj_size_t length)
 {
-    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
+    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
 
     PJ_ASSERT_RETURN(buf, PJ_EINVAL);
 
     if (length < 12)
     	return PJ_ETOOSMALL;
 
     /* PLI uses pt==RTCP_PSFB and FMT==1 */
-    if (hdr->pt != RTCP_PSFB || hdr->count != 1)
+    if (hdr->rtcp_common.pt != RTCP_PSFB || hdr->rtcp_common.count != 1)
 	return PJ_ENOTFOUND;
 
     return PJ_SUCCESS;
 }
 
@@ -684,22 +684,22 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_sli(
 					const void *buf,
 					pj_size_t length,
 					unsigned *sli_cnt,
 					pjmedia_rtcp_fb_sli sli[])
 {
-    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
+    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
     pj_uint8_t *p;
     unsigned cnt, i;
 
     PJ_ASSERT_RETURN(buf && sli_cnt && sli, PJ_EINVAL);
-    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL);
+    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_fb_common), PJ_ETOOSMALL);
 
     /* PLI uses pt==RTCP_PSFB and FMT==2 */
-    if (hdr->pt != RTCP_PSFB || hdr->count != 2)
+    if (hdr->rtcp_common.pt != RTCP_PSFB || hdr->rtcp_common.count != 2)
 	return PJ_ENOTFOUND;
 
-    cnt = pj_ntohs((pj_uint16_t)hdr->length) - 2;
+    cnt = pj_ntohs((pj_uint16_t)hdr->rtcp_common.length) - 2;
     if (length < (cnt+3)*4)
 	return PJ_ETOOSMALL;
 
     *sli_cnt = PJ_MIN(*sli_cnt, cnt);
 
@@ -728,28 +728,47 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_sli(
 PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_rpsi(
 					const void *buf,
 					pj_size_t length,
 					pjmedia_rtcp_fb_rpsi *rpsi)
 {
-    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
+    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
     pj_uint8_t *p;
     pj_uint8_t padlen;
     pj_size_t rpsi_len;
 
     PJ_ASSERT_RETURN(buf && rpsi, PJ_EINVAL);
-    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL);
+    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_fb_common), PJ_ETOOSMALL);
 
     /* RPSI uses pt==RTCP_PSFB and FMT==3 */
-    if (hdr->pt != RTCP_PSFB || hdr->count != 3)
+    if (hdr->rtcp_common.pt != RTCP_PSFB || hdr->rtcp_common.count != 3)
 	return PJ_ENOTFOUND;
 
-    rpsi_len = (pj_ntohs((pj_uint16_t)hdr->length)-2) * 4;
+    if (hdr->rtcp_common.length < 3) {    
+        PJ_PERROR(3, (THIS_FILE, PJ_ETOOSMALL,
+                      "Failed parsing FB RPSI, invalid header length"));
+	return PJ_ETOOSMALL;
+    }
+
+    rpsi_len = (pj_ntohs((pj_uint16_t)hdr->rtcp_common.length)-2) * 4;
     if (length < rpsi_len + 12)
 	return PJ_ETOOSMALL;
 
     p = (pj_uint8_t*)hdr + sizeof(*hdr);
     padlen = *p++;
+
+    if (padlen >= 32) {
+        PJ_PERROR(3, (THIS_FILE, PJ_ETOOBIG,
+                      "Failed parsing FB RPSI, invalid RPSI padding len"));
+	return PJ_ETOOBIG;
+    }
+
+    if ((rpsi_len * 8) < (unsigned)(16 + padlen)) {
+        PJ_PERROR(3, (THIS_FILE, PJ_ETOOSMALL,
+                      "Failed parsing FB RPSI, invalid RPSI bit len"));
+	return PJ_ETOOSMALL;
+    }
+
     rpsi->pt = (*p++ & 0x7F);
     rpsi->rpsi_bit_len = rpsi_len*8 - 16 - padlen;
     pj_strset(&rpsi->rpsi, (char*)p, (rpsi->rpsi_bit_len + 7)/8);
 
     return PJ_SUCCESS;

Vulnerable code:     pjmedia_rtcp_common *hdr;
    hdr = (pjmedia_rtcp_common*)buf;
    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
    hdr->pt = RTCP_RTPFB;
    hdr->count = 1; /* FMT = 1 */
    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_common *hdr;
    hdr = (pjmedia_rtcp_common*)buf;
    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
    hdr->pt = RTCP_PSFB;
    hdr->count = 1; /* FMT = 1 */
    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_common *hdr;
    hdr = (pjmedia_rtcp_common*)buf;
    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
    hdr->pt = RTCP_PSFB;
    hdr->count = 2; /* FMT = 2 */
    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_common *hdr;
    hdr = (pjmedia_rtcp_common*)buf;
    pj_memcpy(hdr, &session->rtcp_rr_pkt.common,  sizeof(*hdr));
    hdr->pt = RTCP_PSFB;
    hdr->count = 3; /* FMT = 3 */
    hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL);
    if (hdr->pt != RTCP_RTPFB || hdr->count != 1)
    cnt = pj_ntohs((pj_uint16_t)hdr->length);
    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
    if (hdr->pt != RTCP_PSFB || hdr->count != 1)
    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL);
    if (hdr->pt != RTCP_PSFB || hdr->count != 2)
    cnt = pj_ntohs((pj_uint16_t)hdr->length) - 2;
    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf;
    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL);
    if (hdr->pt != RTCP_PSFB || hdr->count != 3)
    rpsi_len = (pj_ntohs((pj_uint16_t)hdr->length)-2) * 4;
Fixed code: /**
 * RTCP feedback common header.
 */
typedef struct pjmedia_rtcp_fb_common
{
    pjmedia_rtcp_common rtcp_common;
    pj_uint32_t	    ssrc_src;	/**< SSRC media source	    */
} pjmedia_rtcp_fb_common;

    pjmedia_rtcp_fb_common  rtcp_fb_com;/**< Cached RTCP feedback common 
					     header packet.		    */
    /* Copy to RTCP FB common header */
    pj_memcpy(&sess->rtcp_fb_com, &sr_pkt->common, 
	      sizeof(pjmedia_rtcp_common));
    sess->rtcp_fb_com.ssrc_src = 0;

    pjmedia_rtcp_fb_common *hdr;
    hdr = (pjmedia_rtcp_fb_common*)buf;
    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
    hdr->rtcp_common.pt = RTCP_RTPFB;
    hdr->rtcp_common.count = 1; /* FMT = 1 */
    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_fb_common *hdr;
    hdr = (pjmedia_rtcp_fb_common*)buf;
    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
    hdr->rtcp_common.pt = RTCP_PSFB;
    hdr->rtcp_common.count = 1; /* FMT = 1 */
    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_fb_common *hdr;
    hdr = (pjmedia_rtcp_fb_common*)buf;
    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
    hdr->rtcp_common.pt = RTCP_PSFB;
    hdr->rtcp_common.count = 2; /* FMT = 2 */
    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_fb_common *hdr;
    hdr = (pjmedia_rtcp_fb_common*)buf;
    pj_memcpy(hdr, &session->rtcp_fb_com, sizeof(*hdr));
    hdr->rtcp_common.pt = RTCP_PSFB;
    hdr->rtcp_common.count = 3; /* FMT = 3 */
    hdr->rtcp_common.length = pj_htons((pj_uint16_t)(len/4 - 1));
    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_fb_common), PJ_ETOOSMALL);
    if (hdr->rtcp_common.pt != RTCP_RTPFB || hdr->rtcp_common.count != 1)
    cnt = pj_ntohs((pj_uint16_t)hdr->rtcp_common.length);
    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
    if (hdr->rtcp_common.pt != RTCP_PSFB || hdr->rtcp_common.count != 1)
    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_fb_common), PJ_ETOOSMALL);
    if (hdr->rtcp_common.pt != RTCP_PSFB || hdr->rtcp_common.count != 2)
    cnt = pj_ntohs((pj_uint16_t)hdr->rtcp_common.length) - 2;
    pjmedia_rtcp_fb_common *hdr = (pjmedia_rtcp_fb_common*) buf;
    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_fb_common), PJ_ETOOSMALL);
    if (hdr->rtcp_common.pt != RTCP_PSFB || hdr->rtcp_common.count != 3)
    if (hdr->rtcp_common.length < 3) {    
        PJ_PERROR(3, (THIS_FILE, PJ_ETOOSMALL,
                      "Failed parsing FB RPSI, invalid header length"));
	return PJ_ETOOSMALL;
    }

    rpsi_len = (pj_ntohs((pj_uint16_t)hdr->rtcp_common.length)-2) * 4;

    if (padlen >= 32) {
        PJ_PERROR(3, (THIS_FILE, PJ_ETOOBIG,
                      "Failed parsing FB RPSI, invalid RPSI padding len"));
	return PJ_ETOOBIG;
    }

    if ((rpsi_len * 8) < (unsigned)(16 + padlen)) {
        PJ_PERROR(3, (THIS_FILE, PJ_ETOOSMALL,
                      "Failed parsing FB RPSI, invalid RPSI bit len"));
	return PJ_ETOOSMALL;
    }