From 559eb7ff266b1da7b7ae9ec2fd366b43ad333bc1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:50:41 +0100 Subject: [PATCH] Fix integer overflows in timelib There are edge cases where computations can cause an integer overflow, which is undefined behaviour. Lately, some fuzzers seem to be hitting these quite frequently. While this behaviour is undefined, it doesn't actually matter in practice, the worst effect is having a wrong computation result, but no sane person would do computations on e.g. the year pow(2,63). Still, undefined behaviour is bad. Make the wrapping behaviour defined by using -fwrapv when possible. The scope of this is limited to timelib and doesn't affect php_date.c. The reason for this is that this may in theory prevent some optimizations and it also seems bad to affect code that lives so close to the PHP-native edge. I tested all issues. This fixes all but one issues, the remaining issue is in php_date.c. Fixes GH-13881. Fixes GH-14075. Fixes GH-15150. Fixes GH-16034. Fixes GH-16035. Fixes GH-16048. Fixes GH-16050. Fixes GH-16051. Fixes GH-16052. Fixes GH-16775. Fixes GH-16864. Fixes GH-16865. Fixes GH-16975. Fixes GH-17025. Fixes GH-17059. Closes GH-17060. --- NEWS | 4 ++++ ext/date/config.w32 | 3 +++ ext/date/config0.m4 | 13 +++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index d5989e61d6b..8663f30c99d 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ PHP NEWS - Curl: . Added curl_multi_get_handles(). (timwolla) +- Date: + . Fix undefined behaviour problems regarding integer overflow in extreme edge + cases. (nielsdos, cmb, ilutov) + - DOM: . Added Dom\Element::$outerHTML. (nielsdos) . Added Dom\Element::insertAdjacentHTML(). (nielsdos) diff --git a/ext/date/config.w32 b/ext/date/config.w32 index b053e27aae3..3dad8d438ca 100644 --- a/ext/date/config.w32 +++ b/ext/date/config.w32 @@ -5,6 +5,9 @@ PHP_DATE = "yes"; ADD_SOURCES("ext/date/lib", "astro.c timelib.c dow.c parse_date.c parse_posix.c parse_tz.c tm2unixtime.c unixtime2tm.c parse_iso_intervals.c interval.c", "date"); ADD_FLAG('CFLAGS_DATE', "/wd4244"); +if (CLANG_TOOLSET) { + ADD_FLAG('CFLAGS_BD_EXT_DATE_LIB', "-fwrapv"); +} var tl_config = FSO.CreateTextFile("ext/date/lib/timelib_config.h", true); tl_config.WriteLine("#include \"config.w32.h\""); diff --git a/ext/date/config0.m4 b/ext/date/config0.m4 index 5af6be13faf..9091803edfa 100644 --- a/ext/date/config0.m4 +++ b/ext/date/config0.m4 @@ -8,15 +8,24 @@ AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough], [PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -Wno-implicit-fallthrough"],, [-Werror]) -PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -I@ext_builddir@/lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -DHAVE_TIMELIB_CONFIG_H=1" +PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -DHAVE_TIMELIB_CONFIG_H=1" +PHP_TIMELIB_CFLAGS="$PHP_DATE_CFLAGS" +PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -I@ext_builddir@/lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" + +AX_CHECK_COMPILE_FLAG([-fwrapv], + [PHP_TIMELIB_CFLAGS="$PHP_TIMELIB_CFLAGS -fwrapv"],, + [-Werror]) + timelib_sources="lib/astro.c lib/dow.c lib/parse_date.c lib/parse_tz.c lib/parse_posix.c lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c lib/parse_iso_intervals.c lib/interval.c" PHP_NEW_EXTENSION([date], - [php_date.c $timelib_sources], + [php_date.c], [no],, [$PHP_DATE_CFLAGS]) +PHP_ADD_SOURCES([$ext_dir], [$timelib_sources], [$PHP_TIMELIB_CFLAGS]) + PHP_ADD_BUILD_DIR([$ext_builddir/lib], [1]) PHP_ADD_INCLUDE([$ext_builddir/lib]) PHP_ADD_INCLUDE([$ext_srcdir/lib])