bunzip2: reject blocks whose run-length count overflows
No binary (build failed)
—
(log yok)
| @@ -463,13 +463,12 @@ static int get_next_block(bunzip_data *bd) | |
| symbols, but a run of length 0 doesn't mean anything in this | |
| context). Thus space is saved. */ | |
| runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ | |
| - | //The 32-bit overflow of runCnt wasn't yet seen, but probably can happen. |
| - | //This would be the fix (catches too large count way before it can overflow): |
| - | // if (runCnt > bd->dbufSize) { |
| - | // dbg("runCnt:%u > dbufSize:%u RETVAL_DATA_ERROR", |
| - | // runCnt, bd->dbufSize); |
| - | // return RETVAL_DATA_ERROR; |
| - | // } |
| + | /* Catch 32-bit overflow (we have an example .bz2 file) */ |
| + | if ((int)runCnt < 0) { |
| + | dbg("runCnt:%u > dbufSize:%u RETVAL_DATA_ERROR", |
| + | runCnt, bd->dbufSize); |
| + | return RETVAL_DATA_ERROR; |
| + | } |
| if (runPos < bd->dbufSize) runPos <<= 1; | |
| goto end_of_huffman_loop; | |
| } | |
| @@ -568,6 +568,18 @@ if test "${0##*/}" = "bunzip2.tests"; then | |
| echo "FAIL: $unpack: bz2_issue_12.bz2 corrupted example" | |
| FAILCOUNT=$((FAILCOUNT + 1)) | |
| fi | |
| + | |
| + | # specially crafted file to attack the |
| + | # runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */ |
| + | # code, making (dbufCount + runCnt) overflow 32 bits and become small. |
| + | # (there is a fix now which catches when runCnt reaches 0x80000000) |
| + | errout="`${bb}bunzip2 <bz2_runcnt_overflow.bz2 2>&1 >/dev/null`" |
| + | if test x"$errout:$?" = x"bunzip2: bunzip error -5:1"; then |
| + | echo "PASS: $unpack: bz2_runcnt_overflow.bz2 corrupted example" |
| + | else |
| + | echo "FAIL: $unpack: bz2_runcnt_overflow.bz2 corrupted example" |
| + | FAILCOUNT=$((FAILCOUNT + 1)) |
| + | fi |
| fi | |
| exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255)) | |