From ecae12323d44cd739662051a2b9a5965cbe0e965 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Sat, 20 Feb 2016 23:41:33 -0800 Subject: [PATCH] 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. --- configure.ac | 14 +++++++++++++- .../internal/jemalloc_internal_defs.h.in | 8 ++++++-- include/jemalloc/internal/private_symbols.txt | 3 +++ include/jemalloc/internal/prng.h | 2 +- include/jemalloc/internal/util.h | 19 +++++++++++++++++-- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 8adb6f7b..da4ee3ac 100644 --- a/configure.ac +++ b/configure.ac @@ -201,6 +201,16 @@ else fi 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]) if test "x${ac_cv_sizeof_intmax_t}" = "x16" ; then 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 One of those two functions should (theoretically) exist on all platforms 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. JE_COMPILABLE([a program using __builtin_ffsl], [ #include @@ -1053,6 +1063,7 @@ JE_COMPILABLE([a program using __builtin_ffsl], [ } ], [je_cv_gcc_builtin_ffsl]) 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_FFS], [__builtin_ffs]) else @@ -1067,6 +1078,7 @@ else } ], [je_cv_function_ffsl]) 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_FFS], [ffs]) else diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in index c84e27c9..4bcda716 100644 --- a/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -189,9 +189,10 @@ #undef JEMALLOC_TLS /* - * ffs()/ffsl() functions to use for bitmapping. Don't use these directly; - * instead, use jemalloc_ffs() or jemalloc_ffsl() from util.h. + * ffs*() functions to use for bitmapping. Don't use these directly; instead, + * use jemalloc_ffs*() from util.h. */ +#undef JEMALLOC_INTERNAL_FFSLL #undef JEMALLOC_INTERNAL_FFSL #undef JEMALLOC_INTERNAL_FFS @@ -241,6 +242,9 @@ /* sizeof(long) == 2^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. */ #undef LG_SIZEOF_INTMAX_T diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt index 284410a9..8428cf48 100644 --- a/include/jemalloc/internal/private_symbols.txt +++ b/include/jemalloc/internal/private_symbols.txt @@ -292,6 +292,9 @@ isqalloc isthreaded ivsalloc ixalloc +jemalloc_ffs +jemalloc_ffs64 +jemalloc_ffsl jemalloc_postfork_child jemalloc_postfork_parent jemalloc_prefork diff --git a/include/jemalloc/internal/prng.h b/include/jemalloc/internal/prng.h index 83c90906..44d67c9a 100644 --- a/include/jemalloc/internal/prng.h +++ b/include/jemalloc/internal/prng.h @@ -64,7 +64,7 @@ prng_range(uint64_t *state, uint64_t range) assert(range > 1); /* 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. */ do { diff --git a/include/jemalloc/internal/util.h b/include/jemalloc/internal/util.h index dfe5c93c..39f70878 100644 --- a/include/jemalloc/internal/util.h +++ b/include/jemalloc/internal/util.h @@ -121,6 +121,7 @@ void malloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2); #ifdef JEMALLOC_H_INLINES #ifndef JEMALLOC_ENABLE_INLINE +int jemalloc_ffs64(uint64_t bitmap); int jemalloc_ffsl(long bitmap); int jemalloc_ffs(int bitmap); 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_)) /* Sanity check. */ -#if !defined(JEMALLOC_INTERNAL_FFSL) || !defined(JEMALLOC_INTERNAL_FFS) -# error Both JEMALLOC_INTERNAL_FFSL && JEMALLOC_INTERNAL_FFS should have been defined by configure +#if !defined(JEMALLOC_INTERNAL_FFSLL) || !defined(JEMALLOC_INTERNAL_FFSL) \ + || !defined(JEMALLOC_INTERNAL_FFS) +# error JEMALLOC_INTERNAL_FFS{,L,LL} should have been defined by configure #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_ffsl(long bitmap) {