Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed uninitialised memory access, mitigated BYPASS/RESTART issues #894

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions src/lib/openjp2/mqc.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,25 +297,159 @@ OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc) {
return (OPJ_UINT32)diff;
}

// pg. 477
// FIXME: bitwise AND of the upper part of the C was omitted, so far
#define BOOK_Ccarry(mqc) (OPJ_BYTE)( (mqc)->c >> 27 )
#define BOOK_Cmsbs(mqc) (OPJ_BYTE)( (mqc)->c >> 20 )
#define BOOK_Cpartial(mqc) (OPJ_BYTE)( (mqc)->c >> 19 )
#define BOOK_Ccarry_reset(mqc) (void)( (mqc)->c &= 0x7ffffff )
#define BOOK_Cmsbs_reset(mqc) (void)( (mqc)->c &= 0x00fffff )
#define BOOK_Cpartial_reset(mqc) (void)( (mqc)->c &= 0x007ffff )

#ifdef BOOK_ENABLE
static void BOOK_mq_encoder_initialization(opj_mqc_t *mqc, OPJ_BYTE *bpst)
{
mqc->a = 0x8000;
mqc->c = 0;
mqc->ct = 12;
mqc->b = 0;
mqc->bp = bpst - 1;
}
#endif

void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) {
/* TODO MSD: need to take a look to the v2 version */
opj_mqc_setcurctx(mqc, 0);
#ifdef BOOK_ENABLE
BOOK_mq_encoder_initialization(mqc, bp);
#else
mqc->a = 0x8000;
mqc->c = 0;
mqc->bp = bp - 1;
mqc->ct = 12;
#endif
mqc->start = bp;
}

#ifdef BOOK_ENABLE
// pg. 479
static void BOOK_put_byte(opj_mqc_t *mqc)
{
if( mqc->bp >= mqc->start ) // if L >= 0
{
*mqc->bp = mqc->b; // B_L <- T
}

mqc->bp++; // L = L + 1
}
#endif

#ifdef BOOK_ENABLE
// pg. 479
static void BOOK_transfer_byte(opj_mqc_t *mqc)
{
if( mqc->b == 0xff ) // if T = FF
{
BOOK_put_byte(mqc); // Put-Byte(T,L)
mqc->b = BOOK_Cmsbs(mqc); // T <- Cmsbs
BOOK_Cmsbs_reset(mqc); // Cmsbs <- 0
mqc->ct = 7; // t <- 7
}
else
{
mqc->b += BOOK_Ccarry(mqc); // T <- T + Ccarry
BOOK_Ccarry_reset(mqc); // Ccarry <- 0
BOOK_put_byte(mqc); // Put-Byte(T,L)
if( mqc->b == 0xff ) // if T = FF
{
mqc->b = BOOK_Cmsbs(mqc); // T <- Cmsbs
BOOK_Cmsbs_reset(mqc); // Cmsbs <- 0
mqc->ct = 7; // t <- 7
}
else
{
mqc->b = BOOK_Cpartial(mqc); // T <- Cpartial
BOOK_Cpartial_reset(mqc); // Cpartial <- 0
mqc->ct = 8; // t <- 8
}
}
}
#endif

#ifdef BOOK_ENABLE
static void BOOK_mq_encode(opj_mqc_t *mqc, OPJ_UINT32 x)
{
OPJ_UINT32 s = (*mqc->curctx)->mps; // s = MPS(CX)
OPJ_UINT32 p = (*mqc->curctx)->qeval; // p = Qe(I(CX))
mqc->a -= p; // A <- A - p
if( mqc->a < p ) // if A < p
{
s = 1 - s; // s <- 1 - s
}
if( x == s ) // if x = s
{
mqc->c += p; // C <- C + p
}
else
{
mqc->a = p; // A <- p
}
if( mqc->a < 0x8000 ) // if A < 2^15
{
if( x == (*mqc->curctx)->mps ) // if x = s_k
{
*mqc->curctx = (*mqc->curctx)->nmps; // ...
}
else
{
// (*mqc->curctx)->mps ^= 1; // NOTE: omitted in OpenJPEG
*mqc->curctx = (*mqc->curctx)->nlps; // ...
}
}
while( mqc->a < 0x8000 ) // while A < 2^15
{
mqc->a <<= 1; // A <- 2A
mqc->c <<= 1; // C <- 2C
mqc->ct--; // t <- t - 1
if( mqc->ct == 0 ) // if t = 0
{
BOOK_transfer_byte(mqc); // Transfer-Byte(T,C,L,t)
}
}
}
#endif

