Repository: libtiff/libtiff
Fuzzing engine: libfuzzer
Fuzz target: tiff_read_rgba_fuzzer
Sanitizer: memory
Crash type: Use-of-uninitialized-value

Sanitizer report:
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3693094467
INFO: Loaded 1 modules   (25721 inline 8-bit counters): 25721 [0x55a82cf467c0, 0x55a82cf4cc39), 
INFO: Loaded 1 PC tables (25721 PCs): 25721 [0x55a82cf4cc40,0x55a82cfb13d0), 
/out/tiff_read_rgba_fuzzer: Running 1 inputs 1 time(s) each.
Running: /testcase/OSV-2020-1232.poc
==7==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x55a82c9036ee in putcontig8bitYCbCr22tile /src/libtiff/libtiff/tif_getimage.c:2145:4
    #1 0x55a82c8ee489 in gtTileContig /src/libtiff/libtiff/tif_getimage.c:691:6
    #2 0x55a82c8ec4e4 in TIFFRGBAImageGet /src/libtiff/libtiff/tif_getimage.c:511:12
    #3 0x55a82c8ec4e4 in TIFFReadRGBAImageOriented /src/libtiff/libtiff/tif_getimage.c:530:8
    #4 0x55a82c88f488 in LLVMFuzzerTestOneInput /src/libtiff/contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc:94:7
    #5 0x55a82c784810 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #6 0x55a82c76fa85 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:327:6
    #7 0x55a82c77551f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:862:9
    #8 0x55a82c7a07c2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #9 0x7f953ad30082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e)
    #10 0x55a82c767c6d in _start (/out/tiff_read_rgba_fuzzer+0xf0c6d)

DEDUP_TOKEN: putcontig8bitYCbCr22tile--gtTileContig--TIFFRGBAImageGet
  Uninitialized value was stored to memory at
    #0 0x55a82c9a4e61 in OJPEGDecodeRaw /src/libtiff/libtiff/tif_ojpeg.c:886:10
    #1 0x55a82c9a4e61 in OJPEGDecode /src/libtiff/libtiff/tif_ojpeg.c:803:7
    #2 0x55a82c9153e9 in TIFFReadEncodedTile /src/libtiff/libtiff/tif_read.c:997:33
    #3 0x55a82c8ee18a in gtTileContig /src/libtiff/libtiff/tif_getimage.c:673:10
    #4 0x55a82c8ec4e4 in TIFFRGBAImageGet /src/libtiff/libtiff/tif_getimage.c:511:12
    #5 0x55a82c8ec4e4 in TIFFReadRGBAImageOriented /src/libtiff/libtiff/tif_getimage.c:530:8
    #6 0x55a82c88f488 in LLVMFuzzerTestOneInput /src/libtiff/contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc:94:7
    #7 0x55a82c784810 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #8 0x55a82c76fa85 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:327:6
    #9 0x55a82c77551f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:862:9
    #10 0x55a82c7a07c2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #11 0x7f953ad30082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e)

DEDUP_TOKEN: OJPEGDecodeRaw--OJPEGDecode--TIFFReadEncodedTile
  Uninitialized value was created by a heap allocation
    #0 0x55a82c831ca2 in malloc /src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:1021:3
    #1 0x55a82c9a2b53 in OJPEGWriteHeaderInfo /src/libtiff/libtiff/tif_ojpeg.c:1244:37
    #2 0x55a82c9a2b53 in OJPEGPreDecode /src/libtiff/libtiff/tif_ojpeg.c:708:7
    #3 0x55a82c917143 in _TIFFReadEncodedTileAndAllocBuffer /src/libtiff/libtiff/tif_read.c:1053:10
    #4 0x55a82c8ee18a in gtTileContig /src/libtiff/libtiff/tif_getimage.c:673:10
    #5 0x55a82c8ec4e4 in TIFFRGBAImageGet /src/libtiff/libtiff/tif_getimage.c:511:12
    #6 0x55a82c8ec4e4 in TIFFReadRGBAImageOriented /src/libtiff/libtiff/tif_getimage.c:530:8
    #7 0x55a82c88f488 in LLVMFuzzerTestOneInput /src/libtiff/contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc:94:7
    #8 0x55a82c784810 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #9 0x55a82c76fa85 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:327:6
    #10 0x55a82c77551f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:862:9
    #11 0x55a82c7a07c2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #12 0x7f953ad30082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e)

DEDUP_TOKEN: __interceptor_malloc--OJPEGWriteHeaderInfo--OJPEGPreDecode
SUMMARY: MemorySanitizer: use-of-uninitialized-value /src/libtiff/libtiff/tif_getimage.c:2145:4 in putcontig8bitYCbCr22tile
Unique heap origins: 193
Stack depot allocated bytes: 9764880
Unique origin histories: 16
History depot allocated bytes: 196608
Exiting


Fix patch:
diff --git a/libtiff/tif_ojpeg.c b/libtiff/tif_ojpeg.c
index 83d2f5c6..159e9250 100644
--- a/libtiff/tif_ojpeg.c
+++ b/libtiff/tif_ojpeg.c
@@ -1241,7 +1241,13 @@ OJPEGWriteHeaderInfo(TIFF* tif)
 			sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines;
 			sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines;
 			sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen;
-			sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen);
+                        /* The calloc is not normally necessary, except in some edge/broken cases */
+                        /* for example for a tiled image of height 1 with a tile height of 1 and subsampling_hor=subsampling_ver=2 */
+                        /* In that case, libjpeg will only fill the 8 first lines of the 16 lines */
+                        /* See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844 */
+                        /* Even if this case is allowed (?), its handling is broken because OJPEGPreDecode() should also likely */
+                        /* reset subsampling_convert_state to 0 when changing tile. */
+			sp->subsampling_convert_ycbcrbuf=_TIFFcalloc(1, sp->subsampling_convert_ycbcrbuflen);
 			if (sp->subsampling_convert_ycbcrbuf==0)
 			{
 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");