mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Add <isc/overflow.h> for checked mul, add, and sub
The `ISC_OVERFLOW_XXX()` macros are usually wrappers around `__builtin_xxx_overflow()`, with alternative implementations for compilers that lack the builtins. Replace the overflow checks in `isc/time.c` with the new macros.
This commit is contained in:
parent
bf6f8abb2a
commit
7474cad4ad
3 changed files with 99 additions and 16 deletions
|
|
@ -61,6 +61,7 @@ libisc_la_HEADERS = \
|
|||
include/isc/nonce.h \
|
||||
include/isc/once.h \
|
||||
include/isc/os.h \
|
||||
include/isc/overflow.h \
|
||||
include/isc/parseint.h \
|
||||
include/isc/pause.h \
|
||||
include/isc/portset.h \
|
||||
|
|
|
|||
95
lib/isc/include/isc/overflow.h
Normal file
95
lib/isc/include/isc/overflow.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <isc/util.h>
|
||||
|
||||
/*
|
||||
* It is awkward to support signed numbers as well, so keep it simple
|
||||
* (with a safety check).
|
||||
*/
|
||||
#define ISC_OVERFLOW_IS_UNSIGNED(a) \
|
||||
({ \
|
||||
STATIC_ASSERT((typeof(a))-1 > 0, \
|
||||
"overflow checks require unsigned types"); \
|
||||
(a); \
|
||||
})
|
||||
|
||||
#define ISC_OVERFLOW_UINT_MAX(a) ISC_OVERFLOW_IS_UNSIGNED((typeof(a))-1)
|
||||
|
||||
#define ISC_OVERFLOW_UINT_MIN(a) ISC_OVERFLOW_IS_UNSIGNED(0)
|
||||
|
||||
/*
|
||||
* Return true on overflow, e.g.
|
||||
*
|
||||
* bool overflow = ISC_OVERFLOW_MUL(count, sizeof(array[0]), &bytes);
|
||||
* INSIST(!overflow);
|
||||
*/
|
||||
|
||||
#if HAVE_BUILTIN_MUL_OVERFLOW
|
||||
#define ISC_OVERFLOW_MUL(a, b, cp) __builtin_mul_overflow(a, b, cp)
|
||||
#else
|
||||
#define ISC_OVERFLOW_MUL(a, b, cp) \
|
||||
((ISC_OVERFLOW_UINT_MAX(a) / (b) > (a)) ? (*(cp) = (a) * (b), false) \
|
||||
: true)
|
||||
#endif
|
||||
|
||||
#if HAVE_BUILTIN_ADD_OVERFLOW
|
||||
#define ISC_OVERFLOW_ADD(a, b, cp) __builtin_add_overflow(a, b, cp)
|
||||
#else
|
||||
#define ISC_OVERFLOW_ADD(a, b, cp) \
|
||||
((ISC_OVERFLOW_UINT_MAX(a) - (b) > (a)) ? (*(cp) = (a) + (b), false) \
|
||||
: true)
|
||||
#endif
|
||||
|
||||
#if HAVE_BUILTIN_SUB_OVERFLOW
|
||||
#define ISC_OVERFLOW_SUB(a, b, cp) __builtin_sub_overflow(a, b, cp)
|
||||
#else
|
||||
#define ISC_OVERFLOW_SUB(a, b, cp) \
|
||||
((ISC_OVERFLOW_UINT_MIN(a) + (b) < (a)) ? (*(cp) = (a) - (b), false) \
|
||||
: true)
|
||||
#endif
|
||||
|
||||
#define ISC_CHECKED_MUL(a, b) \
|
||||
({ \
|
||||
typeof(a) _c; \
|
||||
bool _overflow = ISC_OVERFLOW_MUL(a, b, &_c); \
|
||||
INSIST(!_overflow); \
|
||||
_c; \
|
||||
})
|
||||
|
||||
#define ISC_CHECKED_ADD(a, b) \
|
||||
({ \
|
||||
typeof(a) _c; \
|
||||
bool _overflow = ISC_OVERFLOW_ADD(a, b, &_c); \
|
||||
INSIST(!_overflow); \
|
||||
_c; \
|
||||
})
|
||||
|
||||
#define ISC_CHECKED_SUB(a, b) \
|
||||
({ \
|
||||
typeof(a) _c; \
|
||||
bool _overflow = ISC_OVERFLOW_SUB(a, b, cp); \
|
||||
INSIST(!_overflow); \
|
||||
_c; \
|
||||
})
|
||||
|
||||
#define ISC_CHECKED_MUL_ADD(a, b, c) \
|
||||
({ \
|
||||
size_t _d; \
|
||||
bool _overflow = ISC_OVERFLOW_MUL(a, b, &_d) || \
|
||||
ISC_OVERFLOW_ADD(_d, c, &_d); \
|
||||
INSIST(!_overflow); \
|
||||
_d; \
|
||||
})
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include <isc/log.h>
|
||||
#include <isc/overflow.h>
|
||||
#include <isc/strerr.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/time.h>
|
||||
|
|
@ -186,16 +187,9 @@ isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) {
|
|||
REQUIRE(t->nanoseconds < NS_PER_SEC && i->nanoseconds < NS_PER_SEC);
|
||||
|
||||
/* Seconds */
|
||||
#if HAVE_BUILTIN_ADD_OVERFLOW
|
||||
if (__builtin_add_overflow(t->seconds, i->seconds, &result->seconds)) {
|
||||
if (ISC_OVERFLOW_ADD(t->seconds, i->seconds, &result->seconds)) {
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
#else
|
||||
if (t->seconds > UINT_MAX - i->seconds) {
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
result->seconds = t->seconds + i->seconds;
|
||||
#endif
|
||||
|
||||
/* Nanoseconds */
|
||||
result->nanoseconds = t->nanoseconds + i->nanoseconds;
|
||||
|
|
@ -217,16 +211,9 @@ isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
|
|||
REQUIRE(t->nanoseconds < NS_PER_SEC && i->nanoseconds < NS_PER_SEC);
|
||||
|
||||
/* Seconds */
|
||||
#if HAVE_BUILTIN_SUB_OVERFLOW
|
||||
if (__builtin_sub_overflow(t->seconds, i->seconds, &result->seconds)) {
|
||||
if (ISC_OVERFLOW_SUB(t->seconds, i->seconds, &result->seconds)) {
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
#else
|
||||
if (t->seconds < i->seconds) {
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
result->seconds = t->seconds - i->seconds;
|
||||
#endif
|
||||
|
||||
/* Nanoseconds */
|
||||
if (t->nanoseconds >= i->nanoseconds) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue