]> granicus.if.org Git - php/commitdiff
Add ZPP macros for class name or object parameters
authorMáté Kocsis <kocsismate@woohoolabs.com>
Tue, 30 Jun 2020 09:14:58 +0000 (11:14 +0200)
committerMáté Kocsis <kocsismate@woohoolabs.com>
Tue, 30 Jun 2020 09:19:30 +0000 (11:19 +0200)
Closes GH-5647

Zend/tests/010.phpt
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_builtin_functions.stub.php
Zend/zend_builtin_functions_arginfo.h
ext/date/php_date.c
ext/standard/tests/class_object/get_parent_class_variation_002.phpt

index a4a862cac220152c4520a29f854901ac78d9b6e0..351398ecfa85427939705aac27bbcf5d06d59168 100644 (file)
@@ -32,12 +32,37 @@ var_dump(get_parent_class("bar"));
 var_dump(get_parent_class("foo"));
 var_dump(get_parent_class("i"));
 
-var_dump(get_parent_class(""));
-var_dump(get_parent_class("[[[["));
-var_dump(get_parent_class(" "));
+try {
+    get_parent_class("");
+} catch (TypeError $exception) {
+    echo $exception->getMessage() . "\n";
+}
+
+try {
+    get_parent_class("[[[[");
+} catch (TypeError $exception) {
+    echo $exception->getMessage() . "\n";
+}
+
+try {
+    get_parent_class(" ");
+} catch (TypeError $exception) {
+    echo $exception->getMessage() . "\n";
+}
+
 var_dump(get_parent_class(new stdclass));
-var_dump(get_parent_class(array()));
-var_dump(get_parent_class(1));
+
+try {
+    get_parent_class(array());
+} catch (TypeError $exception) {
+    echo $exception->getMessage() . "\n";
+}
+
+try {
+    get_parent_class(1);
+} catch (TypeError $exception) {
+    echo $exception->getMessage() . "\n";
+}
 
 echo "Done\n";
 ?>
@@ -50,10 +75,10 @@ bool(false)
 string(3) "foo"
 bool(false)
 bool(false)
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
 bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, int given
 Done
index 9744612ac7460168e5c990d417be982e0e66a760..ae0363f7657bc2b62caf5ff7cfa8a2a578109862 100644 (file)
@@ -1217,6 +1217,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
        _(Z_EXPECTED_STRING_OR_ARRAY_OR_NULL, "of type string|array|null") \
        _(Z_EXPECTED_STRING_OR_LONG,    "of type string|int") \
        _(Z_EXPECTED_STRING_OR_LONG_OR_NULL, "of type string|int|null") \
+       _(Z_EXPECTED_CLASS_NAME_OR_OBJECT,      "a valid class name or object") \
+       _(Z_EXPECTED_CLASS_NAME_OR_OBJECT_OR_NULL, "a valid class name, object, or null") \
 
 #define Z_EXPECTED_TYPE
 
@@ -1395,6 +1397,20 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
 #define Z_PARAM_CLASS(dest) \
        Z_PARAM_CLASS_EX(dest, 0, 0)
 
+#define Z_PARAM_CLASS_NAME_OR_OBJ_EX(dest, allow_null) \
+       Z_PARAM_PROLOGUE(0, 0); \
+       if (UNEXPECTED(!zend_parse_arg_class_name_or_obj(_arg, &dest, _i, allow_null))) { \
+               _expected_type = allow_null ? Z_EXPECTED_CLASS_NAME_OR_OBJECT_OR_NULL : Z_EXPECTED_CLASS_NAME_OR_OBJECT; \
+               _error_code = ZPP_ERROR_WRONG_ARG; \
+               break; \
+       }
+
+#define Z_PARAM_CLASS_NAME_OR_OBJ(dest) \
+       Z_PARAM_CLASS_NAME_OR_OBJ_EX(dest, 0);
+
+#define Z_PARAM_CLASS_NAME_OR_OBJ_OR_NULL(dest) \
+       Z_PARAM_CLASS_NAME_OR_OBJ_EX(dest, 1);
+
 /* old "d" */
 #define Z_PARAM_DOUBLE_EX2(dest, is_null, check_null, deref, separate) \
                Z_PARAM_PROLOGUE(deref, separate); \
@@ -1513,6 +1529,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
 #define Z_PARAM_OBJECT(dest) \
        Z_PARAM_OBJECT_EX(dest, 0, 0)
 
+#define Z_PARAM_OBJECT_OR_NULL(dest) \
+       Z_PARAM_OBJECT_EX(dest, 1, 0)
+
 /* old "O" */
 #define Z_PARAM_OBJECT_OF_CLASS_EX2(dest, _ce, check_null, deref, separate) \
                Z_PARAM_PROLOGUE(deref, separate); \
