Coverage Report

Created: 2026-07-30 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/goo/GooCheckedOps.h
Line
Count
Source
1
//========================================================================
2
//
3
// GooCheckedOps.h
4
//
5
// This file is licensed under the GPLv2 or later
6
//
7
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
8
// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com>
9
// Copyright (C) 2019-2021, 2025 Albert Astals Cid <aacid@kde.org>
10
//
11
//========================================================================
12
13
#ifndef GOO_CHECKED_OPS_H
14
#define GOO_CHECKED_OPS_H
15
16
#include <limits>
17
#include <type_traits>
18
19
template<typename T>
20
inline bool checkedAssign(long long lz, T *z)
21
{
22
    static_assert((std::numeric_limits<long long>::max)() > (std::numeric_limits<T>::max)(), "The max of long long type must be larger to perform overflow checks.");
23
    static_assert((std::numeric_limits<long long>::min)() < (std::numeric_limits<T>::min)(), "The min of long long type must be smaller to perform overflow checks.");
24
25
    if (lz > (std::numeric_limits<T>::max)() || lz < (std::numeric_limits<T>::min)()) {
26
        return true;
27
    }
28
29
    *z = static_cast<T>(lz);
30
    return false;
31
}
32
33
#ifndef __has_builtin
34
#    define __has_builtin(x) 0
35
#endif
36
37
template<typename T>
38
inline bool checkedAdd(T x, T y, T *z)
39
326
{
40
326
#if __has_builtin(__builtin_add_overflow)
41
326
    return __builtin_add_overflow(x, y, z);
42
#else
43
    const auto lz = static_cast<long long>(x) + static_cast<long long>(y);
44
    return checkedAssign(lz, z);
45
#endif
46
326
}
bool checkedAdd<int>(int, int, int*)
Line
Count
Source
39
326
{
40
326
#if __has_builtin(__builtin_add_overflow)
41
326
    return __builtin_add_overflow(x, y, z);
42
#else
43
    const auto lz = static_cast<long long>(x) + static_cast<long long>(y);
44
    return checkedAssign(lz, z);
45
#endif
46
326
}
Unexecuted instantiation: bool checkedAdd<unsigned int>(unsigned int, unsigned int, unsigned int*)
47
48
template<>
49
inline bool checkedAdd<long long>(long long x, long long y, long long *z)
50
207k
{
51
207k
#if __has_builtin(__builtin_add_overflow)
52
207k
    return __builtin_add_overflow(x, y, z);
53
#else
54
    if (x > 0 && y > 0) {
55
        if (x > (std::numeric_limits<long long>::max)() - y) {
56
            return true;
57
        }
58
    } else if (x < 0 && y < 0) {
59
        if (x < (std::numeric_limits<long long>::min)() - y) {
60
            return true;
61
        }
62
    }
63
    *z = x + y;
64
    return false;
65
#endif
66
207k
}
67
68
template<typename T>
69
inline bool checkedSubtraction(T x, T y, T *z)
70
0
{
71
0
#if __has_builtin(__builtin_sub_overflow)
72
0
    return __builtin_sub_overflow(x, y, z);
73
#else
74
    const auto lz = static_cast<long long>(x) - static_cast<long long>(y);
75
    return checkedAssign(lz, z);
76
#endif
77
0
}
78
79
template<typename T>
80
inline bool checkedMultiply(T x, T y, T *z)
81
940k
{
82
940k
#if __has_builtin(__builtin_mul_overflow)
83
940k
    return __builtin_mul_overflow(x, y, z);
84
#else
85
    const auto lz = static_cast<long long>(x) * static_cast<long long>(y);
86
    return checkedAssign(lz, z);
87
#endif
88
940k
}
bool checkedMultiply<int>(int, int, int*)
Line
Count
Source
81
940k
{
82
940k
#if __has_builtin(__builtin_mul_overflow)
83
940k
    return __builtin_mul_overflow(x, y, z);
84
#else
85
    const auto lz = static_cast<long long>(x) * static_cast<long long>(y);
86
    return checkedAssign(lz, z);
87
#endif
88
940k
}
Unexecuted instantiation: bool checkedMultiply<unsigned int>(unsigned int, unsigned int, unsigned int*)
89
90
template<>
91
inline bool checkedMultiply<long long>(long long x, long long y, long long *z)
92
0
{
93
0
#if __has_builtin(__builtin_mul_overflow)
94
0
    return __builtin_mul_overflow(x, y, z);
95
#else
96
    if (x != 0 && (std::numeric_limits<long long>::max)() / x < y) {
97
        return true;
98
    }
99
100
    *z = x * y;
101
    return false;
102
#endif
103
0
}
104
105
template<typename T>
106
inline T safeAverage(T a, T b)
107
0
{
108
0
    static_assert((std::numeric_limits<long long>::max)() > (std::numeric_limits<T>::max)(), "The max of long long type must be larger to perform overflow checks.");
109
0
    static_assert((std::numeric_limits<long long>::min)() < (std::numeric_limits<T>::min)(), "The min of long long type must be smaller to perform overflow checks.");
110
111
0
    return static_cast<T>((static_cast<long long>(a) + static_cast<long long>(b)) / 2);
112
0
}
113
114
#endif // GOO_CHECKED_OPS_H