1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 +----------------------------------------------------------------------+
18 */
19
20 /* $Id$ */
21
22 #include <ctype.h>
23
24 #include "zend.h"
25 #include "zend_operators.h"
26 #include "zend_variables.h"
27 #include "zend_globals.h"
28 #include "zend_list.h"
29 #include "zend_API.h"
30 #include "zend_strtod.h"
31 #include "zend_exceptions.h"
32 #include "zend_closures.h"
33
34 #if ZEND_USE_TOLOWER_L
35 #include <locale.h>
36 static _locale_t current_locale = NULL;
37 /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
38 #define zend_tolower(c) _tolower_l(c, current_locale)
39 #else
40 #define zend_tolower(c) tolower(c)
41 #endif
42
43 #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
44
45 static const unsigned char tolower_map[256] = {
46 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
47 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
48 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
49 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
50 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
51 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
52 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
53 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
54 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
55 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
56 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
57 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
58 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
59 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
60 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
61 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
62 };
63
64 #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)])
65
66 /**
67 * Functions using locale lowercase:
68 zend_binary_strncasecmp_l
69 zend_binary_strcasecmp_l
70 zend_binary_zval_strcasecmp
71 zend_binary_zval_strncasecmp
72 string_compare_function_ex
73 string_case_compare_function
74 * Functions using ascii lowercase:
75 zend_str_tolower_copy
76 zend_str_tolower_dup
77 zend_str_tolower
78 zend_binary_strcasecmp
79 zend_binary_strncasecmp
80 */
81
zend_atoi(const char * str,int str_len)82 ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
83 {
84 int retval;
85
86 if (!str_len) {
87 str_len = strlen(str);
88 }
89 retval = strtol(str, NULL, 0);
90 if (str_len>0) {
91 switch (str[str_len-1]) {
92 case 'g':
93 case 'G':
94 retval *= 1024;
95 /* break intentionally missing */
96 case 'm':
97 case 'M':
98 retval *= 1024;
99 /* break intentionally missing */
100 case 'k':
101 case 'K':
102 retval *= 1024;
103 break;
104 }
105 }
106 return retval;
107 }
108 /* }}} */
109
zend_atol(const char * str,int str_len)110 ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
111 {
112 long retval;
113
114 if (!str_len) {
115 str_len = strlen(str);
116 }
117 retval = strtol(str, NULL, 0);
118 if (str_len>0) {
119 switch (str[str_len-1]) {
120 case 'g':
121 case 'G':
122 retval *= 1024;
123 /* break intentionally missing */
124 case 'm':
125 case 'M':
126 retval *= 1024;
127 /* break intentionally missing */
128 case 'k':
129 case 'K':
130 retval *= 1024;
131 break;
132 }
133 }
134 return retval;
135 }
136 /* }}} */
137
zend_string_to_double(const char * number,zend_uint length)138 ZEND_API double zend_string_to_double(const char *number, zend_uint length) /* {{{ */
139 {
140 double divisor = 10.0;
141 double result = 0.0;
142 double exponent;
143 const char *end = number+length;
144 const char *digit = number;
145
146 if (!length) {
147 return result;
148 }
149
150 while (digit < end) {
151 if ((*digit <= '9' && *digit >= '0')) {
152 result *= 10;
153 result += *digit - '0';
154 } else if (*digit == '.') {
155 digit++;
156 break;
157 } else if (toupper(*digit) == 'E') {
158 exponent = (double) atoi(digit+1);
159 result *= pow(10.0, exponent);
160 return result;
161 } else {
162 return result;
163 }
164 digit++;
165 }
166
167 while (digit < end) {
168 if ((*digit <= '9' && *digit >= '0')) {
169 result += (*digit - '0') / divisor;
170 divisor *= 10;
171 } else if (toupper(*digit) == 'E') {
172 exponent = (double) atoi(digit+1);
173 result *= pow(10.0, exponent);
174 return result;
175 } else {
176 return result;
177 }
178 digit++;
179 }
180 return result;
181 }
182 /* }}} */
183
convert_scalar_to_number(zval * op TSRMLS_DC)184 ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
185 {
186 switch (Z_TYPE_P(op)) {
187 case IS_STRING:
188 {
189 char *strval;
190
191 strval = Z_STRVAL_P(op);
192 if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
193 ZVAL_LONG(op, 0);
194 }
195 STR_FREE(strval);
196 break;
197 }
198 case IS_BOOL:
199 Z_TYPE_P(op) = IS_LONG;
200 break;
201 case IS_RESOURCE:
202 zend_list_delete(Z_LVAL_P(op));
203 Z_TYPE_P(op) = IS_LONG;
204 break;
205 case IS_OBJECT:
206 convert_to_long_base(op, 10);
207 break;
208 case IS_NULL:
209 ZVAL_LONG(op, 0);
210 break;
211 }
212 }
213 /* }}} */
214
215 /* {{{ zendi_convert_scalar_to_number */
216 #define zendi_convert_scalar_to_number(op, holder, result) \
217 if (op==result) { \
218 if (Z_TYPE_P(op) != IS_LONG) { \
219 convert_scalar_to_number(op TSRMLS_CC); \
220 } \
221 } else { \
222 switch (Z_TYPE_P(op)) { \
223 case IS_STRING: \
224 { \
225 if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
226 ZVAL_LONG(&(holder), 0); \
227 } \
228 (op) = &(holder); \
229 break; \
230 } \
231 case IS_BOOL: \
232 case IS_RESOURCE: \
233 ZVAL_LONG(&(holder), Z_LVAL_P(op)); \
234 (op) = &(holder); \
235 break; \
236 case IS_NULL: \
237 ZVAL_LONG(&(holder), 0); \
238 (op) = &(holder); \
239 break; \
240 case IS_OBJECT: \
241 (holder) = (*(op)); \
242 zval_copy_ctor(&(holder)); \
243 convert_to_long_base(&(holder), 10); \
244 if (Z_TYPE(holder) == IS_LONG) { \
245 (op) = &(holder); \
246 } \
247 break; \
248 } \
249 }
250
251 /* }}} */
252
253 /* {{{ zendi_convert_to_long */
254 #define zendi_convert_to_long(op, holder, result) \
255 if (op == result) { \
256 convert_to_long(op); \
257 } else if (Z_TYPE_P(op) != IS_LONG) { \
258 switch (Z_TYPE_P(op)) { \
259 case IS_NULL: \
260 Z_LVAL(holder) = 0; \
261 break; \
262 case IS_DOUBLE: \
263 Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
264 break; \
265 case IS_STRING: \
266 Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
267 break; \
268 case IS_ARRAY: \
269 Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
270 break; \
271 case IS_OBJECT: \
272 (holder) = (*(op)); \
273 zval_copy_ctor(&(holder)); \
274 convert_to_long_base(&(holder), 10); \
275 break; \
276 case IS_BOOL: \
277 case IS_RESOURCE: \
278 Z_LVAL(holder) = Z_LVAL_P(op); \
279 break; \
280 default: \
281 zend_error(E_WARNING, "Cannot convert to ordinal value"); \
282 Z_LVAL(holder) = 0; \
283 break; \
284 } \
285 Z_TYPE(holder) = IS_LONG; \
286 (op) = &(holder); \
287 }
288
289 /* }}} */
290
291 /* {{{ zendi_convert_to_boolean */
292 #define zendi_convert_to_boolean(op, holder, result) \
293 if (op==result) { \
294 convert_to_boolean(op); \
295 } else if (Z_TYPE_P(op) != IS_BOOL) { \
296 switch (Z_TYPE_P(op)) { \
297 case IS_NULL: \
298 Z_LVAL(holder) = 0; \
299 break; \
300 case IS_RESOURCE: \
301 case IS_LONG: \
302 Z_LVAL(holder) = (Z_LVAL_P(op) ? 1 : 0); \
303 break; \
304 case IS_DOUBLE: \
305 Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
306 break; \
307 case IS_STRING: \
308 if (Z_STRLEN_P(op) == 0 \
309 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
310 Z_LVAL(holder) = 0; \
311 } else { \
312 Z_LVAL(holder) = 1; \
313 } \
314 break; \
315 case IS_ARRAY: \
316 Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
317 break; \
318 case IS_OBJECT: \
319 (holder) = (*(op)); \
320 zval_copy_ctor(&(holder)); \
321 convert_to_boolean(&(holder)); \
322 break; \
323 default: \
324 Z_LVAL(holder) = 0; \
325 break; \
326 } \
327 Z_TYPE(holder) = IS_BOOL; \
328 (op) = &(holder); \
329 }
330
331 /* }}} */
332
333 /* {{{ convert_object_to_type */
334 #define convert_object_to_type(op, ctype, conv_func) \
335 if (Z_OBJ_HT_P(op)->cast_object) { \
336 zval dst; \
337 if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) { \
338 zend_error(E_RECOVERABLE_ERROR, \
339 "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name, \
340 zend_get_type_by_const(ctype)); \
341 } else { \
342 zval_dtor(op); \
343 Z_TYPE_P(op) = ctype; \
344 op->value = dst.value; \
345 } \
346 } else { \
347 if (Z_OBJ_HT_P(op)->get) { \
348 zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
349 if (Z_TYPE_P(newop) != IS_OBJECT) { \
350 /* for safety - avoid loop */ \
351 zval_dtor(op); \
352 *op = *newop; \
353 FREE_ZVAL(newop); \
354 conv_func(op); \
355 } \
356 } \
357 }
358
359 /* }}} */
360
convert_to_long(zval * op)361 ZEND_API void convert_to_long(zval *op) /* {{{ */
362 {
363 if (Z_TYPE_P(op) != IS_LONG) {
364 convert_to_long_base(op, 10);
365 }
366 }
367 /* }}} */
368
convert_to_long_base(zval * op,int base)369 ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
370 {
371 long tmp;
372
373 switch (Z_TYPE_P(op)) {
374 case IS_NULL:
375 Z_LVAL_P(op) = 0;
376 break;
377 case IS_RESOURCE: {
378 TSRMLS_FETCH();
379
380 zend_list_delete(Z_LVAL_P(op));
381 }
382 /* break missing intentionally */
383 case IS_BOOL:
384 case IS_LONG:
385 break;
386 case IS_DOUBLE:
387 Z_LVAL_P(op) = zend_dval_to_lval(Z_DVAL_P(op));
388 break;
389 case IS_STRING:
390 {
391 char *strval = Z_STRVAL_P(op);
392
393 Z_LVAL_P(op) = strtol(strval, NULL, base);
394 STR_FREE(strval);
395 }
396 break;
397 case IS_ARRAY:
398 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
399 zval_dtor(op);
400 Z_LVAL_P(op) = tmp;
401 break;
402 case IS_OBJECT:
403 {
404 int retval = 1;
405 TSRMLS_FETCH();
406
407 convert_object_to_type(op, IS_LONG, convert_to_long);
408
409 if (Z_TYPE_P(op) == IS_LONG) {
410 return;
411 }
412 zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
413
414 zval_dtor(op);
415 ZVAL_LONG(op, retval);
416 return;
417 }
418 default:
419 zend_error(E_WARNING, "Cannot convert to ordinal value");
420 zval_dtor(op);
421 Z_LVAL_P(op) = 0;
422 break;
423 }
424
425 Z_TYPE_P(op) = IS_LONG;
426 }
427 /* }}} */
428
convert_to_double(zval * op)429 ZEND_API void convert_to_double(zval *op) /* {{{ */
430 {
431 double tmp;
432
433 switch (Z_TYPE_P(op)) {
434 case IS_NULL:
435 Z_DVAL_P(op) = 0.0;
436 break;
437 case IS_RESOURCE: {
438 TSRMLS_FETCH();
439
440 zend_list_delete(Z_LVAL_P(op));
441 }
442 /* break missing intentionally */
443 case IS_BOOL:
444 case IS_LONG:
445 Z_DVAL_P(op) = (double) Z_LVAL_P(op);
446 break;
447 case IS_DOUBLE:
448 break;
449 case IS_STRING:
450 {
451 char *strval = Z_STRVAL_P(op);
452
453 Z_DVAL_P(op) = zend_strtod(strval, NULL);
454 STR_FREE(strval);
455 }
456 break;
457 case IS_ARRAY:
458 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
459 zval_dtor(op);
460 Z_DVAL_P(op) = tmp;
461 break;
462 case IS_OBJECT:
463 {
464 double retval = 1.0;
465 TSRMLS_FETCH();
466
467 convert_object_to_type(op, IS_DOUBLE, convert_to_double);
468
469 if (Z_TYPE_P(op) == IS_DOUBLE) {
470 return;
471 }
472 zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
473
474 zval_dtor(op);
475 ZVAL_DOUBLE(op, retval);
476 break;
477 }
478 default:
479 zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op));
480 zval_dtor(op);
481 Z_DVAL_P(op) = 0;
482 break;
483 }
484 Z_TYPE_P(op) = IS_DOUBLE;
485 }
486 /* }}} */
487
convert_to_null(zval * op)488 ZEND_API void convert_to_null(zval *op) /* {{{ */
489 {
490 if (Z_TYPE_P(op) == IS_OBJECT) {
491 if (Z_OBJ_HT_P(op)->cast_object) {
492 zval *org;
493 TSRMLS_FETCH();
494
495 ALLOC_ZVAL(org);
496 *org = *op;
497 if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
498 zval_dtor(org);
499 return;
500 }
501 *op = *org;
502 FREE_ZVAL(org);
503 }
504 }
505
506 zval_dtor(op);
507 Z_TYPE_P(op) = IS_NULL;
508 }
509 /* }}} */
510
convert_to_boolean(zval * op)511 ZEND_API void convert_to_boolean(zval *op) /* {{{ */
512 {
513 int tmp;
514
515 switch (Z_TYPE_P(op)) {
516 case IS_BOOL:
517 break;
518 case IS_NULL:
519 Z_LVAL_P(op) = 0;
520 break;
521 case IS_RESOURCE: {
522 TSRMLS_FETCH();
523
524 zend_list_delete(Z_LVAL_P(op));
525 }
526 /* break missing intentionally */
527 case IS_LONG:
528 Z_LVAL_P(op) = (Z_LVAL_P(op) ? 1 : 0);
529 break;
530 case IS_DOUBLE:
531 Z_LVAL_P(op) = (Z_DVAL_P(op) ? 1 : 0);
532 break;
533 case IS_STRING:
534 {
535 char *strval = Z_STRVAL_P(op);
536
537 if (Z_STRLEN_P(op) == 0
538 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
539 Z_LVAL_P(op) = 0;
540 } else {
541 Z_LVAL_P(op) = 1;
542 }
543 STR_FREE(strval);
544 }
545 break;
546 case IS_ARRAY:
547 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
548 zval_dtor(op);
549 Z_LVAL_P(op) = tmp;
550 break;
551 case IS_OBJECT:
552 {
553 zend_bool retval = 1;
554 TSRMLS_FETCH();
555
556 convert_object_to_type(op, IS_BOOL, convert_to_boolean);
557
558 if (Z_TYPE_P(op) == IS_BOOL) {
559 return;
560 }
561
562 zval_dtor(op);
563 ZVAL_BOOL(op, retval);
564 break;
565 }
566 default:
567 zval_dtor(op);
568 Z_LVAL_P(op) = 0;
569 break;
570 }
571 Z_TYPE_P(op) = IS_BOOL;
572 }
573 /* }}} */
574
_convert_to_cstring(zval * op ZEND_FILE_LINE_DC)575 ZEND_API void _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {{{ */
576 {
577 double dval;
578 switch (Z_TYPE_P(op)) {
579 case IS_DOUBLE: {
580 TSRMLS_FETCH();
581 dval = Z_DVAL_P(op);
582 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*H", (int) EG(precision), dval);
583 /* %H already handles removing trailing zeros from the fractional part, yay */
584 break;
585 }
586 default:
587 _convert_to_string(op ZEND_FILE_LINE_CC);
588 }
589 Z_TYPE_P(op) = IS_STRING;
590 }
591 /* }}} */
592
_convert_to_string(zval * op ZEND_FILE_LINE_DC)593 ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
594 {
595 long lval;
596 double dval;
597
598 switch (Z_TYPE_P(op)) {
599 case IS_NULL:
600 Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
601 Z_STRLEN_P(op) = 0;
602 break;
603 case IS_STRING:
604 break;
605 case IS_BOOL:
606 if (Z_LVAL_P(op)) {
607 Z_STRVAL_P(op) = estrndup_rel("1", 1);
608 Z_STRLEN_P(op) = 1;
609 } else {
610 Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
611 Z_STRLEN_P(op) = 0;
612 }
613 break;
614 case IS_RESOURCE: {
615 long tmp = Z_LVAL_P(op);
616 TSRMLS_FETCH();
617
618 zend_list_delete(Z_LVAL_P(op));
619 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "Resource id #%ld", tmp);
620 break;
621 }
622 case IS_LONG:
623 lval = Z_LVAL_P(op);
624
625 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%ld", lval);
626 break;
627 case IS_DOUBLE: {
628 TSRMLS_FETCH();
629 dval = Z_DVAL_P(op);
630 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), dval);
631 /* %G already handles removing trailing zeros from the fractional part, yay */
632 break;
633 }
634 case IS_ARRAY:
635 zend_error(E_NOTICE, "Array to string conversion");
636 zval_dtor(op);
637 Z_STRVAL_P(op) = estrndup_rel("Array", sizeof("Array")-1);
638 Z_STRLEN_P(op) = sizeof("Array")-1;
639 break;
640 case IS_OBJECT: {
641 TSRMLS_FETCH();
642
643 convert_object_to_type(op, IS_STRING, convert_to_string);
644
645 if (Z_TYPE_P(op) == IS_STRING) {
646 return;
647 }
648
649 zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
650 zval_dtor(op);
651 Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
652 Z_STRLEN_P(op) = sizeof("Object")-1;
653 break;
654 }
655 default:
656 zval_dtor(op);
657 ZVAL_BOOL(op, 0);
658 break;
659 }
660 Z_TYPE_P(op) = IS_STRING;
661 }
662 /* }}} */
663
convert_scalar_to_array(zval * op,int type TSRMLS_DC)664 static void convert_scalar_to_array(zval *op, int type TSRMLS_DC) /* {{{ */
665 {
666 zval *entry;
667
668 ALLOC_ZVAL(entry);
669 *entry = *op;
670 INIT_PZVAL(entry);
671
672 switch (type) {
673 case IS_ARRAY:
674 ALLOC_HASHTABLE(Z_ARRVAL_P(op));
675 zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
676 zend_hash_index_update(Z_ARRVAL_P(op), 0, (void *) &entry, sizeof(zval *), NULL);
677 Z_TYPE_P(op) = IS_ARRAY;
678 break;
679 case IS_OBJECT:
680 object_init(op);
681 zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
682 break;
683 }
684 }
685 /* }}} */
686
convert_to_array(zval * op)687 ZEND_API void convert_to_array(zval *op) /* {{{ */
688 {
689 TSRMLS_FETCH();
690
691 switch (Z_TYPE_P(op)) {
692 case IS_ARRAY:
693 break;
694 /* OBJECTS_OPTIMIZE */
695 case IS_OBJECT:
696 {
697 zval *tmp;
698 HashTable *ht;
699
700 ALLOC_HASHTABLE(ht);
701 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
702 if (Z_OBJCE_P(op) == zend_ce_closure) {
703 convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
704 if (Z_TYPE_P(op) == IS_ARRAY) {
705 zend_hash_destroy(ht);
706 FREE_HASHTABLE(ht);
707 return;
708 }
709 } else if (Z_OBJ_HT_P(op)->get_properties) {
710 HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
711 if (obj_ht) {
712 zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
713 }
714 } else {
715 convert_object_to_type(op, IS_ARRAY, convert_to_array);
716
717 if (Z_TYPE_P(op) == IS_ARRAY) {
718 zend_hash_destroy(ht);
719 FREE_HASHTABLE(ht);
720 return;
721 }
722 }
723 zval_dtor(op);
724 Z_TYPE_P(op) = IS_ARRAY;
725 Z_ARRVAL_P(op) = ht;
726 }
727 break;
728 case IS_NULL:
729 ALLOC_HASHTABLE(Z_ARRVAL_P(op));
730 zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
731 Z_TYPE_P(op) = IS_ARRAY;
732 break;
733 default:
734 convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
735 break;
736 }
737 }
738 /* }}} */
739
convert_to_object(zval * op)740 ZEND_API void convert_to_object(zval *op) /* {{{ */
741 {
742 TSRMLS_FETCH();
743
744 switch (Z_TYPE_P(op)) {
745 case IS_ARRAY:
746 {
747 object_and_properties_init(op, zend_standard_class_def, Z_ARRVAL_P(op));
748 break;
749 }
750 case IS_OBJECT:
751 break;
752 case IS_NULL:
753 object_init(op);
754 break;
755 default:
756 convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
757 break;
758 }
759 }
760 /* }}} */
761
multi_convert_to_long_ex(int argc,...)762 ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
763 {
764 zval **arg;
765 va_list ap;
766
767 va_start(ap, argc);
768
769 while (argc--) {
770 arg = va_arg(ap, zval **);
771 convert_to_long_ex(arg);
772 }
773
774 va_end(ap);
775 }
776 /* }}} */
777
multi_convert_to_double_ex(int argc,...)778 ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
779 {
780 zval **arg;
781 va_list ap;
782
783 va_start(ap, argc);
784
785 while (argc--) {
786 arg = va_arg(ap, zval **);
787 convert_to_double_ex(arg);
788 }
789
790 va_end(ap);
791 }
792 /* }}} */
793
multi_convert_to_string_ex(int argc,...)794 ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
795 {
796 zval **arg;
797 va_list ap;
798
799 va_start(ap, argc);
800
801 while (argc--) {
802 arg = va_arg(ap, zval **);
803 convert_to_string_ex(arg);
804 }
805
806 va_end(ap);
807 }
808 /* }}} */
809
add_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)810 ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
811 {
812 zval op1_copy, op2_copy;
813 int converted = 0;
814
815 while (1) {
816 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
817 case TYPE_PAIR(IS_LONG, IS_LONG): {
818 long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
819
820 /* check for overflow by comparing sign bits */
821 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
822 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
823
824 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
825 } else {
826 ZVAL_LONG(result, lval);
827 }
828 return SUCCESS;
829 }
830
831 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
832 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
833 return SUCCESS;
834
835 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
836 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
837 return SUCCESS;
838
839 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
840 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
841 return SUCCESS;
842
843 case TYPE_PAIR(IS_ARRAY, IS_ARRAY): {
844 zval *tmp;
845
846 if ((result == op1) && (result == op2)) {
847 /* $a += $a */
848 return SUCCESS;
849 }
850 if (result != op1) {
851 *result = *op1;
852 zval_copy_ctor(result);
853 }
854 zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
855 return SUCCESS;
856 }
857
858 default:
859 if (!converted) {
860 zendi_convert_scalar_to_number(op1, op1_copy, result);
861 zendi_convert_scalar_to_number(op2, op2_copy, result);
862 converted = 1;
863 } else {
864 zend_error(E_ERROR, "Unsupported operand types");
865 return FAILURE; /* unknown datatype */
866 }
867 }
868 }
869 }
870 /* }}} */
871
sub_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)872 ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
873 {
874 zval op1_copy, op2_copy;
875 int converted = 0;
876
877 while (1) {
878 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
879 case TYPE_PAIR(IS_LONG, IS_LONG): {
880 long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
881
882 /* check for overflow by comparing sign bits */
883 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
884 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
885
886 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
887 } else {
888 ZVAL_LONG(result, lval);
889 }
890 return SUCCESS;
891
892 }
893 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
894 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
895 return SUCCESS;
896
897 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
898 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
899 return SUCCESS;
900
901 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
902 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
903 return SUCCESS;
904
905 default:
906 if (!converted) {
907 zendi_convert_scalar_to_number(op1, op1_copy, result);
908 zendi_convert_scalar_to_number(op2, op2_copy, result);
909 converted = 1;
910 } else {
911 zend_error(E_ERROR, "Unsupported operand types");
912 return FAILURE; /* unknown datatype */
913 }
914 }
915 }
916 }
917 /* }}} */
918
mul_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)919 ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
920 {
921 zval op1_copy, op2_copy;
922 int converted = 0;
923
924 while (1) {
925 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
926 case TYPE_PAIR(IS_LONG, IS_LONG): {
927 long overflow;
928
929 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
930 Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
931 return SUCCESS;
932
933 }
934 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
935 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
936 return SUCCESS;
937
938 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
939 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
940 return SUCCESS;
941
942 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
943 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
944 return SUCCESS;
945
946 default:
947 if (!converted) {
948 zendi_convert_scalar_to_number(op1, op1_copy, result);
949 zendi_convert_scalar_to_number(op2, op2_copy, result);
950 converted = 1;
951 } else {
952 zend_error(E_ERROR, "Unsupported operand types");
953 return FAILURE; /* unknown datatype */
954 }
955 }
956 }
957 }
958 /* }}} */
959
div_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)960 ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
961 {
962 zval op1_copy, op2_copy;
963 int converted = 0;
964
965 while (1) {
966 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
967 case TYPE_PAIR(IS_LONG, IS_LONG):
968 if (Z_LVAL_P(op2) == 0) {
969 zend_error(E_WARNING, "Division by zero");
970 ZVAL_BOOL(result, 0);
971 return FAILURE; /* division by zero */
972 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
973 /* Prevent overflow error/crash */
974 ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
975 return SUCCESS;
976 }
977 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
978 ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
979 } else {
980 ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
981 }
982 return SUCCESS;
983
984 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
985 if (Z_LVAL_P(op2) == 0) {
986 zend_error(E_WARNING, "Division by zero");
987 ZVAL_BOOL(result, 0);
988 return FAILURE; /* division by zero */
989 }
990 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
991 return SUCCESS;
992
993 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
994 if (Z_DVAL_P(op2) == 0) {
995 zend_error(E_WARNING, "Division by zero");
996 ZVAL_BOOL(result, 0);
997 return FAILURE; /* division by zero */
998 }
999 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1000 return SUCCESS;
1001
1002 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1003 if (Z_DVAL_P(op2) == 0) {
1004 zend_error(E_WARNING, "Division by zero");
1005 ZVAL_BOOL(result, 0);
1006 return FAILURE; /* division by zero */
1007 }
1008 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1009 return SUCCESS;
1010
1011 default:
1012 if (!converted) {
1013 zendi_convert_scalar_to_number(op1, op1_copy, result);
1014 zendi_convert_scalar_to_number(op2, op2_copy, result);
1015 converted = 1;
1016 } else {
1017 zend_error(E_ERROR, "Unsupported operand types");
1018 return FAILURE; /* unknown datatype */
1019 }
1020 }
1021 }
1022 }
1023 /* }}} */
1024
mod_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1025 ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1026 {
1027 zval op1_copy, op2_copy;
1028 long op1_lval;
1029
1030 zendi_convert_to_long(op1, op1_copy, result);
1031 op1_lval = Z_LVAL_P(op1);
1032 zendi_convert_to_long(op2, op2_copy, result);
1033
1034 if (Z_LVAL_P(op2) == 0) {
1035 zend_error(E_WARNING, "Division by zero");
1036 ZVAL_BOOL(result, 0);
1037 return FAILURE; /* modulus by zero */
1038 }
1039
1040 if (Z_LVAL_P(op2) == -1) {
1041 /* Prevent overflow error/crash if op1==LONG_MIN */
1042 ZVAL_LONG(result, 0);
1043 return SUCCESS;
1044 }
1045
1046 ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2));
1047 return SUCCESS;
1048 }
1049 /* }}} */
1050
boolean_xor_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1051 ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1052 {
1053 zval op1_copy, op2_copy;
1054 long op1_lval;
1055
1056 zendi_convert_to_boolean(op1, op1_copy, result);
1057 op1_lval = Z_LVAL_P(op1);
1058 zendi_convert_to_boolean(op2, op2_copy, result);
1059 ZVAL_BOOL(result, op1_lval ^ Z_LVAL_P(op2));
1060 return SUCCESS;
1061 }
1062 /* }}} */
1063
boolean_not_function(zval * result,zval * op1 TSRMLS_DC)1064 ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1065 {
1066 zval op1_copy;
1067
1068 zendi_convert_to_boolean(op1, op1_copy, result);
1069 ZVAL_BOOL(result, !Z_LVAL_P(op1));
1070 return SUCCESS;
1071 }
1072 /* }}} */
1073
bitwise_not_function(zval * result,zval * op1 TSRMLS_DC)1074 ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1075 {
1076 zval op1_copy = *op1;
1077
1078 op1 = &op1_copy;
1079
1080 if (Z_TYPE_P(op1) == IS_LONG) {
1081 ZVAL_LONG(result, ~Z_LVAL_P(op1));
1082 return SUCCESS;
1083 } else if (Z_TYPE_P(op1) == IS_DOUBLE) {
1084 ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1085 return SUCCESS;
1086 } else if (Z_TYPE_P(op1) == IS_STRING) {
1087 int i;
1088
1089 Z_TYPE_P(result) = IS_STRING;
1090 Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1091 Z_STRLEN_P(result) = Z_STRLEN_P(op1);
1092 for (i = 0; i < Z_STRLEN_P(op1); i++) {
1093 Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1094 }
1095 return SUCCESS;
1096 }
1097 zend_error(E_ERROR, "Unsupported operand types");
1098 return FAILURE; /* unknown datatype */
1099 }
1100 /* }}} */
1101
bitwise_or_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1102 ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1103 {
1104 zval op1_copy, op2_copy;
1105 long op1_lval;
1106
1107 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1108 zval *longer, *shorter;
1109 char *result_str;
1110 int i, result_len;
1111
1112 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1113 longer = op1;
1114 shorter = op2;
1115 } else {
1116 longer = op2;
1117 shorter = op1;
1118 }
1119
1120 Z_TYPE_P(result) = IS_STRING;
1121 result_len = Z_STRLEN_P(longer);
1122 result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer));
1123 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1124 result_str[i] |= Z_STRVAL_P(shorter)[i];
1125 }
1126 if (result==op1) {
1127 STR_FREE(Z_STRVAL_P(result));
1128 }
1129 Z_STRVAL_P(result) = result_str;
1130 Z_STRLEN_P(result) = result_len;
1131 return SUCCESS;
1132 }
1133 zendi_convert_to_long(op1, op1_copy, result);
1134 op1_lval = Z_LVAL_P(op1);
1135 zendi_convert_to_long(op2, op2_copy, result);
1136
1137 ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
1138 return SUCCESS;
1139 }
1140 /* }}} */
1141
bitwise_and_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1142 ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1143 {
1144 zval op1_copy, op2_copy;
1145 long op1_lval;
1146
1147 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1148 zval *longer, *shorter;
1149 char *result_str;
1150 int i, result_len;
1151
1152 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1153 longer = op1;
1154 shorter = op2;
1155 } else {
1156 longer = op2;
1157 shorter = op1;
1158 }
1159
1160 Z_TYPE_P(result) = IS_STRING;
1161 result_len = Z_STRLEN_P(shorter);
1162 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1163 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1164 result_str[i] &= Z_STRVAL_P(longer)[i];
1165 }
1166 if (result==op1) {
1167 STR_FREE(Z_STRVAL_P(result));
1168 }
1169 Z_STRVAL_P(result) = result_str;
1170 Z_STRLEN_P(result) = result_len;
1171 return SUCCESS;
1172 }
1173
1174
1175 zendi_convert_to_long(op1, op1_copy, result);
1176 op1_lval = Z_LVAL_P(op1);
1177 zendi_convert_to_long(op2, op2_copy, result);
1178
1179 ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
1180 return SUCCESS;
1181 }
1182 /* }}} */
1183
bitwise_xor_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1184 ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1185 {
1186 zval op1_copy, op2_copy;
1187 long op1_lval;
1188
1189 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1190 zval *longer, *shorter;
1191 char *result_str;
1192 int i, result_len;
1193
1194 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1195 longer = op1;
1196 shorter = op2;
1197 } else {
1198 longer = op2;
1199 shorter = op1;
1200 }
1201
1202 Z_TYPE_P(result) = IS_STRING;
1203 result_len = Z_STRLEN_P(shorter);
1204 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1205 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1206 result_str[i] ^= Z_STRVAL_P(longer)[i];
1207 }
1208 if (result==op1) {
1209 STR_FREE(Z_STRVAL_P(result));
1210 }
1211 Z_STRVAL_P(result) = result_str;
1212 Z_STRLEN_P(result) = result_len;
1213 return SUCCESS;
1214 }
1215
1216 zendi_convert_to_long(op1, op1_copy, result);
1217 op1_lval = Z_LVAL_P(op1);
1218 zendi_convert_to_long(op2, op2_copy, result);
1219
1220 ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
1221 return SUCCESS;
1222 }
1223 /* }}} */
1224
shift_left_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1225 ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1226 {
1227 zval op1_copy, op2_copy;
1228 long op1_lval;
1229
1230 zendi_convert_to_long(op1, op1_copy, result);
1231 op1_lval = Z_LVAL_P(op1);
1232 zendi_convert_to_long(op2, op2_copy, result);
1233 ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
1234 return SUCCESS;
1235 }
1236 /* }}} */
1237
shift_right_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1238 ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1239 {
1240 zval op1_copy, op2_copy;
1241 long op1_lval;
1242
1243 zendi_convert_to_long(op1, op1_copy, result);
1244 op1_lval = Z_LVAL_P(op1);
1245 zendi_convert_to_long(op2, op2_copy, result);
1246 ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
1247 return SUCCESS;
1248 }
1249 /* }}} */
1250
1251 /* must support result==op1 */
add_char_to_string(zval * result,const zval * op1,const zval * op2)1252 ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1253 {
1254 int length = Z_STRLEN_P(op1) + 1;
1255 char *buf;
1256
1257 if (UNEXPECTED(length < 0)) {
1258 zend_error(E_ERROR, "String size overflow");
1259 }
1260
1261 if (IS_INTERNED(Z_STRVAL_P(op1))) {
1262 buf = (char *) emalloc(length + 1);
1263 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1264 } else {
1265 buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1);
1266 }
1267 buf[length - 1] = (char) Z_LVAL_P(op2);
1268 buf[length] = 0;
1269 ZVAL_STRINGL(result, buf, length, 0);
1270 return SUCCESS;
1271 }
1272 /* }}} */
1273
1274 /* must support result==op1 */
add_string_to_string(zval * result,const zval * op1,const zval * op2)1275 ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1276 {
1277 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1278 char *buf;
1279
1280 if (UNEXPECTED(length < 0)) {
1281 zend_error(E_ERROR, "String size overflow");
1282 }
1283 if (IS_INTERNED(Z_STRVAL_P(op1))) {
1284 buf = (char *) emalloc(length+1);
1285 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1286 } else {
1287 buf = (char *) erealloc(Z_STRVAL_P(op1), length+1);
1288 }
1289 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1290 buf[length] = 0;
1291 ZVAL_STRINGL(result, buf, length, 0);
1292 return SUCCESS;
1293 }
1294 /* }}} */
1295
concat_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1296 ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1297 {
1298 zval op1_copy, op2_copy;
1299 int use_copy1 = 0, use_copy2 = 0;
1300
1301 if (Z_TYPE_P(op1) != IS_STRING) {
1302 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1303 }
1304 if (Z_TYPE_P(op2) != IS_STRING) {
1305 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1306 }
1307
1308 if (use_copy1) {
1309 /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1310 * we have to free it.
1311 */
1312 if (result == op1) {
1313 zval_dtor(op1);
1314 }
1315 op1 = &op1_copy;
1316 }
1317 if (use_copy2) {
1318 op2 = &op2_copy;
1319 }
1320 if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) { /* special case, perform operations on result */
1321 uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1322
1323 if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
1324 efree(Z_STRVAL_P(result));
1325 ZVAL_EMPTY_STRING(result);
1326 zend_error(E_ERROR, "String size overflow");
1327 }
1328
1329 Z_STRVAL_P(result) = safe_erealloc(Z_STRVAL_P(result), res_len, 1, 1);
1330
1331 memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1332 Z_STRVAL_P(result)[res_len]=0;
1333 Z_STRLEN_P(result) = res_len;
1334 } else {
1335 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1336 char *buf;
1337
1338 if (Z_STRLEN_P(op1) < 0 || Z_STRLEN_P(op2) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
1339 zend_error(E_ERROR, "String size overflow");
1340 }
1341 buf = (char *) safe_emalloc(length, 1, 1);
1342
1343 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1344 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1345 buf[length] = 0;
1346 ZVAL_STRINGL(result, buf, length, 0);
1347 }
1348 if (use_copy1) {
1349 zval_dtor(op1);
1350 }
1351 if (use_copy2) {
1352 zval_dtor(op2);
1353 }
1354 return SUCCESS;
1355 }
1356 /* }}} */
1357
string_compare_function_ex(zval * result,zval * op1,zval * op2,zend_bool case_insensitive TSRMLS_DC)1358 ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */
1359 {
1360 zval op1_copy, op2_copy;
1361 int use_copy1 = 0, use_copy2 = 0;
1362
1363 if (Z_TYPE_P(op1) != IS_STRING) {
1364 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1365 }
1366 if (Z_TYPE_P(op2) != IS_STRING) {
1367 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1368 }
1369
1370 if (use_copy1) {
1371 op1 = &op1_copy;
1372 }
1373 if (use_copy2) {
1374 op2 = &op2_copy;
1375 }
1376
1377 if (case_insensitive) {
1378 ZVAL_LONG(result, zend_binary_zval_strcasecmp(op1, op2));
1379 } else {
1380 ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
1381 }
1382
1383 if (use_copy1) {
1384 zval_dtor(op1);
1385 }
1386 if (use_copy2) {
1387 zval_dtor(op2);
1388 }
1389 return SUCCESS;
1390 }
1391 /* }}} */
1392
string_compare_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1393 ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1394 {
1395 return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC);
1396 }
1397 /* }}} */
1398
string_case_compare_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1399 ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1400 {
1401 return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC);
1402 }
1403 /* }}} */
1404
1405 #if HAVE_STRCOLL
string_locale_compare_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1406 ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1407 {
1408 zval op1_copy, op2_copy;
1409 int use_copy1 = 0, use_copy2 = 0;
1410
1411 if (Z_TYPE_P(op1) != IS_STRING) {
1412 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1413 }
1414 if (Z_TYPE_P(op2) != IS_STRING) {
1415 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1416 }
1417
1418 if (use_copy1) {
1419 op1 = &op1_copy;
1420 }
1421 if (use_copy2) {
1422 op2 = &op2_copy;
1423 }
1424
1425 ZVAL_LONG(result, strcoll(Z_STRVAL_P(op1), Z_STRVAL_P(op2)));
1426
1427 if (use_copy1) {
1428 zval_dtor(op1);
1429 }
1430 if (use_copy2) {
1431 zval_dtor(op2);
1432 }
1433 return SUCCESS;
1434 }
1435 /* }}} */
1436 #endif
1437
numeric_compare_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1438 ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1439 {
1440 zval op1_copy, op2_copy;
1441
1442 op1_copy = *op1;
1443 zval_copy_ctor(&op1_copy);
1444
1445 op2_copy = *op2;
1446 zval_copy_ctor(&op2_copy);
1447
1448 convert_to_double(&op1_copy);
1449 convert_to_double(&op2_copy);
1450
1451 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
1452
1453 return SUCCESS;
1454 }
1455 /* }}} */
1456
zend_free_obj_get_result(zval * op TSRMLS_DC)1457 static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */
1458 {
1459 if (Z_REFCOUNT_P(op) == 0) {
1460 GC_REMOVE_ZVAL_FROM_BUFFER(op);
1461 zval_dtor(op);
1462 FREE_ZVAL(op);
1463 } else {
1464 zval_ptr_dtor(&op);
1465 }
1466 }
1467 /* }}} */
1468
compare_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1469 ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1470 {
1471 int ret;
1472 int converted = 0;
1473 zval op1_copy, op2_copy;
1474 zval *op_free;
1475
1476 while (1) {
1477 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1478 case TYPE_PAIR(IS_LONG, IS_LONG):
1479 ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1480 return SUCCESS;
1481
1482 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1483 Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1484 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1485 return SUCCESS;
1486
1487 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1488 Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1489 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1490 return SUCCESS;
1491
1492 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1493 if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
1494 ZVAL_LONG(result, 0);
1495 } else {
1496 Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1497 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1498 }
1499 return SUCCESS;
1500
1501 case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1502 zend_compare_arrays(result, op1, op2 TSRMLS_CC);
1503 return SUCCESS;
1504
1505 case TYPE_PAIR(IS_NULL, IS_NULL):
1506 ZVAL_LONG(result, 0);
1507 return SUCCESS;
1508
1509 case TYPE_PAIR(IS_NULL, IS_BOOL):
1510 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1511 return SUCCESS;
1512
1513 case TYPE_PAIR(IS_BOOL, IS_NULL):
1514 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1515 return SUCCESS;
1516
1517 case TYPE_PAIR(IS_BOOL, IS_BOOL):
1518 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1519 return SUCCESS;
1520
1521 case TYPE_PAIR(IS_STRING, IS_STRING):
1522 zendi_smart_strcmp(result, op1, op2);
1523 return SUCCESS;
1524
1525 case TYPE_PAIR(IS_NULL, IS_STRING):
1526 ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1527 return SUCCESS;
1528
1529 case TYPE_PAIR(IS_STRING, IS_NULL):
1530 ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
1531 return SUCCESS;
1532
1533 case TYPE_PAIR(IS_OBJECT, IS_NULL):
1534 ZVAL_LONG(result, 1);
1535 return SUCCESS;
1536
1537 case TYPE_PAIR(IS_NULL, IS_OBJECT):
1538 ZVAL_LONG(result, -1);
1539 return SUCCESS;
1540
1541 case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
1542 /* If both are objects sharing the same comparision handler then use is */
1543 if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {
1544 if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
1545 /* object handles are identical, apparently this is the same object */
1546 ZVAL_LONG(result, 0);
1547 return SUCCESS;
1548 }
1549 ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
1550 return SUCCESS;
1551 }
1552 /* break missing intentionally */
1553
1554 default:
1555 if (Z_TYPE_P(op1) == IS_OBJECT) {
1556 if (Z_OBJ_HT_P(op1)->get) {
1557 op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
1558 ret = compare_function(result, op_free, op2 TSRMLS_CC);
1559 zend_free_obj_get_result(op_free TSRMLS_CC);
1560 return ret;
1561 } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1562 ALLOC_INIT_ZVAL(op_free);
1563 if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
1564 ZVAL_LONG(result, 1);
1565 zend_free_obj_get_result(op_free TSRMLS_CC);
1566 return SUCCESS;
1567 }
1568 ret = compare_function(result, op_free, op2 TSRMLS_CC);
1569 zend_free_obj_get_result(op_free TSRMLS_CC);
1570 return ret;
1571 }
1572 }
1573 if (Z_TYPE_P(op2) == IS_OBJECT) {
1574 if (Z_OBJ_HT_P(op2)->get) {
1575 op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
1576 ret = compare_function(result, op1, op_free TSRMLS_CC);
1577 zend_free_obj_get_result(op_free TSRMLS_CC);
1578 return ret;
1579 } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1580 ALLOC_INIT_ZVAL(op_free);
1581 if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
1582 ZVAL_LONG(result, -1);
1583 zend_free_obj_get_result(op_free TSRMLS_CC);
1584 return SUCCESS;
1585 }
1586 ret = compare_function(result, op1, op_free TSRMLS_CC);
1587 zend_free_obj_get_result(op_free TSRMLS_CC);
1588 return ret;
1589 } else if (Z_TYPE_P(op1) == IS_OBJECT) {
1590 ZVAL_LONG(result, 1);
1591 return SUCCESS;
1592 }
1593 }
1594 if (!converted) {
1595 if (Z_TYPE_P(op1) == IS_NULL) {
1596 zendi_convert_to_boolean(op2, op2_copy, result);
1597 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1598 return SUCCESS;
1599 } else if (Z_TYPE_P(op2) == IS_NULL) {
1600 zendi_convert_to_boolean(op1, op1_copy, result);
1601 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1602 return SUCCESS;
1603 } else if (Z_TYPE_P(op1) == IS_BOOL) {
1604 zendi_convert_to_boolean(op2, op2_copy, result);
1605 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1606 return SUCCESS;
1607 } else if (Z_TYPE_P(op2) == IS_BOOL) {
1608 zendi_convert_to_boolean(op1, op1_copy, result);
1609 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1610 return SUCCESS;
1611 } else {
1612 zendi_convert_scalar_to_number(op1, op1_copy, result);
1613 zendi_convert_scalar_to_number(op2, op2_copy, result);
1614 converted = 1;
1615 }
1616 } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1617 ZVAL_LONG(result, 1);
1618 return SUCCESS;
1619 } else if (Z_TYPE_P(op2)==IS_ARRAY) {
1620 ZVAL_LONG(result, -1);
1621 return SUCCESS;
1622 } else if (Z_TYPE_P(op1)==IS_OBJECT) {
1623 ZVAL_LONG(result, 1);
1624 return SUCCESS;
1625 } else if (Z_TYPE_P(op2)==IS_OBJECT) {
1626 ZVAL_LONG(result, -1);
1627 return SUCCESS;
1628 } else {
1629 ZVAL_LONG(result, 0);
1630 return FAILURE;
1631 }
1632 }
1633 }
1634 }
1635 /* }}} */
1636
hash_zval_identical_function(const zval ** z1,const zval ** z2)1637 static int hash_zval_identical_function(const zval **z1, const zval **z2) /* {{{ */
1638 {
1639 zval result;
1640 TSRMLS_FETCH();
1641
1642 /* is_identical_function() returns 1 in case of identity and 0 in case
1643 * of a difference;
1644 * whereas this comparison function is expected to return 0 on identity,
1645 * and non zero otherwise.
1646 */
1647 if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
1648 return 1;
1649 }
1650 return !Z_LVAL(result);
1651 }
1652 /* }}} */
1653
is_identical_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1654 ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1655 {
1656 Z_TYPE_P(result) = IS_BOOL;
1657 if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
1658 Z_LVAL_P(result) = 0;
1659 return SUCCESS;
1660 }
1661 switch (Z_TYPE_P(op1)) {
1662 case IS_NULL:
1663 Z_LVAL_P(result) = 1;
1664 break;
1665 case IS_BOOL:
1666 case IS_LONG:
1667 case IS_RESOURCE:
1668 Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
1669 break;
1670 case IS_DOUBLE:
1671 Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
1672 break;
1673 case IS_STRING:
1674 Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
1675 && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
1676 break;
1677 case IS_ARRAY:
1678 Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
1679 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0);
1680 break;
1681 case IS_OBJECT:
1682 if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
1683 Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
1684 } else {
1685 Z_LVAL_P(result) = 0;
1686 }
1687 break;
1688 default:
1689 Z_LVAL_P(result) = 0;
1690 return FAILURE;
1691 }
1692 return SUCCESS;
1693 }
1694 /* }}} */
1695
is_not_identical_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1696 ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1697 {
1698 if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1699 return FAILURE;
1700 }
1701 Z_LVAL_P(result) = !Z_LVAL_P(result);
1702 return SUCCESS;
1703 }
1704 /* }}} */
1705
is_equal_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1706 ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1707 {
1708 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1709 return FAILURE;
1710 }
1711 ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
1712 return SUCCESS;
1713 }
1714 /* }}} */
1715
is_not_equal_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1716 ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1717 {
1718 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1719 return FAILURE;
1720 }
1721 ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
1722 return SUCCESS;
1723 }
1724 /* }}} */
1725
is_smaller_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1726 ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1727 {
1728 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1729 return FAILURE;
1730 }
1731 ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
1732 return SUCCESS;
1733 }
1734 /* }}} */
1735
is_smaller_or_equal_function(zval * result,zval * op1,zval * op2 TSRMLS_DC)1736 ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1737 {
1738 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1739 return FAILURE;
1740 }
1741 ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
1742 return SUCCESS;
1743 }
1744 /* }}} */
1745
instanceof_function_ex(const zend_class_entry * instance_ce,const zend_class_entry * ce,zend_bool interfaces_only TSRMLS_DC)1746 ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */
1747 {
1748 zend_uint i;
1749
1750 for (i=0; i<instance_ce->num_interfaces; i++) {
1751 if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
1752 return 1;
1753 }
1754 }
1755 if (!interfaces_only) {
1756 while (instance_ce) {
1757 if (instance_ce == ce) {
1758 return 1;
1759 }
1760 instance_ce = instance_ce->parent;
1761 }
1762 }
1763
1764 return 0;
1765 }
1766 /* }}} */
1767
instanceof_function(const zend_class_entry * instance_ce,const zend_class_entry * ce TSRMLS_DC)1768 ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC) /* {{{ */
1769 {
1770 return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
1771 }
1772 /* }}} */
1773
1774 #define LOWER_CASE 1
1775 #define UPPER_CASE 2
1776 #define NUMERIC 3
1777
increment_string(zval * str)1778 static void increment_string(zval *str) /* {{{ */
1779 {
1780 int carry=0;
1781 int pos=Z_STRLEN_P(str)-1;
1782 char *s=Z_STRVAL_P(str);
1783 char *t;
1784 int last=0; /* Shut up the compiler warning */
1785 int ch;
1786
1787 if (Z_STRLEN_P(str) == 0) {
1788 STR_FREE(Z_STRVAL_P(str));
1789 Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
1790 Z_STRLEN_P(str) = 1;
1791 return;
1792 }
1793
1794 if (IS_INTERNED(s)) {
1795 s = (char*) emalloc(Z_STRLEN_P(str) + 1);
1796 memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1);
1797 Z_STRVAL_P(str) = s;
1798 }
1799
1800 while (pos >= 0) {
1801 ch = s[pos];
1802 if (ch >= 'a' && ch <= 'z') {
1803 if (ch == 'z') {
1804 s[pos] = 'a';
1805 carry=1;
1806 } else {
1807 s[pos]++;
1808 carry=0;
1809 }
1810 last=LOWER_CASE;
1811 } else if (ch >= 'A' && ch <= 'Z') {
1812 if (ch == 'Z') {
1813 s[pos] = 'A';
1814 carry=1;
1815 } else {
1816 s[pos]++;
1817 carry=0;
1818 }
1819 last=UPPER_CASE;
1820 } else if (ch >= '0' && ch <= '9') {
1821 if (ch == '9') {
1822 s[pos] = '0';
1823 carry=1;
1824 } else {
1825 s[pos]++;
1826 carry=0;
1827 }
1828 last = NUMERIC;
1829 } else {
1830 carry=0;
1831 break;
1832 }
1833 if (carry == 0) {
1834 break;
1835 }
1836 pos--;
1837 }
1838
1839 if (carry) {
1840 t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
1841 memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
1842 Z_STRLEN_P(str)++;
1843 t[Z_STRLEN_P(str)] = '\0';
1844 switch (last) {
1845 case NUMERIC:
1846 t[0] = '1';
1847 break;
1848 case UPPER_CASE:
1849 t[0] = 'A';
1850 break;
1851 case LOWER_CASE:
1852 t[0] = 'a';
1853 break;
1854 }
1855 STR_FREE(Z_STRVAL_P(str));
1856 Z_STRVAL_P(str) = t;
1857 }
1858 }
1859 /* }}} */
1860
increment_function(zval * op1)1861 ZEND_API int increment_function(zval *op1) /* {{{ */
1862 {
1863 switch (Z_TYPE_P(op1)) {
1864 case IS_LONG:
1865 if (Z_LVAL_P(op1) == LONG_MAX) {
1866 /* switch to double */
1867 double d = (double)Z_LVAL_P(op1);
1868 ZVAL_DOUBLE(op1, d+1);
1869 } else {
1870 Z_LVAL_P(op1)++;
1871 }
1872 break;
1873 case IS_DOUBLE:
1874 Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
1875 break;
1876 case IS_NULL:
1877 ZVAL_LONG(op1, 1);
1878 break;
1879 case IS_STRING: {
1880 long lval;
1881 double dval;
1882
1883 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
1884 case IS_LONG:
1885 str_efree(Z_STRVAL_P(op1));
1886 if (lval == LONG_MAX) {
1887 /* switch to double */
1888 double d = (double)lval;
1889 ZVAL_DOUBLE(op1, d+1);
1890 } else {
1891 ZVAL_LONG(op1, lval+1);
1892 }
1893 break;
1894 case IS_DOUBLE:
1895 str_efree(Z_STRVAL_P(op1));
1896 ZVAL_DOUBLE(op1, dval+1);
1897 break;
1898 default:
1899 /* Perl style string increment */
1900 increment_string(op1);
1901 break;
1902 }
1903 }
1904 break;
1905 default:
1906 return FAILURE;
1907 }
1908 return SUCCESS;
1909 }
1910 /* }}} */
1911
decrement_function(zval * op1)1912 ZEND_API int decrement_function(zval *op1) /* {{{ */
1913 {
1914 long lval;
1915 double dval;
1916
1917 switch (Z_TYPE_P(op1)) {
1918 case IS_LONG:
1919 if (Z_LVAL_P(op1) == LONG_MIN) {
1920 double d = (double)Z_LVAL_P(op1);
1921 ZVAL_DOUBLE(op1, d-1);
1922 } else {
1923 Z_LVAL_P(op1)--;
1924 }
1925 break;
1926 case IS_DOUBLE:
1927 Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
1928 break;
1929 case IS_STRING: /* Like perl we only support string increment */
1930 if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
1931 STR_FREE(Z_STRVAL_P(op1));
1932 ZVAL_LONG(op1, -1);
1933 break;
1934 }
1935 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
1936 case IS_LONG:
1937 STR_FREE(Z_STRVAL_P(op1));
1938 if (lval == LONG_MIN) {
1939 double d = (double)lval;
1940 ZVAL_DOUBLE(op1, d-1);
1941 } else {
1942 ZVAL_LONG(op1, lval-1);
1943 }
1944 break;
1945 case IS_DOUBLE:
1946 STR_FREE(Z_STRVAL_P(op1));
1947 ZVAL_DOUBLE(op1, dval - 1);
1948 break;
1949 }
1950 break;
1951 default:
1952 return FAILURE;
1953 }
1954
1955 return SUCCESS;
1956 }
1957 /* }}} */
1958
zval_is_true(zval * op)1959 ZEND_API int zval_is_true(zval *op) /* {{{ */
1960 {
1961 convert_to_boolean(op);
1962 return (Z_LVAL_P(op) ? 1 : 0);
1963 }
1964 /* }}} */
1965
1966 #ifdef ZEND_USE_TOLOWER_L
zend_update_current_locale(void)1967 ZEND_API void zend_update_current_locale(void) /* {{{ */
1968 {
1969 current_locale = _get_current_locale();
1970 }
1971 /* }}} */
1972 #endif
1973
zend_str_tolower_copy(char * dest,const char * source,unsigned int length)1974 ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */
1975 {
1976 register unsigned char *str = (unsigned char*)source;
1977 register unsigned char *result = (unsigned char*)dest;
1978 register unsigned char *end = str + length;
1979
1980 while (str < end) {
1981 *result++ = zend_tolower_ascii(*str++);
1982 }
1983 *result = '\0';
1984
1985 return dest;
1986 }
1987 /* }}} */
1988
zend_str_tolower_dup(const char * source,unsigned int length)1989 ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */
1990 {
1991 return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
1992 }
1993 /* }}} */
1994
zend_str_tolower(char * str,unsigned int length)1995 ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
1996 {
1997 register unsigned char *p = (unsigned char*)str;
1998 register unsigned char *end = p + length;
1999
2000 while (p < end) {
2001 *p = zend_tolower_ascii(*p);
2002 p++;
2003 }
2004 }
2005 /* }}} */
2006
zend_binary_strcmp(const char * s1,uint len1,const char * s2,uint len2)2007 ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2008 {
2009 int retval;
2010
2011 if (s1 == s2) {
2012 return 0;
2013 }
2014 retval = memcmp(s1, s2, MIN(len1, len2));
2015 if (!retval) {
2016 return (len1 - len2);
2017 } else {
2018 return retval;
2019 }
2020 }
2021 /* }}} */
2022
zend_binary_strncmp(const char * s1,uint len1,const char * s2,uint len2,uint length)2023 ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2024 {
2025 int retval;
2026
2027 if (s1 == s2) {
2028 return 0;
2029 }
2030 retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2031 if (!retval) {
2032 return (MIN(length, len1) - MIN(length, len2));
2033 } else {
2034 return retval;
2035 }
2036 }
2037 /* }}} */
2038
zend_binary_strcasecmp(const char * s1,uint len1,const char * s2,uint len2)2039 ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2040 {
2041 int len;
2042 int c1, c2;
2043
2044 if (s1 == s2) {
2045 return 0;
2046 }
2047
2048 len = MIN(len1, len2);
2049 while (len--) {
2050 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2051 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2052 if (c1 != c2) {
2053 return c1 - c2;
2054 }
2055 }
2056
2057 return len1 - len2;
2058 }
2059 /* }}} */
2060
zend_binary_strncasecmp(const char * s1,uint len1,const char * s2,uint len2,uint length)2061 ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2062 {
2063 int len;
2064 int c1, c2;
2065
2066 if (s1 == s2) {
2067 return 0;
2068 }
2069 len = MIN(length, MIN(len1, len2));
2070 while (len--) {
2071 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2072 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2073 if (c1 != c2) {
2074 return c1 - c2;
2075 }
2076 }
2077
2078 return MIN(length, len1) - MIN(length, len2);
2079 }
2080 /* }}} */
2081
zend_binary_strcasecmp_l(const char * s1,uint len1,const char * s2,uint len2)2082 ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2083 {
2084 int len;
2085 int c1, c2;
2086
2087 if (s1 == s2) {
2088 return 0;
2089 }
2090
2091 len = MIN(len1, len2);
2092 while (len--) {
2093 c1 = zend_tolower((int)*(unsigned char *)s1++);
2094 c2 = zend_tolower((int)*(unsigned char *)s2++);
2095 if (c1 != c2) {
2096 return c1 - c2;
2097 }
2098 }
2099
2100 return len1 - len2;
2101 }
2102 /* }}} */
2103
zend_binary_strncasecmp_l(const char * s1,uint len1,const char * s2,uint len2,uint length)2104 ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2105 {
2106 int len;
2107 int c1, c2;
2108
2109 if (s1 == s2) {
2110 return 0;
2111 }
2112 len = MIN(length, MIN(len1, len2));
2113 while (len--) {
2114 c1 = zend_tolower((int)*(unsigned char *)s1++);
2115 c2 = zend_tolower((int)*(unsigned char *)s2++);
2116 if (c1 != c2) {
2117 return c1 - c2;
2118 }
2119 }
2120
2121 return MIN(length, len1) - MIN(length, len2);
2122 }
2123 /* }}} */
2124
zend_binary_zval_strcmp(zval * s1,zval * s2)2125 ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2126 {
2127 return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2128 }
2129 /* }}} */
2130
zend_binary_zval_strncmp(zval * s1,zval * s2,zval * s3)2131 ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2132 {
2133 return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2134 }
2135 /* }}} */
2136
zend_binary_zval_strcasecmp(zval * s1,zval * s2)2137 ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
2138 {
2139 return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2140 }
2141 /* }}} */
2142
zend_binary_zval_strncasecmp(zval * s1,zval * s2,zval * s3)2143 ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2144 {
2145 return zend_binary_strncasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2146 }
2147 /* }}} */
2148
zendi_smart_strcmp(zval * result,zval * s1,zval * s2)2149 ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
2150 {
2151 int ret1, ret2;
2152 int oflow1, oflow2;
2153 long lval1 = 0, lval2 = 0;
2154 double dval1 = 0.0, dval2 = 0.0;
2155
2156 if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
2157 (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) {
2158 #if ULONG_MAX == 0xFFFFFFFF
2159 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
2160 ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
2161 || (oflow1 == -1 && dval1 < -9007199254740991.))) {
2162 #else
2163 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
2164 #endif
2165 /* both values are integers overflown to the same side, and the
2166 * double comparison may have resulted in crucial accuracy lost */
2167 goto string_cmp;
2168 }
2169 if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
2170 if (ret1!=IS_DOUBLE) {
2171 if (oflow2) {
2172 /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
2173 ZVAL_LONG(result, -1 * oflow2);
2174 return;
2175 }
2176 dval1 = (double) lval1;
2177 } else if (ret2!=IS_DOUBLE) {
2178 if (oflow1) {
2179 ZVAL_LONG(result, oflow1);
2180 return;
2181 }
2182 dval2 = (double) lval2;
2183 } else if (dval1 == dval2 && !zend_finite(dval1)) {
2184 /* Both values overflowed and have the same sign,
2185 * so a numeric comparison would be inaccurate */
2186 goto string_cmp;
2187 }
2188 Z_DVAL_P(result) = dval1 - dval2;
2189 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
2190 } else { /* they both have to be long's */
2191 ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
2192 }
2193 } else {
2194 string_cmp:
2195 Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
2196 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
2197 }
2198 }
2199 /* }}} */
2200
2201 static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC) /* {{{ */
2202 {
2203 zval result;
2204
2205 if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
2206 return 1;
2207 }
2208 return Z_LVAL(result);
2209 }
2210 /* }}} */
2211
2212 ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2213 {
2214 return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2215 }
2216 /* }}} */
2217
2218 ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2219 {
2220 ZVAL_LONG(result, ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC));
2221 }
2222 /* }}} */
2223
2224 ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC) /* {{{ */
2225 {
2226 zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC);
2227 }
2228 /* }}} */
2229
2230 ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
2231 {
2232 Z_TYPE_P(result) = IS_LONG;
2233
2234 if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
2235 Z_LVAL_P(result) = 0;
2236 return;
2237 }
2238
2239 if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2240 Z_LVAL_P(result) = 1;
2241 } else {
2242 Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
2243 }
2244 }
2245 /* }}} */
2246
2247 ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2248 {
2249 TSRMLS_FETCH();
2250
2251 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2252 }
2253 /* }}} */
2254
2255 /*
2256 * Local variables:
2257 * tab-width: 4
2258 * c-basic-offset: 4
2259 * indent-tabs-mode: t
2260 * End:
2261 */
2262