@@ -1534,6 +1553,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
 #define Z_PARAM_OBJECT_OF_CLASS(dest, _ce) \
        Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 0, 0)
 
+#define Z_PARAM_OBJECT_OF_CLASS_OR_NULL(dest, _ce) \
+       Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 1, 0)
+
 /* old "p" */
 #define Z_PARAM_PATH_EX2(dest, dest_len, check_null, deref, separate) \
                Z_PARAM_PROLOGUE(deref, separate); \
@@ -1673,6 +1695,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
 
 #define Z_PARAM_STR_OR_LONG_OR_NULL(dest_str, dest_long, is_null) \
        Z_PARAM_STR_OR_LONG_EX(dest_str, dest_long, is_null, 1);
+
 /* End of new parameter parsing API */
 
 /* Inlined implementations shared by new and old parameter parsing APIs */
@@ -1931,6 +1954,24 @@ static zend_always_inline int zend_parse_arg_str_or_long(zval *arg, zend_string
        return 1;
 }
 
+static zend_always_inline int zend_parse_arg_class_name_or_obj(
+       zval *arg, zend_class_entry **destination, int num, int allow_null
+) {
+       if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
+               *destination = zend_lookup_class(Z_STR_P(arg));
+
+               return *destination != NULL;
+       } else if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
+               *destination = Z_OBJ_P(arg)->ce;
+       } else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+               *destination = NULL;
+       } else {
+               return 0;
+       }
+
+       return 1;
+}
+
 END_EXTERN_C()
 
 #endif /* ZEND_API_H */
index 521c2c32de199623a94559f0b729e759942356dd..881624d321a87d1903c3f7f0cfcbccdab52a8202 100644 (file)
@@ -637,26 +637,15 @@ ZEND_FUNCTION(get_called_class)
    Retrieves the parent class name for object or class or current scope or false if not in a scope. */
 ZEND_FUNCTION(get_parent_class)
 {
-       zval *arg;
        zend_class_entry *ce = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
-               RETURN_THROWS();
-       }
+       ZEND_PARSE_PARAMETERS_START(0, 1)
+               Z_PARAM_OPTIONAL
+               Z_PARAM_CLASS_NAME_OR_OBJ(ce)
+       ZEND_PARSE_PARAMETERS_END();
 
-       if (!ZEND_NUM_ARGS()) {
+       if (!ce) {
                ce = zend_get_executed_scope();
-               if (ce && ce->parent) {
-                       RETURN_STR_COPY(ce->parent->name);
-               } else {
-                       RETURN_FALSE;
-               }
-       }
-
-       if (Z_TYPE_P(arg) == IS_OBJECT) {
-               ce = Z_OBJ_P(arg)->ce;
-       } else if (Z_TYPE_P(arg) == IS_STRING) {
-               ce = zend_lookup_class(Z_STR_P(arg));
        }
 
        if (ce && ce->parent) {
index 9e5078f14a9c91ed19e3cdfd3d5fb0544e190063..a79aced5fed7ecec842853e79a60088588a93937 100644 (file)
@@ -30,7 +30,7 @@ function get_class(object $object = UNKNOWN): string {}
 
 function get_called_class(): string {}
 
-function get_parent_class($object = UNKNOWN): string|false {}
+function get_parent_class(string|object $object = UNKNOWN): string|false {}
 
 function is_subclass_of($object, string $class_name, bool $allow_string = true): bool {}
 
index df1f06888ee94ac132e7466e38e06b25ee6593f2..c464a540a1ff015142529b125f938649991da703 100644 (file)
@@ -54,7 +54,7 @@ ZEND_END_ARG_INFO()
 #define arginfo_get_called_class arginfo_zend_version
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_parent_class, 0, 0, MAY_BE_STRING|MAY_BE_FALSE)
-       ZEND_ARG_INFO(0, object)
+       ZEND_ARG_TYPE_MASK(0, object, MAY_BE_STRING|MAY_BE_OBJECT, NULL)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_subclass_of, 0, 2, _IS_BOOL, 0)
index 0b4520566fe0dba109f8335295094f6fc3058398..6813b60e624c8061ef3d3a53f5da163f411e5dfe 100644 (file)
@@ -2295,7 +2295,7 @@ PHP_FUNCTION(date_create)
        ZEND_PARSE_PARAMETERS_START(0, 2)
                Z_PARAM_OPTIONAL
                Z_PARAM_STRING(time_str, time_str_len)
-               Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
+               Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
        ZEND_PARSE_PARAMETERS_END();
 
        php_date_instantiate(date_ce_date, return_value);
@@ -2318,7 +2318,7 @@ PHP_FUNCTION(date_create_immutable)
        ZEND_PARSE_PARAMETERS_START(0, 2)
                Z_PARAM_OPTIONAL
                Z_PARAM_STRING(time_str, time_str_len)
