From 377085a7fd41e01c0c1ad5d1c1f90b59e8257593 From: Markus Kuhn Subject: [PATCH] Fix two DPPRIV buffer overflows and a bug * jbig.c:jbg_dec_in(): when a BIE with option DPPRIV=1 was received, the included private DP table (1728 bytes) was loaded into 20-byte array s->buffer, creating a buffer overflow vulnerability. It is now loaded instead into a malloc'ed temporary buffer. * jbig.c:jbg_dec_in(): buffer allocated for internal representation of private DP table was 1728 bytes long, but must be 6912 bytes long, creating another buffer overflow vulnerability. * jbig.c: a loop in the routines for converting between the internal and external representations of a DP table terminated earlier than intended. As a result, a private DP table provided to the decoder was not interpreted correctly. Likewise, if a user asked the encoder to output its standard DP table (which is only useful for testing), the result would have been incorrect. * tstcodec.c: test case for DPPRIV=1 added. The buffer overflow vulnerability was reported by Florian Weimer (Red Hat) and has been assigned CVE-2013-6369. None of these fixes should affect ABI compatibility; jbig.h remains unchanged. All past releases of jbig.c are believed to be affected. The jbig85.c lightwight implementation was not affected. --- libjbig/jbig.c | 16 ++++++++++------ libjbig/tstcodec.c | 11 ++++++++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libjbig/jbig.c b/libjbig/jbig.c index f3c35cc..48fc128 100644 --- a/libjbig/jbig.c +++ b/libjbig/jbig.c @@ -1738,7 +1738,7 @@ void jbg_int2dppriv(unsigned char *dptable, const char *internal) #define FILL_TABLE1(offset, len, trans) \ for (i = 0; i < len; i++) { \ k = 0; \ - for (j = 0; j < 8; j++) \ + for (j = 0; i >> j; j++) \ k |= ((i >> j) & 1) << trans[j]; \ dptable[(i + offset) >> 2] |= \ (internal[k + offset] & 3) << ((3 - (i&3)) << 1); \ @@ -1769,7 +1769,7 @@ void jbg_dppriv2int(char *internal, const unsigned char *dptable) #define FILL_TABLE2(offset, len, trans) \ for (i = 0; i < len; i++) { \ k = 0; \ - for (j = 0; j < 8; j++) \ + for (j = 0; i >> j; j++) \ k |= ((i >> j) & 1) << trans[j]; \ internal[k + offset] = \ (dptable[(i + offset) >> 2] >> ((3 - (i & 3)) << 1)) & 3; \ @@ -2574,6 +2574,7 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, unsigned long x, y; unsigned long is[3], ie[3]; size_t dummy_cnt; + unsigned char *dppriv; if (!cnt) cnt = &dummy_cnt; *cnt = 0; @@ -2711,13 +2712,16 @@ int jbg_dec_in(struct jbg_dec_state *s, unsigned char *data, size_t len, (s->options & (JBG_DPON | JBG_DPPRIV | JBG_DPLAST)) == (JBG_DPON | JBG_DPPRIV)) { assert(s->bie_len >= 20); + if (!s->dppriv || s->dppriv == jbg_dptable) + s->dppriv = (char *) checked_malloc(1728, sizeof(char)); while (s->bie_len < 20 + 1728 && *cnt < len) - s->buffer[s->bie_len++ - 20] = data[(*cnt)++]; + s->dppriv[s->bie_len++ - 20] = data[(*cnt)++]; if (s->bie_len < 20 + 1728) return JBG_EAGAIN; - if (!s->dppriv || s->dppriv == jbg_dptable) - s->dppriv = (char *) checked_malloc(1728, sizeof(char)); - jbg_dppriv2int(s->dppriv, s->buffer); + dppriv = s->dppriv; + s->dppriv = (char *) checked_malloc(6912, sizeof(char)); + jbg_dppriv2int(s->dppriv, dppriv); + checked_free(dppriv); } /* diff --git a/libjbig/tstcodec.c b/libjbig/tstcodec.c index 44bae57..6289748 100644 --- a/libjbig/tstcodec.c +++ b/libjbig/tstcodec.c @@ -483,11 +483,16 @@ int main(int argc, char **argv) problems += test_cycle(&pp, 1960, 1951, JBG_DELAY_AT | JBG_TPBON | JBG_TPDON | JBG_DPON, 0, 6, 1, 2, 8, 279314L, "3.4"); -#if 0 - puts("Test 3.5: as Test 3.4 but with order bit SEQ set"); + puts("Test 3.5: as Test 3.4 but with DPPRIV=1"); + problems += test_cycle(&pp, 1960, 1951, + JBG_DELAY_AT | JBG_TPBON | JBG_TPDON | JBG_DPON | + JBG_DPPRIV, + 0, 6, 1, 2, 8, 279314L + 1728, "3.5"); +#if 0 /* Note: option SEQ is currently not supported by the decoder */ + puts("Test 3.6: as Test 3.4 but with order bit SEQ set"); problems += test_cycle(&pp, 1960, 1951, JBG_DELAY_AT | JBG_TPBON | JBG_TPDON | JBG_DPON, - JBG_SEQ, 6, 1, 2, 8, 279314L, "3.5"); + JBG_SEQ, 6, 1, 2, 8, 279314L, "3.6"); #endif #endif -- 1.7.9.5