CVE-2022-31620 (C++, published 2022-05-25T21:15Z)
Description: value: In libjpeg before 1.64, BitStream<false>::Get in bitstream.hpp has an assertion failure that may cause denial of service. This is related to out-of-bounds array access during arithmetically coded lossless scan or arithmetically coded sequential scan.
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-617 \u2014 Reachable Assertion
The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
Repository: https://github.com/thorfdbg/libjpeg
Files changed:
README
README.history
codestream/aclosslessscan.cpp
codestream/aclosslessscan.hpp
codestream/acsequentialscan.cpp
codestream/acsequentialscan.hpp
codestream/losslessscan.cpp
codestream/rectanglerequest.hpp
Commit message: Added out-of-bounds checks for lossless symbol decoding and AC context
indices. Worked around some gcc warnings. Bumped to 1.64.


Vulnerable code:
** $Id: aclosslessscan.cpp,v 1.42 2020/08/31 07:50:43 thor Exp $
              i++;
** $Id: aclosslessscan.hpp,v 1.28 2014/11/16 15:49:58 thor Exp $
      QMContext X[15];
      QMContext M[15];
        for(int i = 0;i < 15;i++) {
** $Id: acsequentialscan.cpp,v 1.51 2016/10/28 13:58:53 thor Exp $
          i++;
          if (m == 0) 
            i++;
            if (m == 0)
** $Id: acsequentialscan.hpp,v 1.38 2016/10/28 13:58:53 thor Exp $
      QMContext X[19];
      QMContext M[19];
        for(int i = 0;i < 19;i++) {
      QMContext X[18];
      QMContext M[18];

        for(int i = 0;i < 18;i++) {
        for(int i = 0;i < 18;i++) {
** $Id: losslessscan.cpp,v 1.50 2015/03/25 08:45:43 thor Exp $
 * $Id: rectanglerequest.hpp,v 1.12 2017/11/28 13:08:07 thor Exp $
    // Not nice, but this is really faster and simpler
    memcpy(this,&req,sizeof(struct RectangleRequest));
    rr_pNext = NULL;
    // Not nice, but this is really faster and simpler
    memcpy(this,&req,sizeof(struct RectangleRequest));
    // Not linked in any way if this is new.
    rr_pNext = NULL;

Fixed code:
Release 1.64:

The lossless scan, the arithmetically coded lossless scan and the
arithmetically coded sequential scan could run into cases where an
out-of-bounds symbol triggered and out-of-bounds array access and could
have crashed the decoder. The code is now more carefully changing the
validity of the symbols and aborts with an error if it finds illegal
codes.

--------------------------------------------------------------------------


Release 1.64:

The lossless scan, the arithmetically coded lossless scan and the
arithmetically coded sequential scan could run into cases where an
out-of-bounds symbol triggered and out-of-bounds array access and could
have crashed the decoder. The code is now more carefully changing the
validity of the symbols and aborts with an error if it finds illegal
codes.

--------------------------------------------------------------------------
** $Id: aclosslessscan.cpp,v 1.43 2022/05/23 05:56:51 thor Exp $
              if (++i >= QMContextSet::MagnitudeSet::MagnitudeContexts)
                JPG_THROW(MALFORMED_STREAM,"ACLosslessScan::ParseMCU",
                          "received an out-of-bounds signal while parsing an AC-coded lossless symbol");
** $Id: aclosslessscan.hpp,v 1.29 2022/05/23 05:56:51 thor Exp $
      enum {
        MagnitudeContexts = 15
      };
      //
      QMContext X[MagnitudeContexts];
      QMContext M[MagnitudeContexts];
        for(int i = 0;i < MagnitudeContexts;i++) {
** $Id: acsequentialscan.cpp,v 1.52 2022/05/23 05:56:51 thor Exp $
          if(++i >= QMContextSet::DCContextMagnitudeSet::MagnitudeContexts)
            if(++i >= QMContextSet::ACContextMagnitudeSet::MagnitudeContexts)
** $Id: acsequentialscan.hpp,v 1.39 2022/05/23 05:56:51 thor Exp $
      enum {
        MagnitudeContexts = 19
      };
      //
      QMContext X[MagnitudeContexts];
      QMContext M[MagnitudeContexts];
        for(int i = 0;i < MagnitudeContexts;i++) {
      enum {
        MagnitudeContexts = 18
      };
      //
      QMContext X[MagnitudeContexts];
      QMContext M[MagnitudeContexts];
        for(int i = 0;i < MagnitudeContexts;i++) {
        for(int i = 0;i < MagnitudeContexts;i++) {
** $Id: losslessscan.cpp,v 1.51 2022/05/23 05:56:51 thor Exp $
        } else if (symbol > 16) {
          JPG_THROW(MALFORMED_STREAM,"LosslessScan::ParseMCU",
                    "received an out-of-bounds symbol in a lossless JPEG scan");
 * $Id: rectanglerequest.hpp,v 1.13 2022/05/23 05:56:51 thor Exp $
    rr_pNext            = NULL;
    rr_Request          = req.rr_Request;
    rr_usFirstComponent = req.rr_usFirstComponent;
    rr_usLastComponent  = req.rr_usLastComponent;
    rr_cPriority        = req.rr_cPriority;
    rr_bIncludeAlpha    = req.rr_bIncludeAlpha;
    rr_bUpsampling      = req.rr_bUpsampling;
    rr_bColorTrafo      = req.rr_bColorTrafo;
   // Not linked in any way if this is new.
    rr_pNext            = NULL;
    rr_Request          = req.rr_Request;
    rr_usFirstComponent = req.rr_usFirstComponent;
    rr_usLastComponent  = req.rr_usLastComponent;
    rr_cPriority        = req.rr_cPriority;
    rr_bIncludeAlpha    = req.rr_bIncludeAlpha;
    rr_bUpsampling      = req.rr_bUpsampling;
    rr_bColorTrafo      = req.rr_bColorTrafo;