Fix overflow in prng_range().

Add jemalloc_ffs64() and use it instead of jemalloc_ffsl() in
prng_range(), since long is not guaranteed to be a 64-bit type.
This commit is contained in:
Jason Evans 2016-02-20 23:41:33 -08:00
parent aac93f414e
commit ecae12323d
5 changed files with 40 additions and 6 deletions

View File

@ -201,6 +201,16 @@ else
fi fi
AC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG]) AC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG])
AC_CHECK_SIZEOF([long long])
if test "x${ac_cv_sizeof_long_long}" = "x8" ; then
LG_SIZEOF_LONG_LONG=3
elif test "x${ac_cv_sizeof_long_long}" = "x4" ; then
LG_SIZEOF_LONG_LONG=2
else
AC_MSG_ERROR([Unsupported long long size: ${ac_cv_sizeof_long_long}])
fi
AC_DEFINE_UNQUOTED([LG_SIZEOF_LONG_LONG], [$LG_SIZEOF_LONG_LONG])
AC_CHECK_SIZEOF([intmax_t]) AC_CHECK_SIZEOF([intmax_t])
if test "x${ac_cv_sizeof_intmax_t}" = "x16" ; then if test "x${ac_cv_sizeof_intmax_t}" = "x16" ; then
LG_SIZEOF_INTMAX_T=4 LG_SIZEOF_INTMAX_T=4
@ -1040,7 +1050,7 @@ dnl ============================================================================
dnl Check for __builtin_ffsl(), then ffsl(3), and fail if neither are found. dnl Check for __builtin_ffsl(), then ffsl(3), and fail if neither are found.
dnl One of those two functions should (theoretically) exist on all platforms dnl One of those two functions should (theoretically) exist on all platforms
dnl that jemalloc currently has a chance of functioning on without modification. dnl that jemalloc currently has a chance of functioning on without modification.
dnl We additionally assume ffs() or __builtin_ffs() are defined if dnl We additionally assume ffs[ll]() or __builtin_ffs[ll]() are defined if
dnl ffsl() or __builtin_ffsl() are defined, respectively. dnl ffsl() or __builtin_ffsl() are defined, respectively.
JE_COMPILABLE([a program using __builtin_ffsl], [ JE_COMPILABLE([a program using __builtin_ffsl], [
#include <stdio.h> #include <stdio.h>
@ -1053,6 +1063,7 @@ JE_COMPILABLE([a program using __builtin_ffsl], [
} }
], [je_cv_gcc_builtin_ffsl]) ], [je_cv_gcc_builtin_ffsl])
if test "x${je_cv_gcc_builtin_ffsl}" = "xyes" ; then if test "x${je_cv_gcc_builtin_ffsl}" = "xyes" ; then
AC_DEFINE([JEMALLOC_INTERNAL_FFSLL], [__builtin_ffsll])
AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [__builtin_ffsl]) AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [__builtin_ffsl])
AC_DEFINE([JEMALLOC_INTERNAL_FFS], [__builtin_ffs]) AC_DEFINE([JEMALLOC_INTERNAL_FFS], [__builtin_ffs])
else else
@ -1067,6 +1078,7 @@ else
} }
], [je_cv_function_ffsl]) ], [je_cv_function_ffsl])
if test "x${je_cv_function_ffsl}" = "xyes" ; then if test "x${je_cv_function_ffsl}" = "xyes" ; then
AC_DEFINE([JEMALLOC_INTERNAL_FFSLL], [ffsll])
AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [ffsl]) AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [ffsl])
AC_DEFINE([JEMALLOC_INTERNAL_FFS], [ffs]) AC_DEFINE([JEMALLOC_INTERNAL_FFS], [ffs])
else else

View File

