File: CFOverflow.h

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (88 lines) | stat: -rw-r--r-- 2,836 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*	CFOverflow.h
	Copyright (c) 2017-2019, Apple Inc. and the Swift project authors
 
	Portions Copyright (c) 2017-2019, Apple Inc. and the Swift project authors
	Licensed under Apache License v2.0 with Runtime Library Exception
	See http://swift.org/LICENSE.txt for license information
	See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*/

#ifndef CFOverflow_h
#define CFOverflow_h

#include "CFBase.h"

static bool __os_warn_unused(bool x) __attribute__((__warn_unused_result__));
static bool __os_warn_unused(bool x) { return x; }

#if __has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow)

    #define os_add_overflow(a, b, res) __os_warn_unused(__builtin_add_overflow((a), (b), (res)))
    #define os_sub_overflow(a, b, res) __os_warn_unused(__builtin_sub_overflow((a), (b), (res)))
    #define os_mul_overflow(a, b, res) __os_warn_unused(__builtin_mul_overflow((a), (b), (res)))

#else
    #error Missing compiler support for overflow checking
#endif

typedef CF_ENUM(uint8_t, _CFOverflowResult) {
    _CFOverflowResultOK = 0,
    _CFOverflowResultNegativeParameters,
    _CFOverflowResultOverflows,
};

// Overflow utilities for positive integers
CF_INLINE _CFOverflowResult _CFPositiveIntegerProductWouldOverflow(CFIndex si_a, CFIndex si_b, CFIndex * /*_Nullable*/ outSum) {
    _CFOverflowResult result = _CFOverflowResultOK;
    CFIndex sum = 0;
    if (si_a < 0 || si_b < 0) {
        // we explicitly only implement a subset of the overflow checking, so report failure if out of domain
        result = _CFOverflowResultNegativeParameters;
    } else {
        if (os_mul_overflow(si_a, si_b, &sum)) {
            result = _CFOverflowResultOverflows;
        }
    }
    if (outSum) {
        *outSum = sum;
    }
    return result;
}

CF_INLINE _CFOverflowResult _CFPointerSumWouldOverflow(void const *p, size_t n, void * /*_Nullable*/ * /*_Nullable*/ outSum) {
    _CFOverflowResult result = _CFOverflowResultOK;
#if TARGET_RT_64_BIT
    uint64_t sum = 0;
    uint64_t const lhs = (uint64_t)p;
    uint64_t const rhs = (uint64_t)n;
#else
    uint32_t sum = 0;
    uint32_t const lhs = (uint32_t)p;
    uint32_t const rhs = (uint32_t)n;
#endif
    if (os_add_overflow(lhs, rhs, &sum)) {
        result = _CFOverflowResultOverflows;
    }
    if (outSum) {
        *outSum = (void *)sum;
    }
    return result;
}

#if TARGET_OS_WIN32
CF_INLINE bool _CFMultiplyBufferSizeWithoutOverflow(size_t a, size_t b, size_t *res) {
    int32_t res32 = 0;
    if (!os_mul_overflow((int32_t)a, (int32_t)b, &res32)) {
        *res = res32;
        return true;
    } else {
        return false;
    }
}
#else
#define _CFMultiplyBufferSizeWithoutOverflow(a, b, res) (os_mul_overflow((a), (b), (res)) == 0)
#endif

#endif /* CFOverflow_h */