#ifdef BOOK_ENABLE
static void BOOK_easy_mq_codeword_termination(opj_mqc_t *mqc)
{
OPJ_INT32 nbits = 27 - 15 - mqc->ct; // nbits <- 27 - 15 - t
mqc->c <<= mqc->ct; // C <- 2^t * C
while( nbits > 0 )
{
BOOK_transfer_byte(mqc); // Transfer-Byte(T,C,L,t)
nbits -= mqc->ct; // nbits <- nbits - t
mqc->c <<= mqc->ct; // C <- 2^t * C
}
BOOK_transfer_byte(mqc); // Transfer-Byte(T,C,L,t)
}
#endif

void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) {
#ifdef BOOK_ENABLE
BOOK_mq_encode(mqc, d);
#else
if ((*mqc->curctx)->mps == d) {
opj_mqc_codemps(mqc);
} else {
opj_mqc_codelps(mqc);
}
#endif
}

void opj_mqc_flush(opj_mqc_t *mqc) {
#ifdef BOOK_ENABLE
BOOK_easy_mq_codeword_termination(mqc);
#else
opj_mqc_setbits(mqc);
mqc->c <<= mqc->ct;
opj_mqc_byteout(mqc);
Expand All @@ -324,10 +458,13 @@ void opj_mqc_flush(opj_mqc_t *mqc) {

if (*mqc->bp != 0xff) {
mqc->bp++;
*mqc->bp = 0;
}
#endif
}

void opj_mqc_bypass_init_enc(opj_mqc_t *mqc) {
opj_mqc_byteout(mqc);
mqc->c = 0;
mqc->ct = 8;
/*if (*mqc->bp == 0xff) {
Expand Down Expand Up @@ -362,6 +499,8 @@ OPJ_UINT32 opj_mqc_bypass_flush_enc(opj_mqc_t *mqc) {
}
mqc->bp++;
*mqc->bp = (OPJ_BYTE)mqc->c;
mqc->bp++;
*mqc->bp = 0;
mqc->ct = 8;
mqc->c = 0;
}
Expand Down Expand Up @@ -393,6 +532,10 @@ OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc) {
}

void opj_mqc_restart_init_enc(opj_mqc_t *mqc) {
#ifdef BOOK_ENABLE
// FIXME why is there the +1 term?
BOOK_mq_encoder_initialization(mqc, mqc->bp+1);
#else
/* <Re-init part> */
opj_mqc_setcurctx(mqc, 0);
mqc->a = 0x8000;
Expand All @@ -402,6 +545,7 @@ void opj_mqc_restart_init_enc(opj_mqc_t *mqc) {
if (*mqc->bp == 0xff) {
mqc->ct = 13;
}
#endif
}

void opj_mqc_erterm_enc(opj_mqc_t *mqc) {
Expand Down
6 changes: 6 additions & 0 deletions src/lib/openjp2/mqc.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,18 @@ typedef struct opj_mqc_state {

#define MQC_NUMCTXS 19

// enable impl. according to the book "JPEG2000: Image Compression Fundamentals, Standards and Practice"
// #define BOOK_ENABLE

/**
MQ coder
*/
typedef struct opj_mqc {
OPJ_UINT32 c;
OPJ_UINT32 a;
#ifdef BOOK_ENABLE
OPJ_BYTE b;
#endif
OPJ_UINT32 ct;
OPJ_BYTE *bp;
OPJ_BYTE *start;
Expand Down
9 changes: 6 additions & 3 deletions src/lib/openjp2/t1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2102,19 +2102,22 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
/* Code switch "RESTART" (i.e. TERMALL) */
if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) {
if (type == T1_TYPE_RAW) {
opj_mqc_flush(mqc);
opj_mqc_bypass_flush_enc(mqc);
correction = 1;
/* correction = mqc_bypass_flush_enc(); */
} else { /* correction = mqc_restart_enc(); */
opj_mqc_flush(mqc);
#ifdef BOOK_ENABLE
opj_mqc_flush(mqc);
#endif
correction = 1;
}
pass->term = 1;
} else {
if (((bpno < ((OPJ_INT32) (cblk->numbps) - 4) && (passtype > 0))
|| ((bpno == ((OPJ_INT32)cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) {
if (type == T1_TYPE_RAW) {
opj_mqc_flush(mqc);
opj_mqc_bypass_flush_enc(mqc);
correction = 1;
/* correction = mqc_bypass_flush_enc(); */
} else { /* correction = mqc_restart_enc(); */
Expand All @@ -2132,7 +2135,7 @@ static void opj_t1_encode_cblk(opj_t1_t *t1,
bpno--;
}

if (pass->term && bpno > 0) {
if (pass->term && (bpno > 0 || (bpno == 0 && passtype < 2))) {
type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
if (type == T1_TYPE_RAW)
opj_mqc_bypass_init_enc(mqc);
Expand Down