@ -189,9 +189,10 @@
#undef JEMALLOC_TLS #undef JEMALLOC_TLS
/* /*
* ffs()/ffsl() functions to use for bitmapping. Don't use these directly; * ffs*() functions to use for bitmapping. Don't use these directly; instead,
* instead, use jemalloc_ffs() or jemalloc_ffsl() from util.h. * use jemalloc_ffs*() from util.h.
*/ */
#undef JEMALLOC_INTERNAL_FFSLL
#undef JEMALLOC_INTERNAL_FFSL #undef JEMALLOC_INTERNAL_FFSL
#undef JEMALLOC_INTERNAL_FFS #undef JEMALLOC_INTERNAL_FFS
@ -241,6 +242,9 @@
/* sizeof(long) == 2^LG_SIZEOF_LONG. */ /* sizeof(long) == 2^LG_SIZEOF_LONG. */
#undef LG_SIZEOF_LONG #undef LG_SIZEOF_LONG
/* sizeof(long long) == 2^LG_SIZEOF_LONG_LONG. */
#undef LG_SIZEOF_LONG_LONG
/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */ /* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */
#undef LG_SIZEOF_INTMAX_T #undef LG_SIZEOF_INTMAX_T

View File

@ -292,6 +292,9 @@ isqalloc
isthreaded isthreaded
ivsalloc ivsalloc
ixalloc ixalloc
jemalloc_ffs
jemalloc_ffs64
jemalloc_ffsl
jemalloc_postfork_child jemalloc_postfork_child
jemalloc_postfork_parent jemalloc_postfork_parent
jemalloc_prefork jemalloc_prefork

View File

@ -64,7 +64,7 @@ prng_range(uint64_t *state, uint64_t range)
assert(range > 1); assert(range > 1);
/* Compute the ceiling of lg(range). */ /* Compute the ceiling of lg(range). */
lg_range = jemalloc_ffsl(pow2_ceil_u64(range)) - 1; lg_range = jemalloc_ffs64(pow2_ceil_u64(range)) - 1;
/* Generate a result in [0..range) via repeated trial. */ /* Generate a result in [0..range) via repeated trial. */
do { do {

View File

@ -121,6 +121,7 @@ void malloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);
#ifdef JEMALLOC_H_INLINES #ifdef JEMALLOC_H_INLINES
#ifndef JEMALLOC_ENABLE_INLINE #ifndef JEMALLOC_ENABLE_INLINE
int jemalloc_ffs64(uint64_t bitmap);
int jemalloc_ffsl(long bitmap); int jemalloc_ffsl(long bitmap);
int jemalloc_ffs(int bitmap); int jemalloc_ffs(int bitmap);
uint64_t pow2_ceil_u64(uint64_t x); uint64_t pow2_ceil_u64(uint64_t x);
@ -134,10 +135,24 @@ int get_errno(void);
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_)) #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))
/* Sanity check. */ /* Sanity check. */
#if !defined(JEMALLOC_INTERNAL_FFSL) || !defined(JEMALLOC_INTERNAL_FFS) #if !defined(JEMALLOC_INTERNAL_FFSLL) || !defined(JEMALLOC_INTERNAL_FFSL) \
# error Both JEMALLOC_INTERNAL_FFSL && JEMALLOC_INTERNAL_FFS should have been defined by configure || !defined(JEMALLOC_INTERNAL_FFS)
# error JEMALLOC_INTERNAL_FFS{,L,LL} should have been defined by configure
#endif #endif
JEMALLOC_ALWAYS_INLINE int
jemalloc_ffs64(uint64_t bitmap)
{
#if LG_SIZEOF_LONG == 3
return (JEMALLOC_INTERNAL_FFSL(bitmap));
#elif LG_SIZEOF_LONG_LONG == 3
return (JEMALLOC_INTERNAL_FFSLL(bitmap));
#else
#error No implementation for 64-bit ffs()
#endif
}
JEMALLOC_ALWAYS_INLINE int JEMALLOC_ALWAYS_INLINE int
jemalloc_ffsl(long bitmap) jemalloc_ffsl(long bitmap)
{ {