1 /* $NetBSD: overflow.h,v 1.3 2026/04/08 00:16:16 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 #include <isc/util.h> 19 20 /* 21 * It is awkward to support signed numbers as well, so keep it simple 22 * (with a safety check). 23 */ 24 #define ISC_OVERFLOW_IS_UNSIGNED(a) \ 25 ({ \ 26 STATIC_ASSERT((typeof(a))-1 > 0, \ 27 "overflow checks require unsigned types"); \ 28 (a); \ 29 }) 30 31 #define ISC_OVERFLOW_UINT_MAX(a) ISC_OVERFLOW_IS_UNSIGNED((typeof(a))-1) 32 33 #define ISC_OVERFLOW_UINT_MIN(a) ISC_OVERFLOW_IS_UNSIGNED(0) 34 35 /* 36 * Return true on overflow, e.g. 37 * 38 * bool overflow = ISC_OVERFLOW_MUL(count, sizeof(array[0]), &bytes); 39 * INSIST(!overflow); 40 */ 41 42 #if HAVE_BUILTIN_MUL_OVERFLOW 43 #define ISC_OVERFLOW_MUL(a, b, cp) __builtin_mul_overflow(a, b, cp) 44 #else 45 #define ISC_OVERFLOW_MUL(a, b, cp) \ 46 ((ISC_OVERFLOW_UINT_MAX(a) / (b) > (a)) ? (*(cp) = (a) * (b), false) \ 47 : true) 48 #endif 49 50 #if HAVE_BUILTIN_ADD_OVERFLOW 51 #define ISC_OVERFLOW_ADD(a, b, cp) __builtin_add_overflow(a, b, cp) 52 #else 53 #define ISC_OVERFLOW_ADD(a, b, cp) \ 54 ((ISC_OVERFLOW_UINT_MAX(a) - (b) > (a)) ? (*(cp) = (a) + (b), false) \ 55 : true) 56 #endif 57 58 #if HAVE_BUILTIN_SUB_OVERFLOW 59 #define ISC_OVERFLOW_SUB(a, b, cp) __builtin_sub_overflow(a, b, cp) 60 #else 61 #define ISC_OVERFLOW_SUB(a, b, cp) \ 62 ((ISC_OVERFLOW_UINT_MIN(a) + (b) < (a)) ? (*(cp) = (a) - (b), false) \ 63 : true) 64 #endif 65 66 #define ISC_CHECKED_MUL(a, b) \ 67 ({ \ 68 typeof(a) _c; \ 69 bool _overflow = ISC_OVERFLOW_MUL(a, b, &_c); \ 70 INSIST(!_overflow); \ 71 _c; \ 72 }) 73 74 #define ISC_CHECKED_ADD(a, b) \ 75 ({ \ 76 typeof(a) _c; \ 77 bool _overflow = ISC_OVERFLOW_ADD(a, b, &_c); \ 78 INSIST(!_overflow); \ 79 _c; \ 80 }) 81 82 #define ISC_CHECKED_SUB(a, b) \ 83 ({ \ 84 typeof(a) _c; \ 85 bool _overflow = ISC_OVERFLOW_SUB(a, b, cp); \ 86 INSIST(!_overflow); \ 87 _c; \ 88 }) 89 90 #define ISC_CHECKED_MUL_ADD(a, b, c) \ 91 ({ \ 92 size_t _d; \ 93 bool _overflow = ISC_OVERFLOW_MUL(a, b, &_d) || \ 94 ISC_OVERFLOW_ADD(_d, c, &_d); \ 95 INSIST(!_overflow); \ 96 _d; \ 97 }) 98