Coverage Report

Created: 2026-09-28 07:04

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.09k
void* operator new(std::size_t n, const std::nothrow_t&) noexcept {
30
1.09k
  if (n > kNewNothrowCap) return nullptr;
31
1.09k
  try { return ::operator new(n); } catch (...) { return nullptr; }
32
1.09k
}
33
101k
void* operator new[](std::size_t n, const std::nothrow_t&) noexcept {
34
101k
  if (n > kNewNothrowCap) return nullptr;
35
100k
  try { return ::operator new[](n); } catch (...) { return nullptr; }
36
100k
}
37
38
2.17k
static void walkDataset(DcmItem* item) {
39
2.17k
  if (!item) return;
40
2.17k
  DcmStack stack;
41
2.17k
  if (item->nextObject(stack, OFTrue).good()) {
42
5.95k
    do {
43
5.95k
      DcmObject* obj = stack.top();
44
5.95k
      if (!obj) break;
45
5.95k
      (void)obj->ident();
46
5.95k
      (void)obj->getTag();
47
5.95k
    } while (item->nextObject(stack, OFFalse).good());
48
1.61k
  }
49
2.17k
}
50
51
6.09k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
52
6.09k
  static bool dict_set = (setenv("DCMDICTPATH", "/out/dicom.dic", 0), true);
53
6.09k
  (void)dict_set;
54
55
6.09k
  DcmInputBufferStream in;
56
6.09k
  in.setBuffer((void*)data, size);
57
6.09k
  in.setEos();
58
59
6.09k
  DcmFileFormat file;
60
6.09k
  const Uint32 kMaxReadLen = 256 * 1024;
61
62
6.09k
  if (file.read(in, EXS_Unknown, EGL_noChange, kMaxReadLen).good()) {
63
2.17k
    if (auto* ds = file.getDataset()) {
64
2.17k
      (void)ds->chooseRepresentation(EXS_LittleEndianExplicit, nullptr);
65
2.17k
      (void)ds->calcElementLength(EXS_LittleEndianExplicit, EET_ExplicitLength);
66
67
2.17k
      OFString s;
68
2.17k
      (void)ds->findAndGetOFString(DCM_PatientName, s);
69
2.17k
      (void)ds->findAndGetOFString(DCM_StudyInstanceUID, s);
70
2.17k
      (void)ds->findAndGetOFString(DCM_SOPClassUID, s);
71
72
2.17k
      walkDataset(ds);
73
2.17k
    }
74
2.17k
  }
75
6.09k
  return 0;
76
6.09k
}