Coverage Report

Created: 2026-06-30 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk-fuzzers/dcmtk_image_fuzzer.cc
Line
Count
Source
1
// Copyright 2026 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
///////////////////////////////////////////////////////////////////////////
16
#include <cstdint>
17
#include <cstddef>
18
#include <cstdlib>
19
#include <new>
20
21
#include "dcmtk/dcmdata/dctk.h"
22
#include "dcmtk/dcmdata/dcistrmb.h"
23
#include "dcmtk/dcmdata/dcxfer.h"
24
#include "dcmtk/dcmdata/dcrledrg.h"
25
#include "dcmtk/dcmimage/diregist.h"
26
#include "dcmtk/dcmimgle/dcmimage.h"
27
#include "dcmtk/dcmimgle/diutils.h"
28
#include "dcmtk/dcmjpeg/djdecode.h"
29
#include "dcmtk/dcmjpls/djdecode.h"
30
31
static constexpr std::size_t kNewNothrowCap = 8 * 1024 * 1024;
32
33
403
void* operator new(std::size_t n, const std::nothrow_t&) noexcept {
34
403
  if (n > kNewNothrowCap) return nullptr;
35
403
  try { return ::operator new(n); } catch (...) { return nullptr; }
36
403
}
37
16.0k
void* operator new[](std::size_t n, const std::nothrow_t&) noexcept {
38
16.0k
  if (n > kNewNothrowCap) return nullptr;
39
15.2k
  try { return ::operator new[](n); } catch (...) { return nullptr; }
40
15.2k
}
41
42
1
static void cleanupCodecs() {
43
1
  DJDecoderRegistration::cleanup();
44
1
  DJLSDecoderRegistration::cleanup();
45
1
  DcmRLEDecoderRegistration::cleanup();
46
1
}
47
48
1
static bool registerCodecs() {
49
1
  DJDecoderRegistration::registerCodecs();
50
1
  DJLSDecoderRegistration::registerCodecs();
51
1
  DcmRLEDecoderRegistration::registerCodecs();
52
1
  std::atexit(cleanupCodecs);
53
1
  return true;
54
1
}
55
56
3.34k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
57
3.34k
  static bool dict_set = (setenv("DCMDICTPATH", "/out/dicom.dic", 0), true);
58
3.34k
  static bool codecs_set = registerCodecs();
59
3.34k
  (void)dict_set;
60
3.34k
  (void)codecs_set;
61
62
3.34k
  DcmInputBufferStream in;
63
3.34k
  in.setBuffer((void*)data, size);
64
3.34k
  in.setEos();
65
66
3.34k
  DcmFileFormat file;
67
3.34k
  const Uint32 kMaxReadLen = 256 * 1024;
68
69
3.34k
  if (file.read(in, EXS_Unknown, EGL_noChange, kMaxReadLen).good()) {
70
403
    if (auto* ds = file.getDataset()) {
71
403
      DicomImage* image = new (std::nothrow) DicomImage(&file, ds->getOriginalXfer());
72
403
      if (image && image->getStatus() == EIS_Normal) {
73
0
        unsigned long frames = image->getFrameCount();
74
0
        if (frames > 16) frames = 16;
75
0
        for (unsigned long f = 0; f < frames; ++f)
76
0
          (void)image->getOutputData(8, f);
77
0
      }
78
403
      delete image;
79
403
    }
80
403
  }
81
3.34k
  return 0;
82
3.34k
}