CVE-2022-39244 (C, published 2022-10-06T18:16Z)
Description: value: PJSIP is a free and open source multimedia communication library written in C. In versions of PJSIP prior to 2.13 the PJSIP parser, PJMEDIA RTP decoder, and PJMEDIA SDP parser are affeced by a buffer overflow vulnerability. Users connecting to untrusted clients are at risk. This issue has been patched and is available as commit c4d3498 in the master branch and will be included in releases 2.13 and later. Users are advised to upgrade. There are no known workarounds for this issue.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-120 \u2014 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
Repository: https://github.com/pjsip/pjproject
Files changed:
pjlib-util/src/pjlib-util/scanner.c
pjmedia/src/pjmedia/rtp.c
pjmedia/src/pjmedia/sdp.c
Commit message: 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>

Vulnerable code:
    char *s = pj_memchr(scanner->curptr, '\n', scanner->end - scanner->curptr);
    /* EOF is detected implicitly */
    if (!pj_cis_match(spec, *s)) {
    /* EOF is detected implicitly */
    if (!pj_cis_match(spec, *s) && *s != '%') {
    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
    if (!PJ_SCAN_IS_NEWLINE(*scanner->curptr)) {
    if (*scanner->curptr == '\n') {
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws) {


    /* Check that offset is less than packet size */
    if (offset > pkt_len)


    if (*(scanner->curptr+1) != '=') {
    if (*(scanner->curptr+2) != '0') {
    if (*(scanner->curptr+1) != '=') {
    if (*(scanner->curptr+1) != '=') {
    if (*(scanner->curptr+1) != '=') {
    if (*(scanner->curptr+1) != '=') {
	PJ_THROW(SYNTAX_ERROR);
    while (*scanner->curptr == ' ') {
    if (*(scanner->curptr+1) != '=') {
	if (*scanner->curptr != '\r' && *scanner->curptr != '\n') {

Fixed code:
    char *s;

    if (pj_scan_is_eof(scanner)) {
        return;
    }

    s = pj_memchr(scanner->curptr, '\n', scanner->end - scanner->curptr);
    if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s)) {
    if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s) && *s != '%') {
    if (!pj_scan_is_eof(scanner) &&
	PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws)
    {
    if (pj_scan_is_eof(scanner) || !PJ_SCAN_IS_NEWLINE(*scanner->curptr)) {
    /* We have checked scanner->curptr validity above */
    if (!pj_scan_is_eof(scanner) && *scanner->curptr == '\n') {
    if (!pj_scan_is_eof(scanner) && PJ_SCAN_IS_PROBABLY_SPACE(*s) &&
	scanner->skip_ws)
    {
    if (!pj_scan_is_eof(scanner) && PJ_SCAN_IS_PROBABLY_SPACE(*s) &&
	scanner->skip_ws)
    {
    if (!pj_scan_is_eof(scanner) && PJ_SCAN_IS_PROBABLY_SPACE(*s) &&
	scanner->skip_ws)
    {
    if (!pj_scan_is_eof(scanner) && 
	PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws)
    {
    /* Check that offset is less than packet size */
    if (offset >= pkt_len) {
        return PJMEDIA_RTP_EINLEN;
    }

    /* Check again that offset is still less than packet size */
    if (offset >= pkt_len)
    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
    if (scanner->curptr+2 >= scanner->end || *(scanner->curptr+2) != '0') {
    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
    if ((scanner->curptr+1 >= scanner->end) || *(scanner->curptr+1) != '=') {
    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
    if (pj_scan_is_eof(scanner)) {
        on_scanner_error(scanner);
        return;
    }
	on_scanner_error(scanner);
    while (scanner->curptr < scanner->end && *scanner->curptr == ' ') {
    if (scanner->curptr+1 >= scanner->end || *(scanner->curptr+1) != '=') {
	if (!pj_scan_is_eof(scanner) && *scanner->curptr != '\r' && *scanner->curptr != '\n') {