Skip to content
Permalink
Browse files Browse the repository at this point in the history
Added out-of-bounds checks for lossless symbol decoding and AC context
indices. Worked around some gcc warnings. Bumped to 1.64.
  • Loading branch information
Thomas Richter committed May 23, 2022
1 parent 4aebbf9 commit ef4a29a
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 29 deletions.
11 changes: 11 additions & 0 deletions README
Expand Up @@ -452,6 +452,17 @@ file for the alpha channel with the "-al" command line option.

--------------------------------------------------------------------------

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.

--------------------------------------------------------------------------

For license conditions, please check the file README.license in this
directory.

Expand Down
11 changes: 11 additions & 0 deletions README.history
Expand Up @@ -555,3 +555,14 @@ now in this case simply disregarded. Note that you can define the output
file for the alpha channel with the "-al" command line option.

--------------------------------------------------------------------------

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.

--------------------------------------------------------------------------
6 changes: 4 additions & 2 deletions codestream/aclosslessscan.cpp
Expand Up @@ -42,7 +42,7 @@
**
** Represents the scan including the scan header.
**
** $Id: aclosslessscan.cpp,v 1.42 2020/08/31 07:50:43 thor Exp $
** $Id: aclosslessscan.cpp,v 1.43 2022/05/23 05:56:51 thor Exp $
**
*/

Expand Down Expand Up @@ -359,7 +359,9 @@ void ACLosslessScan::ParseMCU(struct Line **prev,struct Line **top)
//
while(m_Coder.Get(mset.X[i])) {
m <<= 1;
i++;
if (++i >= QMContextSet::MagnitudeSet::MagnitudeContexts)
JPG_THROW(MALFORMED_STREAM,"ACLosslessScan::ParseMCU",
"received an out-of-bounds signal while parsing an AC-coded lossless symbol");
}
//
m >>= 1;
Expand Down
12 changes: 8 additions & 4 deletions codestream/aclosslessscan.hpp
Expand Up @@ -43,7 +43,7 @@
** Represents the lossless scan - lines are coded directly with predictive
** coding, though here residuals are encoded with the arithmetic encoder.
**
** $Id: aclosslessscan.hpp,v 1.28 2014/11/16 15:49:58 thor Exp $
** $Id: aclosslessscan.hpp,v 1.29 2022/05/23 05:56:51 thor Exp $
**
*/

