]> granicus.if.org Git - php/commitdiff
Add Z_PARAM_NUMBER and use it for some functions
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 3 Jun 2019 08:12:21 +0000 (10:12 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 3 Jun 2019 08:14:05 +0000 (10:14 +0200)
Zend/zend_API.c
Zend/zend_API.h
ext/opcache/Optimizer/zend_func_info.c
ext/standard/array.c
ext/standard/math.c
ext/standard/tests/array/range_errors.phpt
ext/standard/tests/array/range_variation.phpt
ext/standard/tests/math/abs_variation.phpt
ext/standard/tests/math/ceil_variation1.phpt
ext/standard/tests/math/floor_variation1.phpt

index d588266b423d51087a6b3728f9c1f00fcbe26fd5..c9c1654a6230c8db20b9994395b5407de81a639d 100644 (file)
@@ -381,6 +381,36 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) /
 }
 /* }}} */
 
+ZEND_API int ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest) /* {{{ */
+{
+       if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
+               return 0;
+       }
+       if (Z_TYPE_P(arg) == IS_STRING) {
+               zend_string *str = Z_STR_P(arg);
+               zend_long lval;
+               double dval;
+               zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &lval, &dval, -1);
+               if (type == IS_LONG) {
+                       ZVAL_LONG(arg, lval);
+               } else if (type == IS_DOUBLE) {
+                       ZVAL_DOUBLE(arg, dval);
+               } else {
+                       return 0;
+               }
+               zend_string_release(str);
+       } else if (Z_TYPE_P(arg) < IS_TRUE) {
+               ZVAL_LONG(arg, 0);
+       } else if (Z_TYPE_P(arg) == IS_TRUE) {
+               ZVAL_LONG(arg, 1);
+       } else {
+               return 0;
+       }
+       *dest = arg;
+       return 1;
+}
+/* }}} */
+
 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */
 {
        if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
index 8b534647a178e475b62172b5e17576fc07a18855..78640b771421cf5e6edab4e945a4577e862cc75e 100644 (file)
@@ -1098,7 +1098,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
        _(Z_EXPECTED_RESOURCE,  "resource") \
        _(Z_EXPECTED_PATH,              "a valid path") \
        _(Z_EXPECTED_OBJECT,    "object") \
-       _(Z_EXPECTED_DOUBLE,    "float")
+       _(Z_EXPECTED_DOUBLE,    "float") \
+       _(Z_EXPECTED_NUMBER,    "int or float") \
 
 #define Z_EXPECTED_TYPE_ENUM(id, str) id,
 #define Z_EXPECTED_TYPE_STR(id, str)  str,
@@ -1343,6 +1344,22 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e
 #define Z_PARAM_LONG(dest) \
        Z_PARAM_LONG_EX(dest, _dummy, 0, 0)
 
+
+/* no old equivalent */
+#define Z_PARAM_NUMBER_EX(dest, check_null) \
+       Z_PARAM_PROLOGUE(0, 0); \
+       if (UNEXPECTED(!zend_parse_arg_number(_arg, &dest, check_null))) { \
+               _expected_type = Z_EXPECTED_NUMBER; \
+               _error_code = ZPP_ERROR_WRONG_ARG; \
+               break; \
+       }
+
+#define Z_PARAM_NUMBER_OR_NULL(dest) \
+       Z_PARAM_NUMBER_EX(dest, 1)
+
+#define Z_PARAM_NUMBER(dest) \
+       Z_PARAM_NUMBER_EX(dest, 0)
+
 /* old "o" */
 #define Z_PARAM_OBJECT_EX2(dest, check_null, deref, separate) \
                Z_PARAM_PROLOGUE(deref, separate); \
@@ -1503,6 +1520,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest);
 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest);
 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest);
 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest);
