Skip to content

UBSan: unbounded shift in mif_decode() from MIF component prec (mif_cod.c) #433

Description

@MMu-Aqua

Affected: JasPer 4.2.9 (5ce57f67e0011e0d2483992a5d77a092b1b64eb7)
Sanitizer: UndefinedBehaviorSanitizer (shift exponent 917737015 is too large for 32-bit type 'int'), not ASan
Entry point: imginfo -f poc.mif
Build note: MIF is off by default. This needs -DJAS_ENABLE_MIF_CODEC=ON.

Summary

mif_decode() parses prec= from the MIF text header into cmpt->prec with no upper bound. If sgnd is set it does:

bias = 1 << (cmpt->prec - 1);  /* mif_cod.c:239 */

The PoC uses prec=88888888888888888, which becomes a huge int; prec - 1 is then used as a shift count and UBSan reports a shift exponent of 917737015.

I did not find an existing GitHub issue for this site. This path is only compiled when the MIF codec is enabled.

Code

		if (cmpt->sgnd) {
			bias = 1 << (cmpt->prec - 1);
			for (y = 0; y < cmpt->height; ++y) {
				for (x = 0; x < cmpt->width; ++x) {
					*jas_seq2d_getref(data, x, y) -= bias;
				}
			}
		}

prec comes from the MIF component ... prec=N sgnd=1 line.

PoC

ubsan_mif_prec.zip

# poc_mif_prec.py
open("poc_mif_prec.mif", "wb").write(bytes.fromhex(
    "4d49460a636f6d706f6e656e7420746c783d3020746c793d302073616d707065"
    "72783d312073616d70706572793d312077696474683d38206865696768743d31"
    "20707265633d38383838383838383838383838383838382073676e643d310a65"
    "6e640a50320a3820310a3235350a0613202d3a4754616e7b"
))

The text form is:

MIF
component tlx=0 tly=0 sampperx=1 samppery=1 width=8 height=1 prec=88888888888888888 sgnd=1
end
P2
8 1
255

plus a few trailing sample bytes (included in the hex).

Reproduce

cmake -S . -B build \
  -DJAS_ENABLE_MIF_CODEC=ON \
  -DCMAKE_C_FLAGS="-fsanitize=undefined,address -fno-omit-frame-pointer" \
  -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=undefined,address"
cmake --build build -j
export UBSAN_OPTIONS='halt_on_error=1:abort_on_error=1:print_stacktrace=1'
./build/src/app/imginfo -f poc_mif_prec.mif

Stack

mif_cod.c:239:13: runtime error: shift exponent 917737015 is too large for 32-bit type 'int'
#0 mif_decode          mif_cod.c:239:13
#1 jas_image_decode    jas_image.c:477:16
#2 main                imginfo.c:334:16
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior .../mif_cod.c:239:13

Suggested fix

Reject prec outside a sane range (e.g. 1..32) when parsing the MIF component header, before the shift. Use an unsigned type for the shift if a large prec is ever intended.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions