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: Rasmus Lerdorf <rasmus@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "php.h"
18 #include "php_incomplete_class.h"
19
20 /* {{{ Returns the type of the variable */
PHP_FUNCTION(gettype)21 PHP_FUNCTION(gettype)
22 {
23 zval *arg;
24 zend_string *type;
25
26 ZEND_PARSE_PARAMETERS_START(1, 1)
27 Z_PARAM_ZVAL(arg)
28 ZEND_PARSE_PARAMETERS_END();
29
30 type = zend_zval_get_legacy_type(arg);
31 if (EXPECTED(type)) {
32 RETURN_INTERNED_STR(type);
33 } else {
34 RETURN_STRING("unknown type");
35 }
36 }
37 /* }}} */
38
39 /* {{{ Returns the type of the variable resolving class names */
PHP_FUNCTION(get_debug_type)40 PHP_FUNCTION(get_debug_type)
41 {
42 zval *arg;
43 const char *name;
44
45 ZEND_PARSE_PARAMETERS_START(1, 1)
46 Z_PARAM_ZVAL(arg)
47 ZEND_PARSE_PARAMETERS_END();
48
49 switch (Z_TYPE_P(arg)) {
50 case IS_NULL:
51 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE));
52 case IS_FALSE:
53 case IS_TRUE:
54 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_BOOL));
55 case IS_LONG:
56 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_INT));
57 case IS_DOUBLE:
58 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_FLOAT));
59 case IS_STRING:
60 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_STRING));
61 case IS_ARRAY:
62 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY));
63 case IS_OBJECT:
64 if (Z_OBJ_P(arg)->ce->ce_flags & ZEND_ACC_ANON_CLASS) {
65 name = ZSTR_VAL(Z_OBJ_P(arg)->ce->name);
66 RETURN_NEW_STR(zend_string_init(name, strlen(name), 0));
67 } else {
68 RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name);
69 }
70 case IS_RESOURCE:
71 name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
72 if (name) {
73 RETURN_NEW_STR(zend_strpprintf(0, "resource (%s)", name));
74 } else {
75 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE));
76 }
77 default:
78 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN));
79 }
80 }
81 /* }}} */
82
83
84 /* {{{ Set the type of the variable */
PHP_FUNCTION(settype)85 PHP_FUNCTION(settype)
86 {
87 zval *var;
88 zend_string *type;
89 zval tmp, *ptr;
90
91 ZEND_PARSE_PARAMETERS_START(2, 2)
92 Z_PARAM_ZVAL(var)
93 Z_PARAM_STR(type)
94 ZEND_PARSE_PARAMETERS_END();
95
96 ZEND_ASSERT(Z_ISREF_P(var));
97 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(var)))) {
98 ZVAL_COPY(&tmp, Z_REFVAL_P(var));
99 ptr = &tmp;
100 } else {
101 ptr = Z_REFVAL_P(var);
102 }
103 if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_INTEGER))) {
104 convert_to_long(ptr);
105 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_INT))) {
106 convert_to_long(ptr);
107 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_FLOAT))) {
108 convert_to_double(ptr);
109 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_DOUBLE))) { /* deprecated */
110 convert_to_double(ptr);
111 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_STRING))) {
112 convert_to_string(ptr);
113 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_ARRAY))) {
114 convert_to_array(ptr);
115 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_OBJECT))) {
116 convert_to_object(ptr);
117 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_BOOL))) {
118 convert_to_boolean(ptr);
119 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_BOOLEAN))) {
120 convert_to_boolean(ptr);
121 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE))) {
122 convert_to_null(ptr);
123 } else {
124 if (ptr == &tmp) {
125 zval_ptr_dtor(&tmp);
126 }
127 if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_RESOURCE))) {
128 zend_value_error("Cannot convert to resource type");
129 } else {
130 zend_argument_value_error(2, "must be a valid type");
131 }
132 RETURN_THROWS();
133 }
134
135 if (ptr == &tmp) {
136 zend_try_assign_typed_ref(Z_REF_P(var), &tmp);
137 }
138 RETVAL_TRUE;
139 }
140 /* }}} */
141
142 /* {{{ Get the integer value of a variable using the optional base for the conversion */
PHP_FUNCTION(intval)143 PHP_FUNCTION(intval)
144 {
145 zval *num;
146 zend_long base = 10;
147
148 ZEND_PARSE_PARAMETERS_START(1, 2)
149 Z_PARAM_ZVAL(num)
150 Z_PARAM_OPTIONAL
151 Z_PARAM_LONG(base)
152 ZEND_PARSE_PARAMETERS_END();
153
154 if (Z_TYPE_P(num) != IS_STRING || base == 10) {
155 RETVAL_LONG(zval_get_long(num));
156 return;
157 }
158
159
160 if (base == 0 || base == 2) {
161 char *strval = Z_STRVAL_P(num);
162 size_t strlen = Z_STRLEN_P(num);
163
164 while (isspace(*strval) && strlen) {
165 strval++;
166 strlen--;
167 }
168
169 /* Length of 3+ covers "0b#" and "-0b" (which results in 0) */
170 if (strlen > 2) {
171 int offset = 0;
172 if (strval[0] == '-' || strval[0] == '+') {
173 offset = 1;
174 }
175
176 if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) {
177 char *tmpval;
178 strlen -= 2; /* Removing "0b" */
179 tmpval = emalloc(strlen + 1);
180
181 /* Place the unary symbol at pos 0 if there was one */
182 if (offset) {
183 tmpval[0] = strval[0];
184 }
185
186 /* Copy the data from after "0b" to the end of the buffer */
187 memcpy(tmpval + offset, strval + offset + 2, strlen - offset);
188 tmpval[strlen] = 0;
189
190 RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2));
191 efree(tmpval);
192 return;
193 }
194 }
195 }
196
197 RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
198 }
199 /* }}} */
200
201 /* {{{ Get the float value of a variable */
PHP_FUNCTION(floatval)202 PHP_FUNCTION(floatval)
203 {
204 zval *num;
205
206 ZEND_PARSE_PARAMETERS_START(1, 1)
207 Z_PARAM_ZVAL(num)
208 ZEND_PARSE_PARAMETERS_END();
209
210 RETURN_DOUBLE(zval_get_double(num));
211 }
212 /* }}} */
213
214 /* {{{ Get the boolean value of a variable */
PHP_FUNCTION(boolval)215 PHP_FUNCTION(boolval)
216 {
217 zval *value;
218
219 ZEND_PARSE_PARAMETERS_START(1, 1)
220 Z_PARAM_ZVAL(value)
221 ZEND_PARSE_PARAMETERS_END();
222
223 RETURN_BOOL(zend_is_true(value));
224 }
225 /* }}} */
226
227 /* {{{ Get the string value of a variable */
PHP_FUNCTION(strval)228 PHP_FUNCTION(strval)
229 {
230 zval *value;
231
232 ZEND_PARSE_PARAMETERS_START(1, 1)
233 Z_PARAM_ZVAL(value)
234 ZEND_PARSE_PARAMETERS_END();
235
236 RETVAL_STR(zval_get_string(value));
237 }
238 /* }}} */
239
php_is_type(INTERNAL_FUNCTION_PARAMETERS,int type)240 static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
241 {
242 zval *arg;
243
244 ZEND_PARSE_PARAMETERS_START(1, 1)
245 Z_PARAM_ZVAL(arg)
246 ZEND_PARSE_PARAMETERS_END();
247
248 if (Z_TYPE_P(arg) == type) {
249 if (type == IS_RESOURCE) {
250 const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
251 if (!type_name) {
252 RETURN_FALSE;
253 }
254 }
255 RETURN_TRUE;
256 } else {
257 RETURN_FALSE;
258 }
259 }
260
261
262 /* {{{ Returns true if variable is null
263 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_null)264 PHP_FUNCTION(is_null)
265 {
266 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_NULL);
267 }
268 /* }}} */
269
270 /* {{{ Returns true if variable is a resource
271 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_resource)272 PHP_FUNCTION(is_resource)
273 {
274 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_RESOURCE);
275 }
276 /* }}} */
277
278 /* {{{ Returns true if variable is a boolean
279 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_bool)280 PHP_FUNCTION(is_bool)
281 {
282 zval *arg;
283
284 ZEND_PARSE_PARAMETERS_START(1, 1)
285 Z_PARAM_ZVAL(arg)
286 ZEND_PARSE_PARAMETERS_END();
287
288 RETURN_BOOL(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE);
289 }
290 /* }}} */
291
292 /* {{{ Returns true if variable is an integer
293 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_int)294 PHP_FUNCTION(is_int)
295 {
296 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_LONG);
297 }
298 /* }}} */
299
300 /* {{{ Returns true if variable is float point
301 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_float)302 PHP_FUNCTION(is_float)
303 {
304 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_DOUBLE);
305 }
306 /* }}} */
307
308 /* {{{ Returns true if variable is a string
309 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_string)310 PHP_FUNCTION(is_string)
311 {
312 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING);
313 }
314 /* }}} */
315
316 /* {{{ Returns true if variable is an array
317 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_array)318 PHP_FUNCTION(is_array)
319 {
320 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY);
321 }
322 /* }}} */
323
324 /* {{{ Returns true if $array is an array whose keys are all numeric, sequential, and start at 0 */
PHP_FUNCTION(array_is_list)325 PHP_FUNCTION(array_is_list)
326 {
327 HashTable *array;
328
329 ZEND_PARSE_PARAMETERS_START(1, 1)
330 Z_PARAM_ARRAY_HT(array)
331 ZEND_PARSE_PARAMETERS_END();
332
333 RETURN_BOOL(zend_array_is_list(array));
334 }
335 /* }}} */
336
337 /* {{{ Returns true if variable is an object
338 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_object)339 PHP_FUNCTION(is_object)
340 {
341 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_OBJECT);
342 }
343 /* }}} */
344
345 /* {{{ Returns true if value is a number or a numeric string */
PHP_FUNCTION(is_numeric)346 PHP_FUNCTION(is_numeric)
347 {
348 zval *arg;
349
350 ZEND_PARSE_PARAMETERS_START(1, 1)
351 Z_PARAM_ZVAL(arg)
352 ZEND_PARSE_PARAMETERS_END();
353
354 switch (Z_TYPE_P(arg)) {
355 case IS_LONG:
356 case IS_DOUBLE:
357 RETURN_TRUE;
358 break;
359
360 case IS_STRING:
361 if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0)) {
362 RETURN_TRUE;
363 } else {
364 RETURN_FALSE;
365 }
366 break;
367
368 default:
369 RETURN_FALSE;
370 break;
371 }
372 }
373 /* }}} */
374
375 /* {{{ Returns true if value is a scalar */
PHP_FUNCTION(is_scalar)376 PHP_FUNCTION(is_scalar)
377 {
378 zval *arg;
379
380 ZEND_PARSE_PARAMETERS_START(1, 1)
381 Z_PARAM_ZVAL(arg)
382 ZEND_PARSE_PARAMETERS_END();
383
384 switch (Z_TYPE_P(arg)) {
385 case IS_FALSE:
386 case IS_TRUE:
387 case IS_DOUBLE:
388 case IS_LONG:
389 case IS_STRING:
390 RETURN_TRUE;
391 break;
392
393 default:
394 RETURN_FALSE;
395 break;
396 }
397 }
398 /* }}} */
399
400 /* {{{ Returns true if var is callable. */
PHP_FUNCTION(is_callable)401 PHP_FUNCTION(is_callable)
402 {
403 zval *var, *callable_name = NULL;
404 zend_string *name;
405 bool retval;
406 bool syntax_only = 0;
407 int check_flags = 0;
408
409 ZEND_PARSE_PARAMETERS_START(1, 3)
410 Z_PARAM_ZVAL(var)
411 Z_PARAM_OPTIONAL
412 Z_PARAM_BOOL(syntax_only)
413 Z_PARAM_ZVAL(callable_name)
414 ZEND_PARSE_PARAMETERS_END();
415
416 if (syntax_only) {
417 check_flags |= IS_CALLABLE_CHECK_SYNTAX_ONLY;
418 }
419 if (ZEND_NUM_ARGS() > 2) {
420 retval = zend_is_callable_ex(var, NULL, check_flags, &name, NULL, NULL);
421 ZEND_TRY_ASSIGN_REF_STR(callable_name, name);
422 } else {
423 retval = zend_is_callable_ex(var, NULL, check_flags, NULL, NULL, NULL);
424 }
425
426 RETURN_BOOL(retval);
427 }
428 /* }}} */
429
430 /* {{{ Returns true if var is iterable (array or instance of Traversable). */
PHP_FUNCTION(is_iterable)431 PHP_FUNCTION(is_iterable)
432 {
433 zval *var;
434
435 ZEND_PARSE_PARAMETERS_START(1, 1)
436 Z_PARAM_ZVAL(var)
437 ZEND_PARSE_PARAMETERS_END();
438
439 RETURN_BOOL(zend_is_iterable(var));
440 }
441 /* }}} */
442
443 /* {{{ Returns true if var is countable (array or instance of Countable). */
PHP_FUNCTION(is_countable)444 PHP_FUNCTION(is_countable)
445 {
446 zval *var;
447
448 ZEND_PARSE_PARAMETERS_START(1, 1)
449 Z_PARAM_ZVAL(var)
450 ZEND_PARSE_PARAMETERS_END();
451
452 RETURN_BOOL(zend_is_countable(var));
453 }
454 /* }}} */
455