From 73635c7e096eb36b52c1e874f9b76856c6a41228 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Mon, 17 Jun 2019 16:37:29 -0400 Subject: [PATCH 36/63] util.h: implement add()/mul()/sub() for more integer types. This adds the following: uint_add() uint_mul() uint_sub() long_sub() ulong_sub() Additionally it renames ulong_mult() to ulong_mul() and long_mult() to long_mul(). As before, all of these are available without caring about the types, as if declared: bool add(TYPE addend, TYPE addend, TYPE *sum); bool mul(TYPE factor, TYPE factor, TYPE *product); bool sub(TYPE minuend, TYPE subtractahend, TYPE *difference); If overflow would occur, the pointer target for the result is not changed and the function returns true, otherwise it returns false. Signed-off-by: Peter Jones --- src/efivar.h | 1 + src/safemath.h | 208 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 96 ----------------------- 3 files changed, 209 insertions(+), 96 deletions(-) create mode 100644 src/safemath.h diff --git a/src/efivar.h b/src/efivar.h index 3d4b429631e..646863d14c5 100644 --- a/src/efivar.h +++ b/src/efivar.h @@ -23,6 +23,7 @@ #include #include "util.h" +#include "safemath.h" #include "efivar_endian.h" #include "lib.h" #include "guid.h" diff --git a/src/safemath.h b/src/safemath.h new file mode 100644 index 00000000000..08dfef7ec0b --- /dev/null +++ b/src/safemath.h @@ -0,0 +1,208 @@ +/* + * safemath.h + * Copyright 2016-2019 Peter Jones + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * . + * + */ + +#ifndef SAFEMATH_H_ +#define SAFEMATH_H_ + +/* + * I'm not actually sure when these appear, but they're present in the + * version in front of me. + */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1 +#define int_add(a, b, c) __builtin_add_overflow(a, b, c) +#define uint_add(a, b, c) __builtin_add_overflow(a, b, c) +#define long_add(a, b, c) __builtin_add_overflow(a, b, c) +#define ulong_add(a, b, c) __builtin_add_overflow(a, b, c) + +#define int_mul(a, b, c) __builtin_mul_overflow(a, b, c) +#define uint_mul(a, b, c) __builtin_mul_overflow(a, b, c) +#define long_mul(a, b, c) __builtin_mul_overflow(a, b, c) +#define ulong_mul(a, b, c) __builtin_mul_overflow(a, b, c) + +#define int_sub(a, b, c) __builtin_sub_overflow(a, b, c) +#define uint_sub(a, b, c) __builtin_sub_overflow(a, b, c) +#define long_sub(a, b, c) __builtin_sub_overflow(a, b, c) +#define ulong_sub(a, b, c) __builtin_sub_overflow(a, b, c) +#endif +#endif + +#ifndef int_add +#define int_add(a, b, c) ({ \ + const int _limit = INT_MAX; \ + long int _ret = _limit - (a); \ + _ret = _ret > (b); \ + if (!_ret) \ + *(c) = ((a) + (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef uint_add +#define uint_add(a, b, c) ({ \ + const unsigned int _limit = UINT_MAX; \ + unsigned int _ret = _limit - (a); \ + _ret = _ret > (b); \ + if (!_ret) \ + *(c) = ((a) + (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef long_add +#define long_add(a, b, c) ({ \ + const long _limit = LONG_MAX; \ + long _ret = _limit - (a); \ + _ret = _ret > (b); \ + if (!_ret) \ + *(c) = ((a) + (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef ulong_add +#define ulong_add(a, b, c) ({ \ + const unsigned long _limit = ULONG_MAX; \ + unsigned long _ret = _limit - (a); \ + _ret = _ret > (b); \ + if (!_ret) \ + *(c) = ((a) + (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef int_mul +#define int_mul(a, b, c) ({ \ + int _ret; \ + _ret = __builtin_popcount(a) + __builtin_popcount(b); \ + _ret = _ret < ((sizeof(a) + sizeof(b)) << 4); \ + if (!_ret) \ + *(c) = ((a) * (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef uint_mul +#define uint_mul(a, b, c) int_mul(a, b, c) +#endif + +#ifndef long_mul +#define long_mul(a, b, c) int_mul(a, b, c) +#endif + +#ifndef ulong_mul +#define ulong_mul(a, b, c) int_mul(a, b, c) +#endif + +#ifndef int_sub +#define int_sub(a, b, c) ({ \ + const long _min_limit = INT_MIN; \ + const long _max_limit = INT_MAX; \ + int _ret; \ + _ret = _min_limit + (b); \ + _ret = !(_ret < (a)); \ + if (!_ret) { \ + _ret = _max_limit - (a); \ + _ret = _ret > (b); \ + } \ + if (!_ret) \ + *(c) = ((a) - (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef uint_sub +#define uint_sub(a, b, c) ({ \ + const unsigned int _limit = UINT_MAX; \ + unsigned int _ret = _limit - (a); \ + _ret = _ret > (b); \ + if (!_ret) \ + *(c) = ((a) - (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef long_sub +#define long_sub(a, b, c) ({ \ + const long _min_limit = LONG_MIN; \ + const long _max_limit = LONG_MAX; \ + int _ret; \ + _ret = _min_limit + (b); \ + _ret = !(_ret < (a)); \ + if (!_ret) { \ + _ret = _max_limit - (a); \ + _ret = _ret > (b); \ + } \ + if (!_ret) \ + *(c) = ((a) - (b)); \ + (bool)_ret; \ + }) +#endif + +#ifndef ulong_sub +#define ulong_sub(a, b, c) ({ \ + const unsigned long _limit = ULONG_MAX; \ + unsigned long _ret = _limit - (a); \ + _ret = _ret > (b); \ + if (!_ret) \ + *(c) = ((a) - (b)); \ + _ret; \ + }) +#endif + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1 +#define add(a, b, c) _Generic((c), \ + int *: int_add(a, b, c), \ + unsigned int *: uint_add(a, b, c), \ + long *: long_add(a, b, c), \ + unsigned long *: ulong_add(a, b, c)) +#define sub(a, b, c) _Generic((c), \ + int *: int_sub(a, b, c), \ + unsigned int *: uint_sub(a, b, c), \ + long *: long_sub(a, b, c), \ + unsigned long *: ulong_sub(a, b, c)) +#define mul(a, b, c) _Generic((c), \ + int *: int_sub(a, b, c), \ + unsigned int *: uint_mul(a, b, c), \ + long *: long_mul(a, b, c), \ + unsigned long *: ulong_mul(a, b, c)) +#endif +#endif + +#ifndef add +#define add(a, b, c) ({ \ + (*(c)) = ((a) + (b)); \ + }) +#endif +#ifndef mul +#define mul(a, b, c) ({ \ + (*(c)) = ((a) * (b)); \ + }) +#endif +#ifndef sub +#define sub(a, b, c) ({ \ + (*(c)) = ((a) - (b)); \ + }) +#endif + + +#endif /* !SAFEMATH_H_ */ +// vim:fenc=utf-8:tw=75:noet diff --git a/src/util.h b/src/util.h index 712abea2d42..3f68d812700 100644 --- a/src/util.h +++ b/src/util.h @@ -61,102 +61,6 @@ #define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x))) #endif -/* - * I'm not actually sure when these appear, but they're present in the - * version in front of me. - */ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) -#if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1 -#define int_add(a, b, c) __builtin_add_overflow(a, b, c) -#define long_add(a, b, c) __builtin_add_overflow(a, b, c) -#define long_mult(a, b, c) __builtin_mul_overflow(a, b, c) -#define ulong_add(a, b, c) __builtin_add_overflow(a, b, c) -#define ulong_mult(a, b, c) __builtin_mul_overflow(a, b, c) -#endif -#endif -#ifndef int_add -#define int_add(a, b, c) ({ \ - const int _limit = INT_MAX; \ - int _ret; \ - _ret = _limit - ((unsigned long long)a) > \ - ((unsigned long long)b); \ - if (!_ret) \ - *(c) = ((a) + (b)); \ - _ret; \ - }) -#endif -#ifndef long_add -#define long_add(a, b, c) ({ \ - const long _limit = LONG_MAX; \ - int _ret; \ - _ret = _limit - ((unsigned long long)a) > \ - ((unsigned long long)b); \ - if (!_ret) \ - *(c) = ((a) + (b)); \ - _ret; \ - }) -#endif -#ifndef long_mult -#define long_mult(a, b, c) ({ \ - const long _limit = LONG_MAX; \ - int _ret = 1; \ - if ((a) == 0 || (b) == 0) \ - _ret = 0; \ - else \ - _ret = _limit / (a) < (b); \ - if (!_ret) \ - *(c) = ((a) * (b)); \ - _ret; \ - }) -#endif -#ifndef ulong_add -#define ulong_add(a, b, c) ({ \ - const unsigned long _limit = ULONG_MAX; \ - int _ret; \ - _ret = _limit - ((unsigned long long)a) > \ - ((unsigned long long)b); \ - if (!_ret) \ - *(c) = ((a) + (b)); \ - _ret; \ - }) -#endif -#ifndef ulong_mult -#define ulong_mult(a, b, c) ({ \ - const unsigned long _limit = ULONG_MAX; \ - int _ret = 1; \ - if ((a) == 0 || (b) == 0) \ - _ret = 0; \ - else \ - _ret = _limit / (a) < (b); \ - if (!_ret) \ - *(c) = ((a) * (b)); \ - _ret; \ - }) -#endif - -#if defined(__GNUC__) && defined(__GNUC_MINOR__) -#if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1 -#define add(a, b, c) _Generic((c), \ - int *: int_add(a,b,c), \ - long *: long_add(a,b,c), \ - unsigned long *: ulong_add(a,b,c)) -#define mult(a, b, c) _Generic((c), \ - long *: long_mult(a,b,c), \ - unsigned long *: ulong_mult(a,b,c)) -#endif -#endif - -#ifndef add -#define add(a, b, c) ({ \ - (*(c)) = ((a) + (b)); \ - }) -#endif -#ifndef mult -#define mult(a, b, c) ({ \ - (*(c)) = ((a) * (b)); \ - }) -#endif - static inline int UNUSED read_file(int fd, uint8_t **result, size_t *bufsize) { -- 2.26.2