From 2238d6bf118b50d55dc02de8c480f426d8c867fc Mon Sep 17 00:00:00 2001 From: Giovanni Giacobbi Date: Sun, 18 Sep 2022 22:47:45 +0200 Subject: [PATCH] Check for '__builtin_mul_overflow' before using it --- build/php.m4 | 21 +++++++++++++++++++++ configure.ac | 2 ++ main/reallocarray.c | 7 +++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/build/php.m4 b/build/php.m4 index 637b2a180160f..235b94753ac38 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -2567,6 +2567,27 @@ AC_DEFUN([PHP_CHECK_BUILTIN_CTZLL], [ AC_DEFINE_UNQUOTED([PHP_HAVE_BUILTIN_CTZLL], [$have_builtin_ctzll], [Whether the compiler supports __builtin_ctzll]) ]) +dnl +dnl PHP_CHECK_BUILTIN_MUL_OVERFLOW +dnl +AC_DEFUN([PHP_CHECK_BUILTIN_MUL_OVERFLOW], [ + AC_MSG_CHECKING([for __builtin_mul_overflow]) + + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[ + long tmpvar; + return __builtin_mul_overflow(3, 7, &tmpvar); + ]])], [ + have_builtin_mul_overflow=1 + AC_MSG_RESULT([yes]) + ], [ + have_builtin_mul_overflow=0 + AC_MSG_RESULT([no]) + ]) + + AC_DEFINE_UNQUOTED([PHP_HAVE_BUILTIN_MUL_OVERFLOW], + [$have_builtin_mul_overflow], [Whether the compiler supports __builtin_mul_overflow]) +]) + dnl dnl PHP_CHECK_BUILTIN_SMULL_OVERFLOW dnl diff --git a/configure.ac b/configure.ac index 44f6da3f7d1d5..902696007e6c0 100644 --- a/configure.ac +++ b/configure.ac @@ -494,6 +494,8 @@ dnl Check __builtin_ctzl PHP_CHECK_BUILTIN_CTZL dnl Check __builtin_ctzll PHP_CHECK_BUILTIN_CTZLL +dnl Check __builtin_mul_overflow +PHP_CHECK_BUILTIN_MUL_OVERFLOW dnl Check __builtin_smull_overflow PHP_CHECK_BUILTIN_SMULL_OVERFLOW dnl Check __builtin_smulll_overflow diff --git a/main/reallocarray.c b/main/reallocarray.c index 95500ebdd8591..4508a28429ffe 100644 --- a/main/reallocarray.c +++ b/main/reallocarray.c @@ -23,10 +23,13 @@ PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz) { size_t r; -#ifndef _WIN32 +#ifdef _WIN32 + if (SizeTMult(nmb, siz, &r) != S_OK) { +#elif PHP_HAVE_BUILTIN_MUL_OVERFLOW if (__builtin_mul_overflow(nmb, siz, &r)) { #else - if (SizeTMult(nmb, siz, &r) != S_OK) { + r = siz * nmb; + if (siz != 0 && r / siz != nmb) { #endif // EOVERFLOW may have been, arguably, more appropriate // but this is what other implementations set