+ZEND_API int ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest);
 
 static zend_always_inline int zend_parse_arg_bool(zval *arg, zend_bool *dest, zend_bool *is_null, int check_null)
 {
@@ -1554,6 +1572,18 @@ static zend_always_inline int zend_parse_arg_double(zval *arg, double *dest, zen
        return 1;
 }
 
+static zend_always_inline int zend_parse_arg_number(zval *arg, zval **dest, int check_null)
+{
+       if (EXPECTED(Z_TYPE_P(arg) == IS_LONG || Z_TYPE_P(arg) == IS_DOUBLE)) {
+               *dest = arg;
+       } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+               *dest = NULL;
+       } else {
+               return zend_parse_arg_number_slow(arg, dest);
+       }
+       return 1;
+}
+
 static zend_always_inline int zend_parse_arg_str(zval *arg, zend_string **dest, int check_null)
 {
        if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
index 1437229f0ea1ebbf17b569453c5f6e63f702ad25..588efd038374390542412be5b481980d7f477b39 100644 (file)
@@ -314,9 +314,9 @@ static const func_info_t func_infos[] = {
        F0("password_verify",              MAY_BE_FALSE | MAY_BE_TRUE),
        F1("convert_uuencode",             MAY_BE_FALSE | MAY_BE_STRING),
        F1("convert_uudecode",             MAY_BE_FALSE | MAY_BE_STRING),
-       F0("abs",                          MAY_BE_FALSE | MAY_BE_LONG | MAY_BE_DOUBLE),
-       F0("ceil",                         MAY_BE_FALSE | MAY_BE_DOUBLE),
-       F0("floor",                        MAY_BE_FALSE | MAY_BE_DOUBLE),
+       F0("abs",                          MAY_BE_LONG | MAY_BE_DOUBLE),
+       F0("ceil",                         MAY_BE_DOUBLE),
+       F0("floor",                        MAY_BE_DOUBLE),
        F0("round",                        MAY_BE_FALSE | MAY_BE_DOUBLE),
        F0("sin",                          MAY_BE_DOUBLE),
        F0("cos",                          MAY_BE_DOUBLE),
index e11554a3702903b2217cd64ca41e2d4a69e55d38..8f04db636d585b628cd5c0c3cdcceb7a5b836019 100644 (file)
@@ -2725,24 +2725,11 @@ PHP_FUNCTION(range)
                Z_PARAM_ZVAL(zlow)
                Z_PARAM_ZVAL(zhigh)
                Z_PARAM_OPTIONAL
-               Z_PARAM_ZVAL(zstep)
-       ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
+               Z_PARAM_NUMBER(zstep)
+       ZEND_PARSE_PARAMETERS_END();
 
        if (zstep) {
-               if (Z_TYPE_P(zstep) == IS_DOUBLE) {
-                       is_step_double = 1;
-               } else if (Z_TYPE_P(zstep) == IS_STRING) {
-                       int type = is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0);
-                       if (type == IS_DOUBLE) {
-                               is_step_double = 1;
-                       }
-                       if (type == 0) {
-                               /* bad number */
-                               php_error_docref(NULL, E_WARNING, "Invalid range string - must be numeric");
-                               RETURN_FALSE;
-                       }
-               }
-
+               is_step_double = Z_TYPE_P(zstep) == IS_DOUBLE;
                step = zval_get_double(zstep);
 
                /* We only want positive step values. */
index 1490fa0a4847a74954491ff3989e56d69d5fd38d..94d657ad7dbb6c9902c1913c55e1d66319cd820e 100644 (file)
@@ -283,18 +283,16 @@ static double php_expm1(double x)
 }
 /* }}}*/
 
-/* {{{ proto int|float|false abs(int number)
+/* {{{ proto int|float abs(int number)
    Return the absolute value of the number */
 PHP_FUNCTION(abs)
 {
        zval *value;
 
        ZEND_PARSE_PARAMETERS_START(1, 1)
-               Z_PARAM_ZVAL(value)
+               Z_PARAM_NUMBER(value)
        ZEND_PARSE_PARAMETERS_END();
 
-       convert_scalar_to_number_ex(value);
-
        if (Z_TYPE_P(value) == IS_DOUBLE) {
                RETURN_DOUBLE(fabs(Z_DVAL_P(value)));
        } else if (Z_TYPE_P(value) == IS_LONG) {
@@ -303,50 +301,49 @@ PHP_FUNCTION(abs)
                } else {
                        RETURN_LONG(Z_LVAL_P(value) < 0 ? -Z_LVAL_P(value) : Z_LVAL_P(value));
                }
+       } else {
+               ZEND_ASSERT(0 && "Unexpected type");
        }
-       RETURN_FALSE;
 }
 /* }}} */
 
-/* {{{ proto float|false ceil(float number)
+/* {{{ proto float ceil(float number)
    Returns the next highest integer value of the number */
 PHP_FUNCTION(ceil)
 {
        zval *value;
 
        ZEND_PARSE_PARAMETERS_START(1, 1)
-               Z_PARAM_ZVAL(value)
+               Z_PARAM_NUMBER(value)
        ZEND_PARSE_PARAMETERS_END();
 
-       convert_scalar_to_number_ex(value);
-
        if (Z_TYPE_P(value) == IS_DOUBLE) {
                RETURN_DOUBLE(ceil(Z_DVAL_P(value)));
        } else if (Z_TYPE_P(value) == IS_LONG) {
                RETURN_DOUBLE(zval_get_double(value));
+       } else {
+               ZEND_ASSERT(0 && "Unexpected type");
        }
-       RETURN_FALSE;
 }
 /* }}} */
 
