diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e5b094acdb3c..2a06aadb8dc2 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -32,11 +32,11 @@ #endif #ifdef PHP_WIN32 -static __inline __int64 php_date_llabs( __int64 i ) { return i >= 0? i: -i; } +static __inline unsigned __int64 php_date_llabs( __int64 i ) { return i >= 0 ? (unsigned __int64)i : -(unsigned __int64)i; } #elif defined(__GNUC__) && __GNUC__ < 3 -static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i; } +static __inline unsigned long long php_date_llabs( __int64_t i ) { return i >= 0 ? (unsigned long long)i : -(unsigned long long)i; } #else -static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; } +static inline unsigned long long php_date_llabs( long long i ) { return i >= 0 ? (unsigned long long)i : -(unsigned long long)i; } #endif #ifdef PHP_WIN32 @@ -742,9 +742,9 @@ static zend_string *date_format(const char *format, size_t format_len, const tim /* year */ case 'L': length = slprintf(buffer, sizeof(buffer), "%d", timelib_is_leap((int) t->y)); break; case 'y': length = slprintf(buffer, sizeof(buffer), "%02d", (int) (t->y % 100)); break; - case 'Y': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break; - case 'x': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : (t->y >= 10000 ? "+" : ""), php_date_llabs((timelib_sll) t->y)); break; - case 'X': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : "+", php_date_llabs((timelib_sll) t->y)); break; + case 'Y': length = slprintf(buffer, sizeof(buffer), "%s%04llu", t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break; + case 'x': length = slprintf(buffer, sizeof(buffer), "%s%04llu", t->y < 0 ? "-" : (t->y >= 10000 ? "+" : ""), php_date_llabs((timelib_sll) t->y)); break; + case 'X': length = slprintf(buffer, sizeof(buffer), "%s%04llu", t->y < 0 ? "-" : "+", php_date_llabs((timelib_sll) t->y)); break; /* time */ case 'a': length = slprintf(buffer, sizeof(buffer), "%s", t->h >= 12 ? "pm" : "am"); break; diff --git a/ext/date/tests/gh18422.phpt b/ext/date/tests/gh18422.phpt new file mode 100644 index 000000000000..643476615277 --- /dev/null +++ b/ext/date/tests/gh18422.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-18422 (int overflow in Date extension) +--FILE-- +format("Y"), "\n"; +echo $dto->format("x"), "\n"; +echo $dto->format("X"), "\n"; + +echo date_create("2024-06-15")->format("Y"), "\n"; +echo date_create("-0042-01-01")->format("Y"), "\n"; +?> +--EXPECTF-- +-%d +-%d +-%d +2024 +-0042