/src/botan/build/include/botan/internal/safeint.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Safe(r) Integer Handling |
3 | | * (C) 2016 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #ifndef BOTAN_UTILS_SAFE_INT_H_ |
9 | | #define BOTAN_UTILS_SAFE_INT_H_ |
10 | | |
11 | | #include <botan/exceptn.h> |
12 | | #include <botan/internal/fmt.h> |
13 | | #include <optional> |
14 | | #include <string_view> |
15 | | |
16 | | #if defined(_MSC_VER) |
17 | | #include <intsafe.h> |
18 | | #endif |
19 | | |
20 | | namespace Botan { |
21 | | |
22 | | class Integer_Overflow_Detected final : public Exception { |
23 | | public: |
24 | | Integer_Overflow_Detected(std::string_view file, int line) : |
25 | 0 | Exception(fmt("Integer overflow detected at {}:{}", file, line)) {} |
26 | | |
27 | 0 | ErrorType error_type() const noexcept override { return ErrorType::InternalError; } |
28 | | }; |
29 | | |
30 | 721k | inline size_t checked_add(size_t x, size_t y, const char* file, int line) { |
31 | 721k | #if BOTAN_COMPILER_HAS_BUILTIN(__builtin_add_overflow) |
32 | 721k | size_t z; |
33 | 721k | if(__builtin_add_overflow(x, y, &z)) [[unlikely]] |
34 | | #elif defined(_MSC_VER) |
35 | | size_t z; |
36 | | if(SizeTAdd(x, y, &z) != S_OK) [[unlikely]] |
37 | | #else |
38 | | size_t z = x + y; |
39 | | if(z < x) [[unlikely]] |
40 | | #endif |
41 | 0 | { |
42 | 0 | throw Integer_Overflow_Detected(file, line); |
43 | 0 | } |
44 | 721k | return z; |
45 | 721k | } |
46 | | |
47 | 38.4M | inline std::optional<size_t> checked_mul(size_t x, size_t y) { |
48 | 38.4M | #if BOTAN_COMPILER_HAS_BUILTIN(__builtin_add_overflow) |
49 | 38.4M | size_t z; |
50 | 38.4M | if(__builtin_mul_overflow(x, y, &z)) [[unlikely]] |
51 | | #elif defined(_MSC_VER) |
52 | | size_t z; |
53 | | if(SizeTMult(x, y, &z) != S_OK) [[unlikely]] |
54 | | #else |
55 | | size_t z = x * y; |
56 | | if(y && z / y != x) [[unlikely]] |
57 | | #endif |
58 | 0 | { |
59 | 0 | return std::nullopt; |
60 | 0 | } |
61 | 38.4M | return z; |
62 | 38.4M | } |
63 | | |
64 | | template <typename RT, typename AT> |
65 | | RT checked_cast_to(AT i) { |
66 | | RT c = static_cast<RT>(i); |
67 | | if(i != static_cast<AT>(c)) |
68 | | throw Internal_Error("Error during integer conversion"); |
69 | | return c; |
70 | | } |
71 | | |
72 | 722k | #define BOTAN_CHECKED_ADD(x, y) checked_add(x, y, __FILE__, __LINE__) |
73 | 38.4M | #define BOTAN_CHECKED_MUL(x, y) checked_mul(x, y) |
74 | | |
75 | | } // namespace Botan |
76 | | |
77 | | #endif |