-               Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
+               Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
        ZEND_PARSE_PARAMETERS_END();
 
        php_date_instantiate(date_ce_immutable, return_value);
@@ -2342,7 +2342,7 @@ PHP_FUNCTION(date_create_from_format)
                Z_PARAM_STRING(format_str, format_str_len)
                Z_PARAM_STRING(time_str, time_str_len)
                Z_PARAM_OPTIONAL
-               Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
+               Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
        ZEND_PARSE_PARAMETERS_END();
 
        php_date_instantiate(date_ce_date, return_value);
@@ -2366,7 +2366,7 @@ PHP_FUNCTION(date_create_immutable_from_format)
                Z_PARAM_STRING(format_str, format_str_len)
                Z_PARAM_STRING(time_str, time_str_len)
                Z_PARAM_OPTIONAL
-               Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
+               Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
        ZEND_PARSE_PARAMETERS_END();
 
        php_date_instantiate(date_ce_immutable, return_value);
@@ -2390,7 +2390,7 @@ PHP_METHOD(DateTime, __construct)
        ZEND_PARSE_PARAMETERS_START(0, 2)
                Z_PARAM_OPTIONAL
                Z_PARAM_STRING(time_str, time_str_len)
-               Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
+               Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
        ZEND_PARSE_PARAMETERS_END();
 
        zend_replace_error_handling(EH_THROW, NULL, &error_handling);
@@ -2412,7 +2412,7 @@ PHP_METHOD(DateTimeImmutable, __construct)
        ZEND_PARSE_PARAMETERS_START(0, 2)
                Z_PARAM_OPTIONAL
                Z_PARAM_STRING(time_str, time_str_len)
-               Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
+               Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
        ZEND_PARSE_PARAMETERS_END();
 
        zend_replace_error_handling(EH_THROW, NULL, &error_handling);
index 8d3e64e92515fffd1efbd37ba9977d3d32bedd2e..a8c8e1711760f12fecc9a5bc94b031b8e4f6b18e 100644 (file)
@@ -70,10 +70,14 @@ $values = array(
 
 // loop through each element of the array for object
 
-foreach($values as $value) {
-      echo "\nArg value " . (is_object($value) ? get_class($value) : $value) . " \n";
-      var_dump( get_parent_class($value) );
-};
+foreach ($values as $value) {
+    echo "\nArg value " . (is_object($value) ? get_class($value) : $value) . "\n";
+    try {
+        var_dump(get_parent_class($value));
+    } catch (TypeError $exception) {
+        echo $exception->getMessage() . "\n";
+    }
+}
 
 echo "Done";
 ?>
@@ -82,91 +86,91 @@ echo "Done";
 Error: 2 - Undefined variable $undefined_var
 Error: 2 - Undefined variable $unset_var
 
-Arg value 0 
-bool(false)
+Arg value 0
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, int given
 
-Arg value 1 
-bool(false)
+Arg value 1
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, int given
 
-Arg value 12345 
-bool(false)
+Arg value 12345
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, int given
 
-Arg value -2345 
-bool(false)
+Arg value -2345
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, int given
 
-Arg value 10.5 
-bool(false)
+Arg value 10.5
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, float given
 
-Arg value -10.5 
-bool(false)
+Arg value -10.5
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, float given
 
-Arg value 101234567000 
-bool(false)
+Arg value 101234567000
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, float given
 
-Arg value 1.07654321E-9 
-bool(false)
+Arg value 1.07654321E-9
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, float given
 
-Arg value 0.5 
-bool(false)
+Arg value 0.5
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, float given
 Error: 2 - Array to string conversion
 
-Arg value Array 
-bool(false)
+Arg value Array
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
 Error: 2 - Array to string conversion
 
-Arg value Array 
-bool(false)
+Arg value Array
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
 Error: 2 - Array to string conversion
 
-Arg value Array 
-bool(false)
+Arg value Array
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
 Error: 2 - Array to string conversion
 
-Arg value Array 
-bool(false)
+Arg value Array
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
 Error: 2 - Array to string conversion
 
-Arg value Array 
-bool(false)
+Arg value Array
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, null given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, null given
 
-Arg value 1 
-bool(false)
+Arg value 1
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, bool given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, bool given
 
-Arg value 1 
-bool(false)
+Arg value 1
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, bool given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, bool given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
 
-Arg value string 
+Arg value string
 In autoload(string)
-bool(false)
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
 
-Arg value String 
+Arg value String
 In autoload(String)
-bool(false)
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
 
-Arg value stdClass 
+Arg value stdClass
 bool(false)
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, null given
 
-Arg value  
-bool(false)
+Arg value 
+get_parent_class(): Argument #1 ($object) must be a valid class name or object, null given
 Done