Coverage Report

Created: 2026-08-13 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/security_limits.h
Line
Count
Source
1
/*
2
 * HEIF codec.
3
 * Copyright (c) 2018 Dirk Farin <dirk.farin@gmail.com>
4
 *
5
 * This file is part of libheif.
6
 *
7
 * libheif is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libheif is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
#ifndef LIBHEIF_SECURITY_LIMITS_H
21
#define LIBHEIF_SECURITY_LIMITS_H
22
23
#include "libheif/heif.h"
24
#include <cinttypes>
25
#include <cstddef>
26
#include "error.h"
27
28
29
extern heif_security_limits global_security_limits;
30
extern heif_security_limits disabled_security_limits;
31
32
// Maximum nesting level of boxes in input files.
33
// We put a limit on this to avoid unlimited stack usage by malicious input files.
34
static const int MAX_BOX_NESTING_LEVEL = 20;
35
36
static const int MAX_BOX_SIZE = 0x7FFFFFFF; // 2 GB
37
static const int64_t MAX_LARGE_BOX_SIZE = 0x0FFFFFFFFFFFFFFF;
38
static const int64_t MAX_FILE_POS = 0x007FFFFFFFFFFFFFLL; // maximum file position
39
static const int MAX_FRACTION_VALUE = 0x10000;
40
41
42
Error check_for_valid_image_size(const heif_security_limits* limits, uint32_t width, uint32_t height);
43
44
// Maximum coding-unit size (in pixels) that the given codec may pad a coded
45
// frame up to. Used as the margin for tighten_image_size_limit_for_ispe.
46
// Returns 0 for codecs without coding-unit padding (e.g. uncompressed).
47
uint32_t max_coding_unit_size_for_codec(heif_compression_format format);
48
49
// Return a copy of `base` with max_image_size_pixels lowered to a value
50
// just above the declared image size. This is used to bound how much memory
51
// a codec plugin may allocate for an image whose internal (codec-declared)
52
// dimensions exceed the file-declared (ispe) dimensions — without us having
53
// to parse the codec bitstream ourselves.
54
//
55
// `coding_unit_size` is the maximum coding-unit size of the target codec
56
// (e.g. 128 for AV1/VVC, 64 for HEVC, 16 for AVC). The allowed coded
57
// dimensions are (ispe + coding_unit_size) in each axis, since a codec may
58
// pad the coded frame up to a coding-unit boundary.
59
heif_security_limits tighten_image_size_limit_for_ispe(const heif_security_limits* base,
60
                                                       uint32_t ispe_width,
61
                                                       uint32_t ispe_height,
62
                                                       uint32_t coding_unit_size);
63
64
65
class TotalMemoryTracker
66
{
67
public:
68
  explicit TotalMemoryTracker(const heif_security_limits* limits_context);
69
  ~TotalMemoryTracker();
70
71
  size_t get_max_total_memory_used() const;
72
73
  void operator=(const TotalMemoryTracker&) = delete;
74
  TotalMemoryTracker(const TotalMemoryTracker&) = delete;
75
76
private:
77
  const heif_security_limits* m_limits_context = nullptr;
78
};
79
80
81
class MemoryHandle
82
{
83
public:
84
102k
  MemoryHandle() = default;
85
165k
  ~MemoryHandle() { free(); }
86
87
  Error alloc(size_t memory_amount, const heif_security_limits* limits_context, const char* reason_description);
88
89
  // calloc-style overload: checks `count * element_size` for size_t overflow before allocating.
90
  // Use this when allocating an array whose total size is count*element_size, to avoid silent
91
  // truncation on 32-bit builds when count is near UINT32_MAX.
92
  Error alloc(size_t count, size_t element_size,
93
              const heif_security_limits* limits_context, const char* reason_description);
94
95
  void free();
96
97
  void free(size_t memory_amount);
98
99
12
  const heif_security_limits* get_security_limits() const { return m_limits_context; }
100
101
  MemoryHandle(const MemoryHandle&) = delete;
102
  MemoryHandle& operator=(const MemoryHandle&) = delete;
103
104
  MemoryHandle(MemoryHandle&& other) noexcept
105
62.3k
      : m_limits_context(other.m_limits_context), m_memory_amount(other.m_memory_amount)
106
62.3k
  {
107
62.3k
    other.m_limits_context = nullptr;
108
62.3k
    other.m_memory_amount = 0;
109
62.3k
  }
110
111
  MemoryHandle& operator=(MemoryHandle&& other) noexcept
112
62.3k
  {
113
62.3k
    if (this != &other) {
114
62.3k
      free();
115
62.3k
      m_limits_context = other.m_limits_context;
116
62.3k
      m_memory_amount = other.m_memory_amount;
117
62.3k
      other.m_limits_context = nullptr;
118
62.3k
      other.m_memory_amount = 0;
119
62.3k
    }
120
62.3k
    return *this;
121
62.3k
  }
122
123
private:
124
  const heif_security_limits* m_limits_context = nullptr;
125
  size_t m_memory_amount = 0;
126
};
127
128
129
#endif  // LIBHEIF_SECURITY_LIMITS_H