-/* {{{ proto float|false floor(float number)
+/* {{{ proto float floor(float number)
    Returns the next lowest integer value from the number */
 PHP_FUNCTION(floor)
 {
        zval *value;
 
        ZEND_PARSE_PARAMETERS_START(1, 1)
-               Z_PARAM_ZVAL(value)
+               Z_PARAM_NUMBER(value)
        ZEND_PARSE_PARAMETERS_END();
 
-       convert_scalar_to_number_ex(value);
-
        if (Z_TYPE_P(value) == IS_DOUBLE) {
                RETURN_DOUBLE(floor(Z_DVAL_P(value)));
        } else if (Z_TYPE_P(value) == IS_LONG) {
                RETURN_DOUBLE(zval_get_double(value));
+       } else {
+               ZEND_ASSERT(0 && "Unexpected type");
        }
-       RETURN_FALSE;
 }
 /* }}} */
 
index 3a3b2bdf606052ad6e8896397eff9ed8ab4533a8..bd297945027f0ca6ad74c4fd47253d43435c365e 100644 (file)
@@ -23,7 +23,11 @@ var_dump( range(7.0, 1.0, 6.5) );
 
 echo "\n-- Testing other conditions --";
 var_dump( range(-1, -2, 2) );
-var_dump( range("a", "j", "z") );
+try {
+    var_dump( range("a", "j", "z") );
+} catch (TypeError $e) {
+    echo $e->getMessage(), "\n";
+}
 var_dump( range(0, 1, "140962482048819216326.24") );
 var_dump( range(0, 1, "140962482048819216326.24.") );
 
@@ -31,7 +35,11 @@ echo "\n-- Testing Invalid steps --";
 $step_arr = array( "string", NULL, FALSE, "", "\0" );
 
 foreach( $step_arr as $step ) {
-  var_dump( range( 1, 5, $step ) );
+    try {
+        var_dump( range( 1, 5, $step ) );
+    } catch (TypeError $e) {
+        echo $e->getMessage(), "\n";
+    }
 }
 
 echo "Done\n";
@@ -67,29 +75,23 @@ bool(false)
 -- Testing other conditions --
 Warning: range(): step exceeds the specified range in %s on line %d
 bool(false)
-
-Warning: range(): Invalid range string - must be numeric in %s on line %d
-bool(false)
+range() expects parameter 3 to be int or float, string given
 
 Warning: range(): step exceeds the specified range in %s on line %d
 bool(false)
 
-Warning: range(): Invalid range string - must be numeric in %s on line %d
-bool(false)
-
--- Testing Invalid steps --
-Warning: range(): Invalid range string - must be numeric in %s on line %d
-bool(false)
+Notice: A non well formed numeric value encountered in %s on line %d
 
 Warning: range(): step exceeds the specified range in %s on line %d
 bool(false)
 
-Warning: range(): step exceeds the specified range in %s on line %d
-bool(false)
+-- Testing Invalid steps --range() expects parameter 3 to be int or float, string given
 
-Warning: range(): Invalid range string - must be numeric in %s on line %d
+Warning: range(): step exceeds the specified range in %s on line %d
 bool(false)
 
-Warning: range(): Invalid range string - must be numeric in %s on line %d
+Warning: range(): step exceeds the specified range in %s on line %d
 bool(false)
+range() expects parameter 3 to be int or float, string given
+range() expects parameter 3 to be int or float, string given
 Done
