diff --git a/NEWS b/NEWS index cd9ddd3994cc..e8d87319aca6 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ PHP NEWS . Use recommended TYPE, HELP order for OpenMetrics metadata. (Marcel Hernandez) +- GD: + . Fixed imagetruecolortopalette() error message. (Marc Bennewitz) + - Hash: . Fixed mhash_keygen_s2k() truncating a $length above INT_MAX instead of throwing a ValueError. (Marc Bennewitz) @@ -36,6 +39,8 @@ PHP NEWS IntlCalendar::fromDateTime() fails after adopting a TimeZone. (Ilia Alshanetsky) . Added IntlNumberFormatter::createFromSkeleton() (GH-24165). (David Carlier) + . Fixed IntlDateFormatter parse functions truncating an $offset below + INT_MIN. (Marc Bennewitz) - Lexbor: . Merge patches lexbor/lexbor@8a14bc0 and lexbor/lexbor@f67ce4b, fixing a @@ -62,6 +67,10 @@ PHP NEWS . Fixed mbstring functions emitting surrogates in UTF-8 output and flagging it as valid UTF-8. (Nicolas Grekas) . Fixed bug GH-23958 (truncated encoding names resolving to full names). (Kamil Tekiela) + . Fixed mbstring.regex_retry_limit above UINT_MAX being ignored. + (Marc Bennewitz) + . Fixed negative mbstring.regex_stack_limit and mbstring.regex_retry_limit + on 32bit platforms. (Marc Bennewitz) - MySQLi: . Fix GH-22854: Fixed failed assertion when accessing mysqli property after @@ -107,6 +116,8 @@ PHP NEWS - Phar: . Fixed bug GH-22556 (OOM DoS via oversized ././@LongLink entry in TAR phar). (crystarm) + . Fixed Phar::buildFromIterator() accepting a negative getMTime() on 32bit + platforms. (Marc Bennewitz) - Readline: . Fixed a heap over-read in the interactive shell prompt when cli.prompt is @@ -176,6 +187,10 @@ PHP NEWS . Fix casing of enum cases in UriHostType and UrlHostType to match the RFC and PHP’s naming policy. (timwolla) +- Windows: + . Fixed sapi_windows_cp_set() and sapi_windows_cp_conv() accepting a negative + codepage on 32bit platforms. (Marc Bennewitz) + - XML: . Fixed xml_get_current_byte_index() returning negative values for byte indexes beyond 2 GiB on Windows x64. (Marc Bennewitz) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 4c5d74b49e9c..65e0be7c45b1 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -47,6 +47,13 @@ PHP 8.7 INTERNALS UPGRADE NOTES - The INIT_CLASS_ENTRY_INIT_METHODS() macro, which was previously used as part of handling disabled classes, was removed following the removal of the `disable_classes` INI setting in PHP 8.5. +- Added ZEND_IN_RANGE_OF(x, T) to check whether the value of an integer x is + representable in the integer type T. +- Added ZEND_TYPE_MIN(T) and ZEND_TYPE_MAX(T). +- Deprecated ZEND_LONG_INT_OVFL(), ZEND_LONG_INT_UDFL(), + ZEND_LONG_EXCEEDS_INT(), ZEND_LONG_UINT_OVFL(), ZEND_SIZE_T_INT_OVFL(), + ZEND_SIZE_T_UINT_OVFL() and the *_CAN_OVFL_* flags. Use ZEND_IN_RANGE_OF() + instead. ======================== 2. Build system changes diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 4906c2947cc5..f5764d2a720b 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -87,8 +87,6 @@ using std::atomic_int; #include #endif -#include "zend_range_check.h" - /* GCC x.y.z supplies __GNUC__ = x and __GNUC_MINOR__ = y */ #ifdef __GNUC__ # define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) @@ -947,4 +945,7 @@ static zend_always_inline uint64_t ZEND_BYTES_SWAP64(uint64_t u) # define ZEND_OPCACHE_SHM_REATTACHMENT 1 #endif +/* Last, as its declarations use ZEND_ATTRIBUTE_DEPRECATED. */ +#include "zend_range_check.h" + #endif /* ZEND_PORTABILITY_H */ diff --git a/Zend/zend_range_check.h b/Zend/zend_range_check.h index 8db867434399..811aebc6c998 100644 --- a/Zend/zend_range_check.h +++ b/Zend/zend_range_check.h @@ -12,6 +12,7 @@ | SPDX-License-Identifier: BSD-3-Clause | +----------------------------------------------------------------------+ | Authors: Anatol Belski | + | Marc Bennewitz | +----------------------------------------------------------------------+ */ @@ -20,47 +21,139 @@ #include "zend_long.h" -/* Flag macros for basic range recognition. Notable is that - always sizeof(signed) == sizeof(unsigned), so no need to - overcomplicate things. */ -#if SIZEOF_INT < SIZEOF_ZEND_LONG -# define ZEND_LONG_CAN_OVFL_INT 1 -# define ZEND_LONG_CAN_OVFL_UINT 1 -#endif +/* _ZEND_INT_TYPE_CHECK(T): the integer constant 0, + * or a compile error unless T is an integer type not wider than intmax_t. */ +#ifndef __cplusplus +/* C: a static_assert() cannot appear in an expression itself, + * but it can as a member of a struct of which only the size is taken. + * The "% 1" only compiles for an integer operand. */ +# include -#if SIZEOF_INT < SIZEOF_SIZE_T -/* size_t can always overflow signed int on the same platform. - Furthermore, by the current design, size_t can always - overflow zend_long. */ -# define ZEND_SIZE_T_CAN_OVFL_UINT 1 +# define _ZEND_INT_TYPE_CHECK(T) \ + ((int)(0 * sizeof(struct { \ + static_assert( \ + sizeof((T)0 % 1) && sizeof(T) <= sizeof(intmax_t), \ + "T must be an integer type not wider than intmax_t" \ + ); \ + char zend_dummy; \ + }))) +#else +/* C++ does not allow to define a struct within sizeof(), + * so the static_assert() lives in a class template instead, + * which taking the size of instantiates. */ +extern "C++" { +# include +# include + template struct _zend_int_type_check { + static_assert(std::is_integral::value && sizeof(T) <= sizeof(intmax_t), + "T must be an integer type not wider than intmax_t"); + }; +} + +# define _ZEND_INT_TYPE_CHECK(T) ((int)(0 * sizeof(_zend_int_type_check))) #endif +/* _ZEND_TYPE_IS_SIGNED(T): whether the integer type T is signed, as an integer constant expression. */ +#define _ZEND_TYPE_IS_SIGNED(T) (!((T)-1 > (T)0)) -/* zend_long vs. (unsigned) int checks. */ -#ifdef ZEND_LONG_CAN_OVFL_INT -# define ZEND_LONG_INT_OVFL(zlong) UNEXPECTED((zlong) > (zend_long)INT_MAX) -# define ZEND_LONG_INT_UDFL(zlong) UNEXPECTED((zlong) < (zend_long)INT_MIN) -# define ZEND_LONG_EXCEEDS_INT(zlong) UNEXPECTED(ZEND_LONG_INT_OVFL(zlong) || ZEND_LONG_INT_UDFL(zlong)) -# define ZEND_LONG_UINT_OVFL(zlong) UNEXPECTED((zlong) < 0 || (zlong) > (zend_long)UINT_MAX) -#else -# define ZEND_LONG_INT_OVFL(zl) (0) -# define ZEND_LONG_INT_UDFL(zl) (0) -# define ZEND_LONG_EXCEEDS_INT(zlong) (0) -# define ZEND_LONG_UINT_OVFL(zl) (0) -#endif +/* ZEND_TYPE_MAX(T): the largest value of the integer type T, as an integer constant expression, + * for types without a constant of their own such as time_t. + * T may be any signed or unsigned integer type not wider than intmax_t. */ +#define ZEND_TYPE_MAX(T) (_ZEND_INT_TYPE_CHECK(T) + (_ZEND_TYPE_IS_SIGNED(T) \ + ? (((((T)1 << (sizeof(T) * CHAR_BIT - 2)) - 1) * 2) + 1) \ + : (T)-1 \ +)) + +/* ZEND_TYPE_MIN(T): the smallest value of the integer type T, as an integer constant expression. + * T may be any signed or unsigned integer type not wider than intmax_t. */ +#define ZEND_TYPE_MIN(T) (_ZEND_TYPE_IS_SIGNED(T) ? -ZEND_TYPE_MAX(T) - 1 : (T)0) + +/* ZEND_IN_RANGE_OF */ +#ifndef __cplusplus +/* C: _Generic dispatches on the promoted type of x, without evaluating it, + * to a comparison done in intmax_t for a signed x or in uintmax_t for an unsigned one, + * against ZEND_TYPE_MIN(T) and ZEND_TYPE_MAX(T). */ +static inline bool _zend_in_range_signed(intmax_t v, intmax_t min, uintmax_t max) +{ + if (max <= INTMAX_MAX) { + return v >= min && v <= (intmax_t)max; + } + return v >= 0; /* T is a uintmax_t-wide unsigned type */ +} -/* size_t vs (unsigned) int checks. */ -#define ZEND_SIZE_T_INT_OVFL(size) UNEXPECTED((size) > (size_t)INT_MAX) -#ifdef ZEND_SIZE_T_CAN_OVFL_UINT -# define ZEND_SIZE_T_UINT_OVFL(size) UNEXPECTED((size) > (size_t)UINT_MAX) +static inline bool _zend_in_range_unsigned(uintmax_t v, uintmax_t max) +{ + return v <= max; +} + +# define _ZEND_IN_RANGE_SIGNED(x, T) _zend_in_range_signed((x), ZEND_TYPE_MIN(T), ZEND_TYPE_MAX(T)) +# define _ZEND_IN_RANGE_UNSIGNED(x, T) _zend_in_range_unsigned((x), ZEND_TYPE_MAX(T)) + +/* ZEND_IN_RANGE_OF(x, T): whether the value of the integer expression x is representable in the integer type T. + * x and T may be any signed or unsigned integer types not wider than intmax_t. + * x is evaluated exactly once. */ +# define ZEND_IN_RANGE_OF(x, T) EXPECTED(_Generic((x) + 0, \ + int: _ZEND_IN_RANGE_SIGNED(x, T), \ + long: _ZEND_IN_RANGE_SIGNED(x, T), \ + long long: _ZEND_IN_RANGE_SIGNED(x, T), \ + unsigned int: _ZEND_IN_RANGE_UNSIGNED(x, T), \ + unsigned long: _ZEND_IN_RANGE_UNSIGNED(x, T), \ + unsigned long long: _ZEND_IN_RANGE_UNSIGNED(x, T) \ +)) #else -# define ZEND_SIZE_T_UINT_OVFL(size) (0) +/* C++ has no _Generic (g++ and MSVC reject it). + * A function template deduces the type of x instead. + * The unary + applies the integer promotions, as (x) + 0 does for C. */ +extern "C++" { + template + constexpr bool _zend_in_range_of(X x) { + static_assert(std::is_integral::value && sizeof(X) <= sizeof(intmax_t), "x must be an integer not wider than intmax_t"); + + return std::is_signed::value + ? (intmax_t)x >= (intmax_t)ZEND_TYPE_MIN(T) + && ((uintmax_t)ZEND_TYPE_MAX(T) > (uintmax_t)INTMAX_MAX + || (intmax_t)x <= (intmax_t)ZEND_TYPE_MAX(T)) + : (uintmax_t)x <= (uintmax_t)ZEND_TYPE_MAX(T); + } +} + +/* ZEND_IN_RANGE_OF(x, T): whether the value of the integer expression x is representable in the integer type T. + * x and T may be any signed or unsigned integer types not wider than intmax_t. + * x is evaluated exactly once. */ +# define ZEND_IN_RANGE_OF(x, T) EXPECTED(_zend_in_range_of(+(x))) #endif /* Comparison zend_long vs size_t */ -#define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) > (size_t)(zlong)) +#define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) > (size_t)(zlong)) #define ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) >= (size_t)(zlong)) -#define ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) ((zlong) >= 0 && (size) < (size_t)(zlong)) +#define ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) ((zlong) >= 0 && (size) < (size_t)(zlong)) #define ZEND_SIZE_T_LTE_ZEND_LONG(size, zlong) ((zlong) >= 0 && (size) <= (size_t)(zlong)) +/* -- DEPRECATED -- */ + +/* The zend_long and size_t vs. (unsigned) int checks below are deprecated, use ZEND_IN_RANGE_OF() instead. */ +static inline ZEND_ATTRIBUTE_DEPRECATED void _zend_deprecated_use_ZEND_IN_RANGE_OF_instead(void) {} + +#if SIZEOF_INT < SIZEOF_ZEND_LONG +# define ZEND_LONG_CAN_OVFL_INT 1 /* Deprecated */ +# define ZEND_LONG_CAN_OVFL_UINT 1 /* Deprecated */ +# define ZEND_LONG_INT_OVFL(zlong) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), UNEXPECTED((zlong) > (zend_long)INT_MAX)) +# define ZEND_LONG_INT_UDFL(zlong) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), UNEXPECTED((zlong) < (zend_long)INT_MIN)) +# define ZEND_LONG_EXCEEDS_INT(zlong) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), UNEXPECTED((zlong) > (zend_long)INT_MAX || (zlong) < (zend_long)INT_MIN)) +# define ZEND_LONG_UINT_OVFL(zlong) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), UNEXPECTED((zlong) < 0 || (zlong) > (zend_long)UINT_MAX)) +#else +# define ZEND_LONG_INT_OVFL(zl) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), 0) +# define ZEND_LONG_INT_UDFL(zl) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), 0) +# define ZEND_LONG_EXCEEDS_INT(zlong) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), 0) +# define ZEND_LONG_UINT_OVFL(zl) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), 0) +#endif + +#define ZEND_SIZE_T_INT_OVFL(size) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), UNEXPECTED((size) > (size_t)INT_MAX)) +#if SIZEOF_INT < SIZEOF_SIZE_T +# define ZEND_SIZE_T_CAN_OVFL_UINT 1 /* Deprecated */ +# define ZEND_SIZE_T_UINT_OVFL(size) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), UNEXPECTED((size) > (size_t)UINT_MAX)) +#else +# define ZEND_SIZE_T_UINT_OVFL(size) (_zend_deprecated_use_ZEND_IN_RANGE_OF_instead(), 0) +#endif + #endif /* ZEND_RANGE_CHECK_H */ diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index a7f8bc143a48..11d7a1c6ccd0 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -157,7 +157,7 @@ static zend_always_inline zend_result bcmath_check_scale(zend_long scale, uint32 static zend_result bcmath_check_precision(zend_long precision, uint32_t arg_num) { - if (ZEND_LONG_INT_OVFL(precision)) { + if (precision > 0 && !ZEND_IN_RANGE_OF(precision, int)) { zend_argument_value_error(arg_num, "must be between " ZEND_LONG_FMT " and %d", (zend_long) ZEND_LONG_MIN, INT_MAX); return FAILURE; diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c index 14daf3a5e678..d822eab49dca 100644 --- a/ext/calendar/calendar.c +++ b/ext/calendar/calendar.c @@ -255,7 +255,7 @@ PHP_FUNCTION(cal_to_jd) RETURN_THROWS(); } - if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(day))) { + if (!ZEND_IN_RANGE_OF(day, int32_t)) { zend_argument_value_error(3, "must be between %d and %d", INT32_MIN, INT32_MAX); RETURN_THROWS(); } @@ -516,7 +516,7 @@ PHP_FUNCTION(jewishtojd) RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(year)) { + if (!ZEND_IN_RANGE_OF(year, int)) { zend_argument_value_error(3, "must be between %d and %d", INT_MIN, INT_MAX); RETURN_THROWS(); } diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 24e6322e4daf..222fb959f410 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -3058,7 +3058,7 @@ PHP_FUNCTION(curl_escape) ch = Z_CURL_P(zid); - if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(str), int)) { RETURN_FALSE; } @@ -3087,7 +3087,7 @@ PHP_FUNCTION(curl_unescape) ch = Z_CURL_P(zid); - if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(str), int)) { RETURN_FALSE; } diff --git a/ext/dba/dba.c b/ext/dba/dba.c index af9c62d2cfd6..65cc231c0d79 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -1057,7 +1057,7 @@ PHP_FUNCTION(dba_fetch) ZEND_PARSE_PARAMETERS_END(); } - if (ZEND_LONG_EXCEEDS_INT(skip)) { + if (!ZEND_IN_RANGE_OF(skip, int)) { zend_argument_value_error(3, "must be between %d and %d", INT_MIN, INT_MAX); RETURN_THROWS(); } diff --git a/ext/dom/characterdata.c b/ext/dom/characterdata.c index 80dce80cf2f0..9677a71bac1b 100644 --- a/ext/dom/characterdata.c +++ b/ext/dom/characterdata.c @@ -119,7 +119,7 @@ PHP_METHOD(DOMCharacterData, substringData) const xmlChar *cur = php_dom_get_content_or_empty(node); length = xmlUTF8Strlen(cur); - if (ZEND_LONG_INT_OVFL(offset_input) || ZEND_LONG_INT_OVFL(count_input)) { + if ((offset_input > 0 && !ZEND_IN_RANGE_OF(offset_input, int)) || (count_input > 0 && !ZEND_IN_RANGE_OF(count_input, int))) { php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document)); RETURN_FALSE; } @@ -206,7 +206,7 @@ static void dom_character_data_insert_data(INTERNAL_FUNCTION_PARAMETERS, bool re length = xmlUTF8Strlen(cur); - if (ZEND_LONG_INT_OVFL(offset_input)) { + if (offset_input > 0 && !ZEND_IN_RANGE_OF(offset_input, int)) { php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document)); RETURN_FALSE; } @@ -271,7 +271,7 @@ static void dom_character_data_delete_data(INTERNAL_FUNCTION_PARAMETERS, bool re length = xmlUTF8Strlen(cur); - if (offset < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count_input) || offset > length) { + if (offset < 0 || !ZEND_IN_RANGE_OF(offset, int) || (count_input > 0 && !ZEND_IN_RANGE_OF(count_input, int)) || offset > length) { php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document)); RETURN_FALSE; } @@ -341,7 +341,7 @@ static void dom_character_data_replace_data(INTERNAL_FUNCTION_PARAMETERS, bool r length = xmlUTF8Strlen(cur); - if (offset < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count_input) || offset > length) { + if (offset < 0 || !ZEND_IN_RANGE_OF(offset, int) || (count_input > 0 && !ZEND_IN_RANGE_OF(count_input, int)) || offset > length) { php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document)); RETURN_FALSE; } diff --git a/ext/dom/document.c b/ext/dom/document.c index 605c4dae782b..27325957964d 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1532,11 +1532,11 @@ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - if (ZEND_SIZE_T_INT_OVFL(source_len)) { + if (!ZEND_IN_RANGE_OF(source_len, int)) { php_error_docref(NULL, E_WARNING, "Input string is too long"); RETURN_FALSE; } - if (ZEND_LONG_EXCEEDS_INT(options)) { + if (!ZEND_IN_RANGE_OF(options, int)) { php_error_docref(NULL, E_WARNING, "Invalid options"); RETURN_FALSE; } @@ -1794,7 +1794,7 @@ PHP_METHOD(DOMDocument, xinclude) RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(flags)) { + if (!ZEND_IN_RANGE_OF(flags, int)) { php_error_docref(NULL, E_WARNING, "Invalid flags"); RETURN_FALSE; } @@ -1820,7 +1820,7 @@ PHP_METHOD(Dom_XMLDocument, xinclude) RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(flags)) { + if (!ZEND_IN_RANGE_OF(flags, int)) { zend_argument_value_error(1, "is too large"); RETURN_THROWS(); } @@ -2105,7 +2105,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(options)) { + if (!ZEND_IN_RANGE_OF(options, int)) { php_error_docref(NULL, E_WARNING, "Invalid options"); RETURN_FALSE; } @@ -2117,7 +2117,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ } ctxt = htmlCreateFileParserCtxt(source, NULL); } else { - if (ZEND_SIZE_T_INT_OVFL(source_len)) { + if (!ZEND_IN_RANGE_OF(source_len, int)) { php_error_docref(NULL, E_WARNING, "Input string is too long"); RETURN_FALSE; } diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index 7566dd8b61a8..00dcc2464c54 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -86,7 +86,7 @@ xmlNodePtr php_dom_libxml_hash_iter(xmlHashTable *ht, zend_long index) if (index < 0) { return NULL; } - if (UNEXPECTED(ZEND_LONG_INT_OVFL(index))) { + if (!ZEND_IN_RANGE_OF(index, int)) { zend_value_error("must be between 0 and %d", INT_MAX); return NULL; } diff --git a/ext/dom/element.c b/ext/dom/element.c index 5fcffaf42055..5c27fcea3c49 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -1745,7 +1745,7 @@ static void dom_element_insert_adjacent_text(INTERNAL_FUNCTION_PARAMETERS, zend_ DOM_GET_THIS_OBJ(thisp, id, xmlNodePtr, this_intern); - if (UNEXPECTED(ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(data)))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(data), int)) { zend_argument_value_error(2, "is too long"); RETURN_THROWS(); } diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c index d665bbbaebdc..88e5220a7fbe 100644 --- a/ext/dom/namednodemap.c +++ b/ext/dom/namednodemap.c @@ -74,7 +74,7 @@ PHP_METHOD(DOMNamedNodeMap, item) ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(index) ZEND_PARSE_PARAMETERS_END(); - if (index < 0 || ZEND_LONG_INT_OVFL(index)) { + if (index < 0 || !ZEND_IN_RANGE_OF(index, int)) { zend_argument_value_error(1, "must be between 0 and %d", INT_MAX); RETURN_THROWS(); } diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 845507924c1e..43e127a7d869 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -2413,7 +2413,7 @@ static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int t } /* see PHP_METHOD(DOMNamedNodeMap, item) */ - if (UNEXPECTED(lval < 0 || ZEND_LONG_INT_OVFL(lval))) { + if (UNEXPECTED(lval < 0 || !ZEND_IN_RANGE_OF(lval, int))) { zend_value_error("must be between 0 and %d", INT_MAX); return NULL; } diff --git a/ext/dom/text.c b/ext/dom/text.c index 357ff1969490..714783085617 100644 --- a/ext/dom/text.c +++ b/ext/dom/text.c @@ -115,7 +115,7 @@ PHP_METHOD(DOMText, splitText) const xmlChar *cur = php_dom_get_content_or_empty(node); length = xmlUTF8Strlen(cur); - if (ZEND_LONG_INT_OVFL(offset) || (int)offset > length) { + if (!ZEND_IN_RANGE_OF(offset, int) || (int)offset > length) { if (php_dom_follow_spec_intern(intern)) { php_dom_throw_error(INDEX_SIZE_ERR, /* strict */ true); } diff --git a/ext/dom/xml_document.c b/ext/dom/xml_document.c index 707356227afe..f82e689720c5 100644 --- a/ext/dom/xml_document.c +++ b/ext/dom/xml_document.c @@ -149,7 +149,7 @@ static void load_from_helper(INTERNAL_FUNCTION_PARAMETERS, int mode) RETURN_THROWS(); } - if (ZEND_SIZE_T_INT_OVFL(source_len)) { + if (!ZEND_IN_RANGE_OF(source_len, int)) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 8d65d12aef65..a5101264315a 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -647,7 +647,7 @@ PHP_FUNCTION(imagesetstyle) zend_argument_type_error(2, "must only have elements of type int, %s given", zend_zval_type_name(item)); RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(tmp)) { + if (!ZEND_IN_RANGE_OF(tmp, int)) { efree(stylearr); zend_argument_value_error(2, "elements must be between %d and %d", INT_MIN, INT_MAX); RETURN_THROWS(); @@ -726,8 +726,8 @@ PHP_FUNCTION(imagetruecolortopalette) im = php_gd_libgdimageptr_from_zval_p(IM); - if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) { - zend_argument_value_error(3, "must be greater than 0 and less than %d", INT_MAX); + if (ncolors <= 0 || !ZEND_IN_RANGE_OF(ncolors, int)) { + zend_argument_value_error(3, "must be between 1 and %d", INT_MAX); RETURN_THROWS(); } @@ -831,7 +831,7 @@ PHP_FUNCTION(imagefilledellipse) Z_PARAM_LONG(color) ZEND_PARSE_PARAMETERS_END(); - if (w < 0 || ZEND_LONG_INT_OVFL(w)) { + if (w < 0 || !ZEND_IN_RANGE_OF(w, int)) { zend_argument_value_error(4, "must be between 0 and %d", INT_MAX); RETURN_THROWS(); } @@ -3647,12 +3647,12 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS) Z_PARAM_ARRAY(hash_colors) ZEND_PARSE_PARAMETERS_END(); - if (scatter_sub < 0 || ZEND_SIZE_T_INT_OVFL(scatter_sub)) { + if (scatter_sub < 0 || !ZEND_IN_RANGE_OF(scatter_sub, int)) { zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); RETURN_THROWS(); } - if (scatter_plus < 0 || ZEND_SIZE_T_INT_OVFL(scatter_plus)) { + if (scatter_plus < 0 || !ZEND_IN_RANGE_OF(scatter_plus, int)) { zend_argument_value_error(4, "must be between 0 and %d", INT_MAX); RETURN_THROWS(); } @@ -3680,7 +3680,7 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS) zend_argument_type_error(5, "must be of type int, %s given", zend_zval_type_name(color)); RETURN_THROWS(); } - if (tmp < 0 || ZEND_LONG_INT_OVFL(tmp)) { + if (tmp < 0 || !ZEND_IN_RANGE_OF(tmp, int)) { efree(colors); zend_argument_value_error(5, "value must be between 0 and %d", INT_MAX); RETURN_THROWS(); @@ -3862,7 +3862,7 @@ static bool php_gd_zval_try_get_c_int(zval *tmp, const char *field, int *res) { zend_argument_type_error(2, "\"%s\" key must be of type int, %s given", field, zend_zval_type_name(tmp)); return false; } - if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(r))) { + if (!ZEND_IN_RANGE_OF(r, int)) { zend_argument_value_error(2, "\"%s\" key must be between %d and %d", field, INT_MIN, INT_MAX); return false; } @@ -4058,12 +4058,12 @@ PHP_FUNCTION(imagescale) } } - if (tmp_w <= 0 || ZEND_SIZE_T_INT_OVFL(tmp_w)) { + if (tmp_w <= 0 || !ZEND_IN_RANGE_OF(tmp_w, int)) { zend_argument_value_error(2, "must be between 1 and %d", INT_MAX); RETURN_THROWS(); } - if (tmp_h <= 0 || ZEND_SIZE_T_INT_OVFL(tmp_h)) { + if (tmp_h <= 0 || !ZEND_IN_RANGE_OF(tmp_h, int)) { zend_argument_value_error(3, "must be between 1 and %d", INT_MAX); RETURN_THROWS(); } @@ -4400,25 +4400,25 @@ PHP_FUNCTION(imageresolution) im = php_gd_libgdimageptr_from_zval_p(IM); if (!res_x_is_null && !res_y_is_null) { - if (res_x < 0 || ZEND_SIZE_T_UINT_OVFL(res_x)) { + if (!ZEND_IN_RANGE_OF(res_x, unsigned int)) { zend_argument_value_error(2, "must be between 0 and %u", UINT_MAX); RETURN_THROWS(); } - if (res_y < 0 || ZEND_SIZE_T_UINT_OVFL(res_y)) { + if (!ZEND_IN_RANGE_OF(res_y, unsigned int)) { zend_argument_value_error(3, "must be between 0 and %u", UINT_MAX); RETURN_THROWS(); } gdImageSetResolution(im, res_x, res_y); RETURN_TRUE; } else if (!res_x_is_null && res_y_is_null) { - if (res_x < 0 || ZEND_SIZE_T_UINT_OVFL(res_x)) { + if (!ZEND_IN_RANGE_OF(res_x, unsigned int)) { zend_argument_value_error(2, "must be between 0 and %u", UINT_MAX); RETURN_THROWS(); } gdImageSetResolution(im, res_x, res_x); RETURN_TRUE; } else if (res_x_is_null && !res_y_is_null) { - if (res_y < 0 || ZEND_SIZE_T_UINT_OVFL(res_y)) { + if (!ZEND_IN_RANGE_OF(res_y, unsigned int)) { zend_argument_value_error(3, "must be between 0 and %u", UINT_MAX); RETURN_THROWS(); } diff --git a/ext/gd/tests/bug72697.phpt b/ext/gd/tests/bug72697.phpt index a7ab6114db34..f8c21406ba05 100644 --- a/ext/gd/tests/bug72697.phpt +++ b/ext/gd/tests/bug72697.phpt @@ -20,5 +20,5 @@ trycatch_dump( ?> DONE --EXPECT-- -!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be greater than 0 and less than 2147483647 +!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be between 1 and 2147483647 DONE diff --git a/ext/gd/tests/imagetruecolortopalette_error3.phpt b/ext/gd/tests/imagetruecolortopalette_error3.phpt index 0cbeca7e6d8b..d7726562572c 100644 --- a/ext/gd/tests/imagetruecolortopalette_error3.phpt +++ b/ext/gd/tests/imagetruecolortopalette_error3.phpt @@ -20,4 +20,4 @@ trycatch_dump( ?> --EXPECT-- -!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be greater than 0 and less than 2147483647 +!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be between 1 and 2147483647 diff --git a/ext/gd/tests/imagetruecolortopalette_error4.phpt b/ext/gd/tests/imagetruecolortopalette_error4.phpt index d1e8cffc39d3..36b6d91b854b 100644 --- a/ext/gd/tests/imagetruecolortopalette_error4.phpt +++ b/ext/gd/tests/imagetruecolortopalette_error4.phpt @@ -21,5 +21,5 @@ trycatch_dump( ?> --EXPECT-- -!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be greater than 0 and less than 2147483647 -!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be greater than 0 and less than 2147483647 +!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be between 1 and 2147483647 +!! [ValueError] imagetruecolortopalette(): Argument #3 ($num_colors) must be between 1 and 2147483647 diff --git a/ext/hash/hash.c b/ext/hash/hash.c index a950d824700f..281ae6acea23 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -1298,7 +1298,7 @@ PHP_FUNCTION(mhash_keygen_s2k) RETURN_THROWS(); } - if (ZEND_LONG_INT_OVFL(l_bytes)) { + if (!ZEND_IN_RANGE_OF(l_bytes, int)) { zend_argument_value_error(4, "must be less than or equal to %d", INT_MAX); RETURN_THROWS(); } diff --git a/ext/intl/dateformat/dateformat_parse.cpp b/ext/intl/dateformat/dateformat_parse.cpp index 4598a9e93c1f..28b76ea5cbf4 100644 --- a/ext/intl/dateformat/dateformat_parse.cpp +++ b/ext/intl/dateformat/dateformat_parse.cpp @@ -172,7 +172,7 @@ U_CFUNC PHP_FUNCTION(datefmt_parse) zend_argument_type_error(hasThis() ? 2 : 3, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); RETURN_THROWS(); } - if (ZEND_LONG_INT_OVFL(long_parse_pos)) { + if (!ZEND_IN_RANGE_OF(long_parse_pos, int32_t)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range."); RETURN_FALSE; @@ -215,7 +215,7 @@ U_CFUNC PHP_METHOD(IntlDateFormatter, parseToCalendar) zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); RETURN_THROWS(); } - if (ZEND_LONG_INT_OVFL(long_parse_pos)) { + if (!ZEND_IN_RANGE_OF(long_parse_pos, int32_t)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range."); RETURN_FALSE; @@ -257,7 +257,7 @@ U_CFUNC PHP_FUNCTION(datefmt_localtime) zend_argument_type_error(hasThis() ? 2 : 3, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); RETURN_THROWS(); } - if (ZEND_LONG_INT_OVFL(long_parse_pos)) { + if (!ZEND_IN_RANGE_OF(long_parse_pos, int32_t)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range."); RETURN_FALSE; diff --git a/ext/intl/tests/dateformat_parse_offset_out_of_range.phpt b/ext/intl/tests/dateformat_parse_offset_out_of_range.phpt new file mode 100644 index 000000000000..bddc678ac947 --- /dev/null +++ b/ext/intl/tests/dateformat_parse_offset_out_of_range.phpt @@ -0,0 +1,33 @@ +--TEST-- +IntlDateFormatter parse functions reject an offset below INT_MIN +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +parseToCalendar('12026', $offset), $offset, intl_get_error_message()); + +$offset = -4294967295; +var_dump(datefmt_localtime($fmt, '12026', $offset), $offset, intl_get_error_message()); +?> +--EXPECT-- +bool(false) +int(-4294967295) +string(78) "datefmt_parse(): String index is out of valid range.: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +int(-4294967295) +string(99) "IntlDateFormatter::parseToCalendar(): String index is out of valid range.: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +int(-4294967295) +string(82) "datefmt_localtime(): String index is out of valid range.: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index 89d725217b90..9cce645622fb 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -133,7 +133,7 @@ PHP_INTL_FUNCTION_WITH_ERROR_RESET(intltz_create_enumeration) } else if (timezone != nullptr) { se = TimeZone::createEnumeration(ZSTR_VAL(timezone)); } else { - if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(timezone_shift))) { + if (!ZEND_IN_RANGE_OF(timezone_shift, int32_t)) { zend_argument_value_error(1, "must be between %d and %d", INT32_MIN, INT32_MAX); RETURN_THROWS(); } @@ -196,7 +196,7 @@ PHP_INTL_FUNCTION_WITH_ERROR_RESET(intltz_create_time_zone_id_enumeration) } if (!arg3isnull) { - if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(offset_arg))) { + if (!ZEND_IN_RANGE_OF(offset_arg, int32_t)) { zend_argument_value_error(3, "must be between %d and %d", INT32_MIN, INT32_MAX); RETURN_THROWS(); } @@ -294,7 +294,7 @@ PHP_INTL_FUNCTION_WITH_ERROR_RESET(intltz_get_equivalent_id) Z_PARAM_LONG(index) ZEND_PARSE_PARAMETERS_END(); - if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(index))) { + if (!ZEND_IN_RANGE_OF(index, int32_t)) { zend_argument_value_error(2, "must be between %d and %d", INT32_MIN, INT32_MAX); RETURN_THROWS(); } diff --git a/ext/intl/uchar/uchar.cpp b/ext/intl/uchar/uchar.cpp index 3b3edfca49a9..9bf6d25e5a82 100644 --- a/ext/intl/uchar/uchar.cpp +++ b/ext/intl/uchar/uchar.cpp @@ -35,7 +35,7 @@ static inline int convert_cp(UChar32* pcp, const zend_string *string_codepoint, int32_t i = 0; const size_t string_codepoint_length = ZSTR_LEN(string_codepoint); - if (UNEXPECTED(ZEND_SIZE_T_INT_OVFL(string_codepoint_length))) { + if (!ZEND_IN_RANGE_OF(string_codepoint_length, int32_t)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "Input string is too long."); return FAILURE; diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 3e03df4c3375..e83906c8176f 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -3215,7 +3215,7 @@ PHP_FUNCTION(ldap_set_option) RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(lval)) { + if (!ZEND_IN_RANGE_OF(lval, int)) { zend_argument_value_error(3, "is too large"); RETURN_THROWS(); } diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c index df1553b54b69..101c10ff9f33 100644 --- a/ext/mbstring/php_mbregex.c +++ b/ext/mbstring/php_mbregex.c @@ -881,11 +881,11 @@ static int _php_mb_onig_search(regex_t* reg, const OnigUChar* str, const OnigUCh OnigMatchParam *mp = onig_new_match_param(); int err; onig_initialize_match_param(mp); - if (!ZEND_LONG_UINT_OVFL(MBSTRG(regex_stack_limit))) { + if (ZEND_IN_RANGE_OF(MBSTRG(regex_stack_limit), unsigned int)) { onig_set_match_stack_limit_size_of_match_param(mp, (unsigned int)MBSTRG(regex_stack_limit)); } - if (!ZEND_LONG_UINT_OVFL(MBSTRG(regex_retry_limit))) { - onig_set_retry_limit_in_match_of_match_param(mp, (unsigned int)MBSTRG(regex_retry_limit)); + if (ZEND_IN_RANGE_OF(MBSTRG(regex_retry_limit), unsigned long)) { + onig_set_retry_limit_in_match_of_match_param(mp, (unsigned long)MBSTRG(regex_retry_limit)); } /* search */ err = onig_search_with_param(reg, str, end, start, range, region, option, mp); @@ -1310,11 +1310,11 @@ PHP_FUNCTION(mb_ereg_match) mp = onig_new_match_param(); onig_initialize_match_param(mp); - if (MBSTRG(regex_stack_limit) > 0 && MBSTRG(regex_stack_limit) < UINT_MAX) { + if (MBSTRG(regex_stack_limit) > 0 && ZEND_IN_RANGE_OF(MBSTRG(regex_stack_limit), unsigned int)) { onig_set_match_stack_limit_size_of_match_param(mp, (unsigned int)MBSTRG(regex_stack_limit)); } - if (MBSTRG(regex_retry_limit) > 0 && MBSTRG(regex_retry_limit) < UINT_MAX) { - onig_set_retry_limit_in_match_of_match_param(mp, (unsigned int)MBSTRG(regex_retry_limit)); + if (MBSTRG(regex_retry_limit) > 0 && ZEND_IN_RANGE_OF(MBSTRG(regex_retry_limit), unsigned long)) { + onig_set_retry_limit_in_match_of_match_param(mp, (unsigned long)MBSTRG(regex_retry_limit)); } /* match */ err = onig_match_with_param(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, NULL, 0, mp); diff --git a/ext/mbstring/tests/retry_limit_above_uint_max.phpt b/ext/mbstring/tests/retry_limit_above_uint_max.phpt new file mode 100644 index 000000000000..371699d78a3b --- /dev/null +++ b/ext/mbstring/tests/retry_limit_above_uint_max.phpt @@ -0,0 +1,32 @@ +--TEST-- +Oniguruma retry limit beyond the range of an unsigned int +--EXTENSIONS-- +mbstring +--SKIPIF-- += 6.9.3'); +} +if (PHP_INT_SIZE <= 4) die('skip a limit beyond an unsigned int needs a wider PHP integer'); +if (PHP_OS_FAMILY === 'Windows') die('skip an unsigned long is 4 bytes wide on Windows'); +if (getenv('SKIP_SLOW_TESTS')) die('skip slow test'); +?> +--INI-- +mbstring.regex_retry_limit=4294967296 +--FILE-- + +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +bool(true) + +Deprecated: Function mb_ereg_match() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +bool(true) diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c index 995d836deead..6274b47f6afe 100644 --- a/ext/openssl/openssl_backend_common.c +++ b/ext/openssl/openssl_backend_common.c @@ -2116,7 +2116,7 @@ PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_le zend_argument_value_error(1, "must be greater than 0"); return NULL; } - if (ZEND_LONG_INT_OVFL(buffer_length)) { + if (!ZEND_IN_RANGE_OF(buffer_length, int)) { zend_argument_value_error(1, "must be less than or equal to %d", INT_MAX); return NULL; } diff --git a/ext/openssl/php_openssl_backend.h b/ext/openssl/php_openssl_backend.h index 364f27eec23e..1e43fd79c6b7 100644 --- a/ext/openssl/php_openssl_backend.h +++ b/ext/openssl/php_openssl_backend.h @@ -63,17 +63,17 @@ typedef X509_EXTENSION PHP_OPENSSL_X509_EXTENSION; } while(0) /* check if size_t can be safely casted to int */ #define PHP_OPENSSL_CHECK_SIZE_T_TO_INT(_var, _name, _arg_num) \ - PHP_OPENSSL_CHECK_NUMBER_CONVERSION(ZEND_SIZE_T_INT_OVFL(_var), _name, _arg_num) + PHP_OPENSSL_CHECK_NUMBER_CONVERSION(!ZEND_IN_RANGE_OF((size_t)(_var), int), _name, _arg_num) #define PHP_OPENSSL_CHECK_SIZE_T_TO_INT_NULL_RETURN(_var, _name) \ - PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(ZEND_SIZE_T_INT_OVFL(_var), _name) + PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(!ZEND_IN_RANGE_OF((size_t)(_var), int), _name) /* check if size_t can be safely casted to unsigned int */ #define PHP_OPENSSL_CHECK_SIZE_T_TO_UINT(_var, _name, _arg_num) \ - PHP_OPENSSL_CHECK_NUMBER_CONVERSION(ZEND_SIZE_T_UINT_OVFL(_var), _name, _arg_num) + PHP_OPENSSL_CHECK_NUMBER_CONVERSION(!ZEND_IN_RANGE_OF((size_t)(_var), unsigned int), _name, _arg_num) /* check if long can be safely casted to int */ #define PHP_OPENSSL_CHECK_LONG_TO_INT(_var, _name, _arg_num) \ - PHP_OPENSSL_CHECK_NUMBER_CONVERSION(ZEND_LONG_EXCEEDS_INT(_var), _name, _arg_num) + PHP_OPENSSL_CHECK_NUMBER_CONVERSION(!ZEND_IN_RANGE_OF(_var, int), _name, _arg_num) #define PHP_OPENSSL_CHECK_LONG_TO_INT_NULL_RETURN(_var, _name) \ - PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(ZEND_LONG_EXCEEDS_INT(_var), _name) + PHP_OPENSSL_CHECK_NUMBER_CONVERSION_NULL_RETURN(!ZEND_IN_RANGE_OF(_var, int), _name) /* FIXME: Use the openssl constants instead of * enum. It is now impossible to match real values diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 548a47c3ee83..3b52770a8b3e 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -274,7 +274,7 @@ static void pgsql_handle_closer(pdo_dbh_t *dbh) /* {{{ */ #ifdef HAVE_PG_SET_CHUNKED_ROWS_SIZE static bool pdo_pgsql_check_chunk_size(zend_long size) { - if (size < 0 || ZEND_LONG_EXCEEDS_INT(size)) { + if (size < 0 || !ZEND_IN_RANGE_OF(size, int)) { zend_value_error("Pdo\\Pgsql::ATTR_CHUNK_SIZE must be between 0 and %d", INT_MAX); return false; } diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index c45ae86a3fa5..67112fa79e3d 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1360,7 +1360,7 @@ static phar_entry_data *phar_build_entry_data(zend_string *fname, char *path, si } /* Sanity check bounds. See GH-14141. */ - if (ZEND_LONG_UINT_OVFL(Z_LVAL(rv))) { + if (!ZEND_IN_RANGE_OF(Z_LVAL(rv), uint32_t)) { *error = estrdup("timestamp is limited to 32-bit"); return NULL; } diff --git a/ext/phar/tests/buildFromIterator_user_overrides/getMTime_negative.phpt b/ext/phar/tests/buildFromIterator_user_overrides/getMTime_negative.phpt new file mode 100644 index 000000000000..315705781647 --- /dev/null +++ b/ext/phar/tests/buildFromIterator_user_overrides/getMTime_negative.phpt @@ -0,0 +1,53 @@ +--TEST-- +buildFromIterator with user overrides - negative getMTime() +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +phar.require_hash=0 +--FILE-- +getPathname()); + } +} + +$workdir = __DIR__.'/getMTime_negative'; +mkdir($workdir . '/content', recursive: true); +file_put_contents($workdir . '/content/hello.txt', "Hello world."); + +try { + $phar = new \Phar($workdir . "/test.phar"); + $phar->startBuffering(); + $phar->buildFromIterator( + new RecursiveIteratorIterator( + new MyIterator($workdir . '/content', FilesystemIterator::SKIP_DOTS) + ), + $workdir + ); + $phar->stopBuffering(); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +?> +--CLEAN-- + +--EXPECTF-- +[MTime] +BadMethodCallException: Entry content%chello.txt cannot be created: timestamp is limited to 32-bit diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 0e02a843e95a..dea4ccbe1f06 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2249,7 +2249,7 @@ PHP_FUNCTION(simplexml_load_file) RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(options)) { + if (!ZEND_IN_RANGE_OF(options, int)) { zend_argument_value_error(3, "is too large"); RETURN_THROWS(); } @@ -2295,15 +2295,15 @@ PHP_FUNCTION(simplexml_load_string) RETURN_THROWS(); } - if (ZEND_SIZE_T_INT_OVFL(data_len)) { + if (!ZEND_IN_RANGE_OF(data_len, int)) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } - if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(ns))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(ns), int)) { zend_argument_value_error(4, "is too long"); RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(options)) { + if (!ZEND_IN_RANGE_OF(options, int)) { zend_argument_value_error(3, "is too large"); RETURN_THROWS(); } @@ -2346,15 +2346,15 @@ PHP_METHOD(SimpleXMLElement, __construct) RETURN_THROWS(); } - if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(data))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(data), int)) { zend_argument_error(zend_ce_exception, 1, "is too long"); RETURN_THROWS(); } - if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(ns))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(ns), int)) { zend_argument_error(zend_ce_exception, 4, "is too long"); RETURN_THROWS(); } - if (ZEND_LONG_EXCEEDS_INT(options)) { + if (!ZEND_IN_RANGE_OF(options, int)) { zend_argument_error(zend_ce_exception, 2, "is invalid"); RETURN_THROWS(); } diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c index 195c5abe45eb..5281670fa035 100644 --- a/ext/soap/php_schema.c +++ b/ext/soap/php_schema.c @@ -68,7 +68,7 @@ static int schema_parse_int(const xmlChar *value, const char *name, bool allow_n } } - if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(lval) || (!allow_negative && lval < 0))) { + if (UNEXPECTED(!ZEND_IN_RANGE_OF(lval, int) || (!allow_negative && lval < 0))) { soap_error1(E_ERROR, "Parsing Schema: %s value is out of range", name); } diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 8d5fc9a694d2..be040fb41c55 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -1407,7 +1407,7 @@ PHP_METHOD(SoapServer, handle) FETCH_THIS_SERVICE(service); SOAP_GLOBAL(soap_version) = service->version; - if (arg && ZEND_SIZE_T_INT_OVFL(arg_len)) { + if (arg && !ZEND_IN_RANGE_OF(arg_len, int)) { soap_server_fault_en("Server", "Input string is too long"); SOAP_SERVER_END_CODE(); return; diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 1d4214ea9bfc..b4c289524b34 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -1305,7 +1305,7 @@ PHP_FUNCTION(socket_strerror) Z_PARAM_LONG(arg1) ZEND_PARSE_PARAMETERS_END(); - if (ZEND_LONG_EXCEEDS_INT(arg1)) { + if (!ZEND_IN_RANGE_OF(arg1, int)) { zend_argument_value_error(1, "must be between %d and %d", INT_MIN, INT_MAX); RETURN_THROWS(); } diff --git a/ext/standard/io_poll.c b/ext/standard/io_poll.c index c2585a51d3c4..02f2e1e064f8 100644 --- a/ext/standard/io_poll.c +++ b/ext/standard/io_poll.c @@ -880,7 +880,7 @@ PHP_METHOD(Io_Poll_Context, wait) } else if (UNEXPECTED(max_events <= 0)) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); - } else if (ZEND_LONG_INT_OVFL(max_events)) { + } else if (!ZEND_IN_RANGE_OF(max_events, int)) { zend_argument_value_error(2, "must be less than or equal to %d", INT_MAX); RETURN_THROWS(); } diff --git a/ext/standard/math.c b/ext/standard/math.c index 20286870c7c9..3e3d0f5a05d4 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -349,9 +349,9 @@ PHP_FUNCTION(round) if (ZEND_NUM_ARGS() >= 2) { if (precision >= 0) { - places = ZEND_LONG_INT_OVFL(precision) ? INT_MAX : (int)precision; + places = ZEND_IN_RANGE_OF(precision, int) ? (int)precision : INT_MAX; } else { - places = ZEND_LONG_INT_UDFL(precision) ? INT_MIN : (int)precision; + places = ZEND_IN_RANGE_OF(precision, int) ? (int)precision : INT_MIN; } } diff --git a/ext/standard/tests/strings/sapi_windows_cp_negative_codepage.phpt b/ext/standard/tests/strings/sapi_windows_cp_negative_codepage.phpt new file mode 100644 index 000000000000..997685f34ef3 --- /dev/null +++ b/ext/standard/tests/strings/sapi_windows_cp_negative_codepage.phpt @@ -0,0 +1,37 @@ +--TEST-- +sapi_windows_cp_set() and sapi_windows_cp_conv() must reject a negative codepage +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +try { + sapi_windows_cp_set(PHP_INT_MIN); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +try { + sapi_windows_cp_conv(-1, 65001, 'php'); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +try { + sapi_windows_cp_conv(65001, -1, 'php'); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} +?> +--EXPECT-- +ValueError: sapi_windows_cp_set(): Argument #1 ($codepage) must be between 0 and 4294967295 +ValueError: sapi_windows_cp_set(): Argument #1 ($codepage) must be between 0 and 4294967295 +ValueError: sapi_windows_cp_conv(): Argument #1 ($in_codepage) must be between 0 and 4294967295 +ValueError: sapi_windows_cp_conv(): Argument #2 ($out_codepage) must be between 0 and 4294967295 diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index a47871ede0dc..c8b4147975ff 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -279,7 +279,7 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, bool is_file) data = arg1; } - if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(data))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(data), unsigned int)) { if (is_file) { zend_string_release_ex(data, false); zend_argument_value_error(1, "File content is too long"); @@ -833,7 +833,7 @@ static zend_result php_tidy_parse_string(PHPTidyObj *obj, const zend_string *str { TidyBuffer buf; - ZEND_ASSERT(!ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(string))); + ZEND_ASSERT(ZEND_IN_RANGE_OF(ZSTR_LEN(string), unsigned int)); if (enc) { if (tidySetCharEncoding(obj->ptdoc->doc, enc) < 0) { @@ -992,7 +992,7 @@ static zend_result php_tidy_output_handler(void **nothing, php_output_context *o TidyBuffer inbuf, outbuf, errbuf; if (TG(clean_output) && (output_context->op & PHP_OUTPUT_HANDLER_START) && (output_context->op & PHP_OUTPUT_HANDLER_FINAL)) { - if (ZEND_SIZE_T_UINT_OVFL(output_context->in.used)) { + if (!ZEND_IN_RANGE_OF(output_context->in.used, unsigned int)) { php_error_docref(NULL, E_WARNING, "Input string is too long"); return status; } @@ -1043,7 +1043,7 @@ PHP_FUNCTION(tidy_parse_string) Z_PARAM_STRING_OR_NULL(enc, enc_len) ZEND_PARSE_PARAMETERS_END(); - if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(input))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(input), unsigned int)) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } @@ -1110,7 +1110,7 @@ PHP_FUNCTION(tidy_parse_file) RETURN_FALSE; } - if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(contents))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(contents), unsigned int)) { zend_string_release_ex(contents, 0); zend_value_error("File content is too long"); RETURN_THROWS(); @@ -1390,7 +1390,7 @@ PHP_METHOD(tidy, __construct) RETURN_THROWS(); } - if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(contents))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(contents), unsigned int)) { zend_string_release_ex(contents, 0); zend_value_error("File content is too long"); RETURN_THROWS(); @@ -1435,7 +1435,7 @@ PHP_METHOD(tidy, parseFile) RETURN_FALSE; } - if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(contents))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(contents), unsigned int)) { zend_string_release_ex(contents, 0); zend_value_error("File content is too long"); RETURN_THROWS(); @@ -1462,7 +1462,7 @@ PHP_METHOD(tidy, parseString) Z_PARAM_STRING_OR_NULL(enc, enc_len) ZEND_PARSE_PARAMETERS_END(); - if (ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(input))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(input), unsigned int)) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } diff --git a/win32/codepage.c b/win32/codepage.c index 1a723efa4496..61020ce989eb 100644 --- a/win32/codepage.c +++ b/win32/codepage.c @@ -597,8 +597,8 @@ PHP_FUNCTION(sapi_windows_cp_set) RETURN_THROWS(); } - if (ZEND_LONG_UINT_OVFL(id)) { - zend_argument_value_error(1, "must be between 0 and %u", UINT_MAX); + if (!ZEND_IN_RANGE_OF(id, DWORD)) { + zend_argument_value_error(1, "must be between 0 and %u", MAXDWORD); RETURN_THROWS(); } @@ -669,7 +669,7 @@ PHP_FUNCTION(sapi_windows_cp_conv) Z_PARAM_STR(subject) ZEND_PARSE_PARAMETERS_END(); - if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(subject))) { + if (!ZEND_IN_RANGE_OF(ZSTR_LEN(subject), int)) { zend_argument_value_error(1, "is too long"); RETURN_THROWS(); } @@ -681,8 +681,8 @@ PHP_FUNCTION(sapi_windows_cp_conv) RETURN_THROWS(); } } else { - if (ZEND_LONG_UINT_OVFL(int_in_codepage)) { - zend_argument_value_error(1, "must be between 0 and %u", UINT_MAX); + if (!ZEND_IN_RANGE_OF(int_in_codepage, DWORD)) { + zend_argument_value_error(1, "must be between 0 and %u", MAXDWORD); RETURN_THROWS(); } @@ -700,8 +700,8 @@ PHP_FUNCTION(sapi_windows_cp_conv) RETURN_THROWS(); } } else { - if (ZEND_LONG_UINT_OVFL(int_out_codepage)) { - zend_argument_value_error(2, "must be between 0 and %u", UINT_MAX); + if (!ZEND_IN_RANGE_OF(int_out_codepage, DWORD)) { + zend_argument_value_error(2, "must be between 0 and %u", MAXDWORD); RETURN_THROWS(); }