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 */
|