/src/php-src/ext/standard/incomplete_class.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Copyright (c) The PHP Group | |
4 | | +----------------------------------------------------------------------+ |
5 | | | This source file is subject to version 3.01 of the PHP license, | |
6 | | | that is bundled with this package in the file LICENSE, and is | |
7 | | | available through the world-wide-web at the following url: | |
8 | | | https://www.php.net/license/3_01.txt | |
9 | | | If you did not receive a copy of the PHP license and are unable to | |
10 | | | obtain it through the world-wide-web, please send a note to | |
11 | | | license@php.net so we can mail you a copy immediately. | |
12 | | +----------------------------------------------------------------------+ |
13 | | | Author: Sascha Schumann <sascha@schumann.cx> | |
14 | | +----------------------------------------------------------------------+ |
15 | | */ |
16 | | |
17 | | #include "php.h" |
18 | | #include "basic_functions.h" |
19 | | #include "php_incomplete_class.h" |
20 | | |
21 | | #define INCOMPLETE_CLASS_MSG \ |
22 | 42 | "The script tried to %s on an incomplete object. " \ |
23 | 42 | "Please ensure that the class definition \"%s\" of the object " \ |
24 | 42 | "you are trying to operate on was loaded _before_ " \ |
25 | 42 | "unserialize() gets called or provide an autoloader " \ |
26 | 42 | "to load the class definition" |
27 | | |
28 | | PHPAPI zend_class_entry *php_ce_incomplete_class; |
29 | | static zend_object_handlers php_incomplete_object_handlers; |
30 | | |
31 | | static void incomplete_class_message(zend_object *object) |
32 | 0 | { |
33 | 0 | zend_string *class_name = php_lookup_class_name(object); |
34 | 0 | php_error_docref(NULL, E_WARNING, INCOMPLETE_CLASS_MSG, |
35 | 0 | "access a property", class_name ? ZSTR_VAL(class_name) : "unknown"); |
36 | 0 | if (class_name) { |
37 | 0 | zend_string_release_ex(class_name, 0); |
38 | 0 | } |
39 | 0 | } |
40 | | |
41 | | static void throw_incomplete_class_error(zend_object *object, const char *what) |
42 | 42 | { |
43 | 42 | zend_string *class_name = php_lookup_class_name(object); |
44 | 42 | zend_throw_error(NULL, INCOMPLETE_CLASS_MSG, |
45 | 42 | what, class_name ? ZSTR_VAL(class_name) : "unknown"); |
46 | 42 | if (class_name) { |
47 | 42 | zend_string_release_ex(class_name, 0); |
48 | 42 | } |
49 | 42 | } |
50 | | |
51 | | static zval *incomplete_class_get_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv) /* {{{ */ |
52 | 0 | { |
53 | 0 | incomplete_class_message(object); |
54 | |
|
55 | 0 | if (type == BP_VAR_W || type == BP_VAR_RW) { |
56 | 0 | ZVAL_ERROR(rv); |
57 | 0 | return rv; |
58 | 0 | } else { |
59 | 0 | return &EG(uninitialized_zval); |
60 | 0 | } |
61 | 0 | } |
62 | | /* }}} */ |
63 | | |
64 | | static zval *incomplete_class_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */ |
65 | 0 | { |
66 | 0 | throw_incomplete_class_error(object, "modify a property"); |
67 | 0 | return value; |
68 | 0 | } |
69 | | /* }}} */ |
70 | | |
71 | | static zval *incomplete_class_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot) /* {{{ */ |
72 | 42 | { |
73 | 42 | throw_incomplete_class_error(object, "modify a property"); |
74 | 42 | return &EG(error_zval); |
75 | 42 | } |
76 | | /* }}} */ |
77 | | |
78 | | static void incomplete_class_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */ |
79 | 0 | { |
80 | 0 | throw_incomplete_class_error(object, "modify a property"); |
81 | 0 | } |
82 | | /* }}} */ |
83 | | |
84 | | static int incomplete_class_has_property(zend_object *object, zend_string *member, int check_empty, void **cache_slot) /* {{{ */ |
85 | 0 | { |
86 | 0 | incomplete_class_message(object); |
87 | 0 | return 0; |
88 | 0 | } |
89 | | /* }}} */ |
90 | | |
91 | | static zend_function *incomplete_class_get_method(zend_object **object, zend_string *method, const zval *key) /* {{{ */ |
92 | 0 | { |
93 | 0 | throw_incomplete_class_error(*object, "call a method"); |
94 | 0 | return NULL; |
95 | 0 | } |
96 | | /* }}} */ |
97 | | |
98 | | /* {{{ php_create_incomplete_class */ |
99 | | static zend_object *php_create_incomplete_object(zend_class_entry *class_type) |
100 | 235k | { |
101 | 235k | zend_object *object; |
102 | | |
103 | 235k | object = zend_objects_new( class_type); |
104 | 235k | object->handlers = &php_incomplete_object_handlers; |
105 | | |
106 | 235k | object_properties_init(object, class_type); |
107 | | |
108 | 235k | return object; |
109 | 235k | } |
110 | | |
111 | | PHPAPI void php_register_incomplete_class_handlers(void) |
112 | 16 | { |
113 | 16 | memcpy(&php_incomplete_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); |
114 | 16 | php_incomplete_object_handlers.read_property = incomplete_class_get_property; |
115 | 16 | php_incomplete_object_handlers.has_property = incomplete_class_has_property; |
116 | 16 | php_incomplete_object_handlers.unset_property = incomplete_class_unset_property; |
117 | 16 | php_incomplete_object_handlers.write_property = incomplete_class_write_property; |
118 | 16 | php_incomplete_object_handlers.get_property_ptr_ptr = incomplete_class_get_property_ptr_ptr; |
119 | 16 | php_incomplete_object_handlers.get_method = incomplete_class_get_method; |
120 | | |
121 | 16 | php_ce_incomplete_class->create_object = php_create_incomplete_object; |
122 | 16 | } |
123 | | /* }}} */ |
124 | | |
125 | | /* {{{ php_lookup_class_name */ |
126 | | PHPAPI zend_string *php_lookup_class_name(zend_object *object) |
127 | 42 | { |
128 | 42 | if (object->properties) { |
129 | 42 | zval *val = zend_hash_str_find(object->properties, MAGIC_MEMBER, sizeof(MAGIC_MEMBER)-1); |
130 | | |
131 | 42 | if (val != NULL && Z_TYPE_P(val) == IS_STRING) { |
132 | 42 | return zend_string_copy(Z_STR_P(val)); |
133 | 42 | } |
134 | 42 | } |
135 | | |
136 | 0 | return NULL; |
137 | 42 | } |
138 | | /* }}} */ |
139 | | |
140 | | /* {{{ php_store_class_name */ |
141 | | PHPAPI void php_store_class_name(zval *object, zend_string *name) |
142 | 235k | { |
143 | 235k | zval val; |
144 | | |
145 | 235k | ZVAL_STR_COPY(&val, name); |
146 | 235k | zend_hash_str_update(Z_OBJPROP_P(object), MAGIC_MEMBER, sizeof(MAGIC_MEMBER)-1, &val); |
147 | 235k | } |
148 | | /* }}} */ |