From 8420dbc003c144e55904eb564f4dd3cb4a655996 Mon Sep 17 00:00:00 2001 From: iliasabk Date: Wed, 16 Sep 2026 15:43:40 +0200 Subject: [PATCH] Fix numhprcs*numvprcs overflow defeating numprcs limit jpc_dec_tileinit() computes rlvl->numprcs = numhprcs * numvprcs in unsigned 32 bits and only then applies the 64*1024 sanity limit, so a crafted codestream whose true product exceeds 2^32 wraps to a small value, passes the check, and leaves band->prcs/prclyrnos severely under-allocated. Later packet iteration then reads and writes out of bounds (see issue #423 for an ASan report). Evaluate the product in uint_fast64_t and apply the limit to the true value before assigning numprcs. The wrapped-numprcs debug print and the now-redundant post-assignment check are folded into the new pre-assignment check. Part of jasper-software/jasper#423 (bug 1). --- src/libjasper/jpc/jpc_dec.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libjasper/jpc/jpc_dec.c b/src/libjasper/jpc/jpc_dec.c index 7e44f052..d0803c8e 100644 --- a/src/libjasper/jpc/jpc_dec.c +++ b/src/libjasper/jpc/jpc_dec.c @@ -797,6 +797,17 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) rlvl->prcwidthexpn; rlvl->numvprcs = (brprcyend - tlprcystart) >> rlvl->prcheightexpn; + /* The product numhprcs * numvprcs must be evaluated in + 64 bits so that a wrapped result cannot defeat the + limit check below. */ + if (JAS_CAST(uint_fast64_t, rlvl->numhprcs) * + rlvl->numvprcs >= 64 * 1024) { + /* avoid out-of-memory due to + malicious file; this limit is + rather arbitrary; "good" files I + have seen have values 1..12 */ + return -1; + } rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; if (jas_get_debug_level() >= 10) { @@ -809,14 +820,6 @@ static int jpc_dec_tileinit(jpc_dec_t *dec, jpc_dec_tile_t *tile) rlvl->numhprcs, rlvl->numvprcs, rlvl->numprcs); } - if (rlvl->numprcs >= 64 * 1024) { - /* avoid out-of-memory due to - malicious file; this limit is - rather arbitrary; "good" files I - have seen have values 1..12 */ - return -1; - } - if (rlvl->xstart >= rlvl->xend || rlvl->ystart >= rlvl->yend) { rlvl->bands = 0; rlvl->numprcs = 0;