Repository: libraw/libraw
Fuzzing engine: libfuzzer
Fuzz target: libraw_cr2_fuzzer
Sanitizer: undefined
Crash type: Index-out-of-bounds

Sanitizer report:
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2726989515
INFO: Loaded 1 modules   (66178 inline 8-bit counters): 66178 [0x5575e6b581b0, 0x5575e6b68432), 
INFO: Loaded 1 PC tables (66178 PCs): 66178 [0x5575e6b68438,0x5575e6c6ac58), 
/out/libraw_cr2_fuzzer: Running 1 inputs 1 time(s) each.
Running: /testcase/OSV-2020-1417.poc
src/demosaic/dht_demosaic.cpp:100:21: runtime error: index 3 out of bounds for type 'float[3]'
    #0 0x5575e6752488 in DHT::get_hv_rbg(int, int, int) /src/libraw/src/demosaic/dht_demosaic.cpp:100:21
    #1 0x5575e6750bea in DHT::make_hv_dline(int) /src/libraw/src/demosaic/dht_demosaic.cpp:569:11
    #2 0x5575e6750754 in DHT::make_hv_dirs() /src/libraw/src/demosaic/dht_demosaic.cpp:460:5
    #3 0x5575e6755d9d in LibRaw::dht_interpolate() /src/libraw/src/demosaic/dht_demosaic.cpp:1016:7
    #4 0x5575e658e815 in LibRaw::dcraw_process() /src/libraw/src/postprocessing/dcraw_process.cpp:171:9
    #5 0x5575e65835e9 in LLVMFuzzerTestOneInput /src/libraw_fuzzer.cc:57:22
    #6 0x5575e64e58f0 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #7 0x5575e64d0b65 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:327:6
    #8 0x5575e64d65ff in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:862:9
    #9 0x5575e65018a2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #10 0x7f2031f0f082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e)
    #11 0x5575e64c8d4d in _start (/out/libraw_cr2_fuzzer+0x372d4d)

DEDUP_TOKEN: DHT::get_hv_rbg(int, int, int)--DHT::make_hv_dline(int)--DHT::make_hv_dirs()
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior src/demosaic/dht_demosaic.cpp:100:21 


Fix patch:
diff --git a/src/metadata/identify.cpp b/src/metadata/identify.cpp
index c68e7f16..9443d8fa 100644
--- a/src/metadata/identify.cpp
+++ b/src/metadata/identify.cpp
@@ -958,15 +958,16 @@ void LibRaw::identify()
     {
     case 0: // Compression not set, assuming uncompressed
     case 1:
-      // Uncompressed float: decoder set in apply_tiff
-      if (load_raw != &LibRaw::uncompressed_fp_dng_load_raw)
+      // Uncompressed float: decoder set in apply_tiff for valid files; not set for non-valid with sampleformat==3
+      if ((load_raw != &LibRaw::uncompressed_fp_dng_load_raw)  && (tiff_sampleformat != 3))
         load_raw = &LibRaw::packed_dng_load_raw;
       break;
     case 7:
       load_raw = &LibRaw::lossless_dng_load_raw;
       break;
     case 8:
-      load_raw = &LibRaw::deflate_dng_load_raw;
+        if (tiff_sampleformat == 3 && tiff_bps > 8 && (tiff_bps % 8 == 0) && tiff_bps <= 32)
+            load_raw = &LibRaw::deflate_dng_load_raw;
       break;
 #ifdef USE_GPRSDK
     case 9:
@@ -1108,7 +1109,9 @@ dng_skip:
       (tiff_bps > 16 &&
        (load_raw != &LibRaw::deflate_dng_load_raw &&
         load_raw != &LibRaw::uncompressed_fp_dng_load_raw )) ||
-      tiff_samples > 4 || colors > 4 || colors < 1)
+      ((load_raw == &LibRaw::deflate_dng_load_raw || load_raw != &LibRaw::uncompressed_fp_dng_load_raw)
+        && (tiff_bps < 16 || tiff_bps > 32 || (tiff_bps % 8))   )
+      ||tiff_samples > 4 || colors > 4 || colors < 1)
   {
     is_raw = 0;
     RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2);
diff --git a/src/metadata/tiff.cpp b/src/metadata/tiff.cpp
index 2439e4f4..d55fdc94 100644
--- a/src/metadata/tiff.cpp
+++ b/src/metadata/tiff.cpp
@@ -1793,7 +1793,7 @@ void LibRaw::apply_tiff()
     case 0:
     case 1:
         if (dng_version && tiff_sampleformat == 3 &&
-            (tiff_bps > 8 && (tiff_bps % 8 == 0))) // 16,24,32,48...
+          (tiff_bps > 8 && (tiff_bps % 8 == 0) && (tiff_bps <= 32))) // only 16,24, and 32 are allowed
         {
             load_raw = &LibRaw::uncompressed_fp_dng_load_raw;
             break;