index f7fc9e08152c61d7c015802919a2ec6b4f34bd51..3de5f6188f06ac92b2cc6d0e9a1e0df421e90685 100644 (file)
@@ -18,7 +18,11 @@ for( $i = 0; $i < count($low_arr); $i++) {
 
 echo "\n*** Possible variatins with steps ***\n";
 var_dump( range( 1, 5, TRUE ) );
-var_dump( range( 1, 5, array(1, 2) ) );
+try {
+    var_dump( range( 1, 5, array(1, 2) ) );
+} catch (TypeError $e) {
+    echo $e->getMessage(), "\n";
+}
 
 echo "Done\n";
 ?>
@@ -611,16 +615,5 @@ array(5) {
   [4]=>
   int(5)
 }
-array(5) {
-  [0]=>
-  int(1)
-  [1]=>
-  int(2)
-  [2]=>
-  int(3)
-  [3]=>
-  int(4)
-  [4]=>
-  int(5)
-}
+range() expects parameter 3 to be int or float, array given
 Done
index fd671855e12f9c8866d88d9bb008d59aa88f187c..e6838f7f72520b2c00f309e94b556eb2b8602fb6 100644 (file)
@@ -73,14 +73,18 @@ $inputs = array(
 $iterator = 1;
 foreach($inputs as $input) {
        echo "\n-- Iteration $iterator --\n";
-       var_dump(abs($input) );
+       try {
+               var_dump(abs($input));
+       } catch (TypeError $e) {
+               echo $e->getMessage(), "\n";
+       }
        $iterator++;
 };
 
 fclose($fp);
 ?>
 ===Done===
---EXPECTF--
+--EXPECT--
 *** Testing abs() : usage variations ***
 
 -- Iteration 1 --
@@ -102,27 +106,25 @@ int(1)
 int(0)
 
 -- Iteration 7 --
-int(0)
+abs() expects parameter 1 to be int or float, string given
 
 -- Iteration 8 --
-int(0)
+abs() expects parameter 1 to be int or float, string given
 
 -- Iteration 9 --
-bool(false)
+abs() expects parameter 1 to be int or float, array given
 
 -- Iteration 10 --
-int(0)
+abs() expects parameter 1 to be int or float, string given
 
 -- Iteration 11 --
-int(0)
+abs() expects parameter 1 to be int or float, string given
 
 -- Iteration 12 --
-int(0)
+abs() expects parameter 1 to be int or float, string given
 
 -- Iteration 13 --
-
-Notice: Object of class classA could not be converted to number in %s on line %d
-int(1)
+abs() expects parameter 1 to be int or float, object given
 
 -- Iteration 14 --
 int(0)
@@ -131,5 +133,5 @@ int(0)
 int(0)
 
 -- Iteration 16 --
-int(%d)
+abs() expects parameter 1 to be int or float, resource given
 ===Done===
index 05f308a4a0012dd378b20b166f3427c242656a80..07481126fdbed24195df4d20f36d4f3979fe4e6f 100644 (file)
@@ -67,13 +67,17 @@ $inputs = array(
 $iterator = 1;
 foreach($inputs as $input) {
        echo "\n-- Iteration $iterator --\n";
-       var_dump(ceil($input));
+       try {
+               var_dump(ceil($input));
+       } catch (TypeError $e) {
+               echo $e->getMessage(), "\n";
+       }
        $iterator++;
 };
 fclose($fp);
 ?>
 ===Done===
---EXPECTF--
+--EXPECT--
 *** Testing ceil() : usage variations ***
 
 -- Iteration 1 --
@@ -95,27 +99,25 @@ float(1)
 float(0)
 
 -- Iteration 7 --
-float(0)
+ceil() expects parameter 1 to be int or float, string given
 
 -- Iteration 8 --
-float(0)
+ceil() expects parameter 1 to be int or float, string given
 
 -- Iteration 9 --
-bool(false)
+ceil() expects parameter 1 to be int or float, array given
 
 -- Iteration 10 --
-float(0)
+ceil() expects parameter 1 to be int or float, string given
 
 -- Iteration 11 --
-float(0)
+ceil() expects parameter 1 to be int or float, string given
 
 -- Iteration 12 --
-float(0)
+ceil() expects parameter 1 to be int or float, string given
 
 -- Iteration 13 --
-
-Notice: Object of class classA could not be converted to number in %s on line %d
-float(1)
+ceil() expects parameter 1 to be int or float, object given
 
 -- Iteration 14 --
 float(0)
@@ -124,5 +126,5 @@ float(0)
 float(0)
 
 -- Iteration 16 --
-float(%d)
+ceil() expects parameter 1 to be int or float, resource given
 ===Done===
index aef4c742b9c1f53393cad505cc507f77fd11b9ba..e3406eba8700973de8d8ae183437703115018a8c 100644 (file)
@@ -67,13 +67,17 @@ $inputs = array(
 $iterator = 1;
 foreach($inputs as $input) {
        echo "\n-- Iteration $iterator --\n";
-       var_dump(floor($input));
+       try {
+               var_dump(floor($input));
+       } catch (TypeError $e) {
+               echo $e->getMessage(), "\n";
+       }
        $iterator++;
 };
 fclose($fp);
 ?>
 ===Done===
---EXPECTF--
+--EXPECT--
 *** Testing floor() : usage variations ***
 
 -- Iteration 1 --
@@ -95,27 +99,25 @@ float(1)
 float(0)
 
 -- Iteration 7 --
-float(0)
+floor() expects parameter 1 to be int or float, string given
 
 -- Iteration 8 --
-float(0)
+floor() expects parameter 1 to be int or float, string given
 
 -- Iteration 9 --
-bool(false)
+floor() expects parameter 1 to be int or float, array given
 
 -- Iteration 10 --
-float(0)
+floor() expects parameter 1 to be int or float, string given
 
 -- Iteration 11 --
-float(0)
+floor() expects parameter 1 to be int or float, string given
 
 -- Iteration 12 --
-float(0)
+floor() expects parameter 1 to be int or float, string given
 
 -- Iteration 13 --
-
-Notice: Object of class classA could not be converted to number in %s on line %d
-float(1)
+floor() expects parameter 1 to be int or float, object given
 
 -- Iteration 14 --
 float(0)
@@ -124,5 +126,5 @@ float(0)
 float(0)
 
 -- Iteration 16 --
-float(%f)
+floor() expects parameter 1 to be int or float, resource given
 ===Done===