Expand Down Expand Up @@ -111,12 +111,16 @@ class ACLosslessScan : public PredictiveScan {
//
// The Magnitude/refinement coding contexts.
struct MagnitudeSet {
QMContext X[15];
QMContext M[15];
enum {
MagnitudeContexts = 15
};
//
QMContext X[MagnitudeContexts];
QMContext M[MagnitudeContexts];
//
void Init(void)
{
for(int i = 0;i < 15;i++) {
for(int i = 0;i < MagnitudeContexts;i++) {
X[i].Init();
M[i].Init();
}
Expand Down
8 changes: 3 additions & 5 deletions codestream/acsequentialscan.cpp
Expand Up @@ -42,7 +42,7 @@
**
** Represents the scan including the scan header.
**
** $Id: acsequentialscan.cpp,v 1.51 2016/10/28 13:58:53 thor Exp $
** $Id: acsequentialscan.cpp,v 1.52 2022/05/23 05:56:51 thor Exp $
**
*/

Expand Down Expand Up @@ -582,8 +582,7 @@ void ACSequentialScan::DecodeBlock(LONG *block,

while(m_Coder.Get(m_Context[dc].DCMagnitude.X[i])) {
m <<= 1;
i++;
if (m == 0)
if(++i >= QMContextSet::DCContextMagnitudeSet::MagnitudeContexts)
JPG_THROW(MALFORMED_STREAM,"ACSequentialScan::DecodeBlock",
"QMDecoder is out of sync");
}
Expand Down Expand Up @@ -653,8 +652,7 @@ void ACSequentialScan::DecodeBlock(LONG *block,

while(m_Coder.Get(acm.X[i])) {
m <<= 1;
i++;
if (m == 0)
if(++i >= QMContextSet::ACContextMagnitudeSet::MagnitudeContexts)
JPG_THROW(MALFORMED_STREAM,"ACSequentialScan::DecodeBlock",
"QMDecoder is out of sync");
}
Expand Down
25 changes: 16 additions & 9 deletions codestream/acsequentialscan.hpp
Expand Up @@ -43,7 +43,7 @@
** Represents the scan including the scan header for the
** arithmetic coding procedure.
**
** $Id: acsequentialscan.hpp,v 1.38 2016/10/28 13:58:53 thor Exp $
** $Id: acsequentialscan.hpp,v 1.39 2022/05/23 05:56:51 thor Exp $
**
*/

Expand Down Expand Up @@ -120,13 +120,17 @@ class ACSequentialScan : public EntropyParser {
//
// The DC Magnitude coding contexts.
struct DCContextMagnitudeSet {
QMContext X[19];
QMContext M[19];
enum {
MagnitudeContexts = 19
};
//
QMContext X[MagnitudeContexts];
QMContext M[MagnitudeContexts];
//
// Initialize
void Init(void)
{
for(int i = 0;i < 19;i++) {
for(int i = 0;i < MagnitudeContexts;i++) {
#ifdef DEBUG_QMCODER
char string[5] = "X0 ";
string[1] = (i / 10) + '0';
Expand Down Expand Up @@ -171,14 +175,17 @@ class ACSequentialScan : public EntropyParser {
//
// The AC Magnitude coder.
struct ACContextMagnitudeSet {
QMContext X[18];
QMContext M[18];
enum {
MagnitudeContexts = 18
};
//
QMContext X[MagnitudeContexts];
QMContext M[MagnitudeContexts];
//

#ifdef DEBUG_QMCODER
void Init(bool hi)
{
for(int i = 0;i < 18;i++) {
for(int i = 0;i < MagnitudeContexts;i++) {
char string[5] = "xl00";
string[1] = (hi)?('h'):('l');
string[2] = (i / 10) + '0';
Expand All @@ -191,7 +198,7 @@ class ACSequentialScan : public EntropyParser {
#else
void Init(void)
{
for(int i = 0;i < 18;i++) {
for(int i = 0;i < MagnitudeContexts;i++) {
X[i].Init();
M[i].Init();
}
Expand Down
5 changes: 4 additions & 1 deletion codestream/losslessscan.cpp
Expand Up @@ -42,7 +42,7 @@
**
** Represents the scan including the scan header.
**
** $Id: losslessscan.cpp,v 1.50 2015/03/25 08:45:43 thor Exp $
** $Id: losslessscan.cpp,v 1.51 2022/05/23 05:56:51 thor Exp $
**
*/

Expand Down Expand Up @@ -377,6 +377,9 @@ void LosslessScan::ParseMCU(struct Line **prev,struct Line **top)
v = 0;
} else if (symbol == 16) {
v = -32768;
} else if (symbol > 16) {
JPG_THROW(MALFORMED_STREAM,"LosslessScan::ParseMCU",
"received an out-of-bounds symbol in a lossless JPEG scan");
} else {
LONG thre = 1L << (symbol - 1);
LONG diff = m_Stream.Get(symbol); // get the number of bits
Expand Down
26 changes: 18 additions & 8 deletions codestream/rectanglerequest.hpp
Expand Up @@ -42,7 +42,7 @@
* Definition of how to request a given rectangle for display,
* for load or for checking for a necessary update.
*
* $Id: rectanglerequest.hpp,v 1.12 2017/11/28 13:08:07 thor Exp $
* $Id: rectanglerequest.hpp,v 1.13 2022/05/23 05:56:51 thor Exp $
*
*/

Expand Down Expand Up @@ -105,19 +105,29 @@ struct RectangleRequest : public JObject, private Explicit {
RectangleRequest(const struct RectangleRequest &req)
: Explicit()
{
// 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;
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;
}
//
// Assignment operator.
RectangleRequest &operator=(const struct RectangleRequest &req)
{
// 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;
// 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;
//
return *this;
}
Expand Down

0 comments on commit ef4a29a

Please sign in to comment.