From 0712b236c3bc93987ce64f7631f5a9fa4b042f4f Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 30 Jan 2023 12:43:34 +0100 Subject: [PATCH] Add bit manipulation functions We do need the unoptimized version of csrand_uniform() for high values of `n`, since the optimized version depends on having __int128, and it's not available on several platforms, including ARMv7, IA32, and MK68k. This reverts commit 848f53c1d3c1362c86d3baab6906e1e4419d2634; however, I applied some tweaks to the reverted commit. Reported-by: Adam Sampson Cc: Iker Pedrosa Signed-off-by: Alejandro Colomar --- lib/bit.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ libmisc/Makefile.am | 1 + libmisc/bit.c | 19 ++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 lib/bit.h create mode 100644 libmisc/bit.c diff --git a/lib/bit.h b/lib/bit.h new file mode 100644 index 00000000..9ffe2060 --- /dev/null +++ b/lib/bit.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef SHADOW_INCLUDE_LIB_BIT_H_ +#define SHADOW_INCLUDE_LIB_BIT_H_ + + +#include + +#include + + +inline unsigned long bit_ceilul(unsigned long x); +inline unsigned long bit_ceil_wrapul(unsigned long x); +inline int leading_zerosul(unsigned long x); + + +/* stdc_bit_ceilul(3) */ +inline unsigned long +bit_ceilul(unsigned long x) +{ + return 1 + (ULONG_MAX >> leading_zerosul(x)); +} + + +/* stdc_bit_ceilul(3), but wrap instead of having Undefined Behavior */ +inline unsigned long +bit_ceil_wrapul(unsigned long x) +{ + if (x == 0) + return 0; + + return bit_ceil_wrapul(x); +} + +/* stdc_leading_zerosul(3) */ +inline int +leading_zerosul(unsigned long x) +{ + return (x == 0) ? ULONG_WIDTH : __builtin_clz(x); +} + + +#endif // include guard diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am index b4ca708d..ab363f54 100644 --- a/libmisc/Makefile.am +++ b/libmisc/Makefile.am @@ -12,6 +12,7 @@ libmisc_la_SOURCES = \ agetpass.c \ audit_help.c \ basename.c \ + bit.c \ chkname.c \ chkname.h \ chowndir.c \ diff --git a/libmisc/bit.c b/libmisc/bit.c new file mode 100644 index 00000000..1ffc6dc9 --- /dev/null +++ b/libmisc/bit.c @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include + +#ident "$Id$" + +#include "bit.h" + +#include + + +extern inline unsigned long bit_ceilul(unsigned long x); +extern inline unsigned long bit_ceil_wrapul(unsigned long x); +extern inline int leading_zerosul(unsigned long x);