Coverage Report

Created: 2026-11-12 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk-fuzzers/dcmtk_dicom_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
#include <string>
21
22
#include "dcmtk/dcmdata/dctk.h"
23
#include "dcmtk/dcmdata/dcistrmb.h"
24
#include "dcmtk/dcmdata/dcdeftag.h"
25
#include "dcmtk/dcmdata/dcxfer.h"
26
27
static constexpr std::size_t kNewNothrowCap = 8 * 1024 * 1024;
28
29
1.11k
void* operator new(std::size_t n, const std::nothrow_t&) noexcept {
30
1.11k
  if (n > kNewNothrowCap) return nullptr;
31
1.11k
  try { return ::operator new(n); } catch (...) { return nullptr; }
32
1.11k
}
33
108k
void* operator new[](std::size_t n, const std::nothrow_t&) noexcept {
34
108k
  if (n > kNewNothrowCap) return nullptr;
35
108k
  try { return ::operator new[](n); } catch (...) { return nullptr; }
36
108k
}
37
38
2.02k
static void walkDataset(DcmItem* item) {
39
2.02k
  if (!item) return;
40
2.02k
  DcmStack stack;
41
2.02k
  if (item->nextObject(stack, OFTrue).good()) {
42
6.84k
    do {
43
6.84k
      DcmObject* obj = stack.top();
44
6.84k
      if (!obj) break;
45
6.84k
      (void)obj->ident();
46
6.84k
      (void)obj->getTag();
47
6.84k
    } while (item->nextObject(stack, OFFalse).good());
48
1.54k
  }
49
2.02k
}
50
51
5.86k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
52
5.86k
  static bool dict_set = (setenv("DCMDICTPATH", "/out/dicom.dic", 0), true);
53
5.86k
  (void)dict_set;
54
55
5.86k
  DcmInputBufferStream in;
56
5.86k
  in.setBuffer((void*)data, size);
57
5.86k
  in.setEos();
58
59
5.86k
  DcmFileFormat file;
60
5.86k
  const Uint32 kMaxReadLen = 256 * 1024;
61
62
5.86k
  if (file.read(in, EXS_Unknown, EGL_noChange, kMaxReadLen).good()) {
63
2.02k
    if (auto* ds = file.getDataset()) {
64
2.02k
      (void)ds->chooseRepresentation(EXS_LittleEndianExplicit, nullptr);
65
2.02k
      (void)ds->calcElementLength(EXS_LittleEndianExplicit, EET_ExplicitLength);
66
67
2.02k
      OFString s;
68
2.02k
      (void)ds->findAndGetOFString(DCM_PatientName, s);
69
2.02k
      (void)ds->findAndGetOFString(DCM_StudyInstanceUID, s);
70
2.02k
      (void)ds->findAndGetOFString(DCM_SOPClassUID, s);
71
72
2.02k
      walkDataset(ds);
73
2.02k
    }
74
2.02k
  }
75
5.86k
  return 0;
76
5.86k
}