1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 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: zend_operators.c 276004 2009-02-17 15:15:36Z mattwil $ */
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_multiply.h"
31 : #include "zend_strtod.h"
32 : #include "zend_exceptions.h"
33 :
34 : #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
35 :
36 : #if ZEND_USE_TOLOWER_L
37 : #include <locale.h>
38 : static _locale_t current_locale = NULL;
39 : /* this is true global! may lead to strange effects on ZTS, but so is setlocale() */
40 : #define zend_tolower(c) _tolower_l(c, current_locale)
41 : #else
42 : #define zend_tolower(c) tolower(c)
43 : #endif
44 :
45 : ZEND_API int zend_atoi(const char *str, int str_len)
46 719172 : {
47 : int retval;
48 :
49 719172 : if (!str_len) {
50 53834 : str_len = strlen(str);
51 : }
52 719172 : retval = strtol(str, NULL, 0);
53 719172 : if (str_len>0) {
54 678899 : switch (str[str_len-1]) {
55 : case 'g':
56 : case 'G':
57 4 : retval *= 1024;
58 : /* break intentionally missing */
59 : case 'm':
60 : case 'M':
61 40699 : retval *= 1024;
62 : /* break intentionally missing */
63 : case 'k':
64 : case 'K':
65 54265 : retval *= 1024;
66 : break;
67 : }
68 : }
69 719172 : return retval;
70 : }
71 :
72 :
73 : ZEND_API double zend_string_to_double(const char *number, zend_uint length)
74 0 : {
75 0 : double divisor = 10.0;
76 0 : double result = 0.0;
77 : double exponent;
78 0 : const char *end = number+length;
79 0 : const char *digit = number;
80 :
81 0 : if (!length) {
82 0 : return result;
83 : }
84 :
85 0 : while (digit < end) {
86 0 : if ((*digit <= '9' && *digit >= '0')) {
87 0 : result *= 10;
88 0 : result += *digit - '0';
89 0 : } else if (*digit == '.') {
90 0 : digit++;
91 0 : break;
92 0 : } else if (toupper(*digit) == 'E') {
93 0 : exponent = (double) atoi(digit+1);
94 0 : result *= pow(10.0, exponent);
95 0 : return result;
96 : } else {
97 0 : return result;
98 : }
99 0 : digit++;
100 : }
101 :
102 0 : while (digit < end) {
103 0 : if ((*digit <= '9' && *digit >= '0')) {
104 0 : result += (*digit - '0') / divisor;
105 0 : divisor *= 10;
106 0 : } else if (toupper(*digit) == 'E') {
107 0 : exponent = (double) atoi(digit+1);
108 0 : result *= pow(10.0, exponent);
109 0 : return result;
110 : } else {
111 0 : return result;
112 : }
113 0 : digit++;
114 : }
115 0 : return result;
116 : }
117 :
118 :
119 : ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
120 205054 : {
121 205054 : switch (op->type) {
122 : case IS_STRING:
123 : {
124 : char *strval;
125 :
126 101158 : strval = op->value.str.val;
127 101158 : if ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval, 1)) == 0) {
128 48 : op->value.lval = 0;
129 48 : op->type = IS_LONG;
130 : }
131 101158 : STR_FREE(strval);
132 101158 : break;
133 : }
134 : case IS_BOOL:
135 39 : op->type = IS_LONG;
136 39 : break;
137 : case IS_RESOURCE:
138 7 : zend_list_delete(op->value.lval);
139 7 : op->type = IS_LONG;
140 7 : break;
141 : case IS_OBJECT:
142 6 : convert_to_long_base(op, 10);
143 6 : break;
144 : case IS_NULL:
145 47 : op->type = IS_LONG;
146 47 : op->value.lval = 0;
147 : break;
148 : }
149 205054 : }
150 :
151 : #define zendi_convert_scalar_to_number(op, holder, result) \
152 : if (op==result) { \
153 : if (op->type != IS_LONG) { \
154 : convert_scalar_to_number(op TSRMLS_CC); \
155 : } \
156 : } else { \
157 : switch ((op)->type) { \
158 : case IS_STRING: \
159 : { \
160 : if (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval, 1)) == 0) { \
161 : (holder).value.lval = 0; \
162 : (holder).type = IS_LONG; \
163 : } \
164 : (op) = &(holder); \
165 : break; \
166 : } \
167 : case IS_BOOL: \
168 : case IS_RESOURCE: \
169 : (holder).value.lval = (op)->value.lval; \
170 : (holder).type = IS_LONG; \
171 : (op) = &(holder); \
172 : break; \
173 : case IS_NULL: \
174 : (holder).value.lval = 0; \
175 : (holder).type = IS_LONG; \
176 : (op) = &(holder); \
177 : break; \
178 : case IS_OBJECT: \
179 : (holder) = (*(op)); \
180 : zval_copy_ctor(&(holder)); \
181 : convert_to_long_base(&(holder), 10); \
182 : if ((holder).type == IS_LONG) { \
183 : (op) = &(holder); \
184 : } \
185 : break; \
186 : } \
187 : }
188 :
189 : #ifdef _WIN64
190 : # define DVAL_TO_LVAL(d, l) \
191 : if ((d) > LONG_MAX) { \
192 : (l) = (long)(unsigned long)(__int64) (d); \
193 : } else { \
194 : (l) = (long) (d); \
195 : }
196 : #else
197 : # define DVAL_TO_LVAL(d, l) \
198 : if ((d) > LONG_MAX) { \
199 : (l) = (unsigned long) (d); \
200 : } else { \
201 : (l) = (long) (d); \
202 : }
203 : #endif
204 :
205 : #define zendi_convert_to_long(op, holder, result) \
206 : if (op == result) { \
207 : convert_to_long(op); \
208 : } else if ((op)->type != IS_LONG) { \
209 : switch ((op)->type) { \
210 : case IS_NULL: \
211 : (holder).value.lval = 0; \
212 : break; \
213 : case IS_DOUBLE: \
214 : DVAL_TO_LVAL((op)->value.dval, (holder).value.lval); \
215 : break; \
216 : case IS_STRING: \
217 : (holder).value.lval = strtol((op)->value.str.val, NULL, 10); \
218 : break; \
219 : case IS_ARRAY: \
220 : (holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
221 : break; \
222 : case IS_OBJECT: \
223 : (holder) = (*(op)); \
224 : zval_copy_ctor(&(holder)); \
225 : convert_to_long_base(&(holder), 10); \
226 : break; \
227 : case IS_BOOL: \
228 : case IS_RESOURCE: \
229 : (holder).value.lval = (op)->value.lval; \
230 : break; \
231 : default: \
232 : zend_error(E_WARNING, "Cannot convert to ordinal value"); \
233 : (holder).value.lval = 0; \
234 : break; \
235 : } \
236 : (holder).type = IS_LONG; \
237 : (op) = &(holder); \
238 : }
239 :
240 :
241 : #define zendi_convert_to_boolean(op, holder, result) \
242 : if (op==result) { \
243 : convert_to_boolean(op); \
244 : } else if ((op)->type != IS_BOOL) { \
245 : switch ((op)->type) { \
246 : case IS_NULL: \
247 : (holder).value.lval = 0; \
248 : break; \
249 : case IS_RESOURCE: \
250 : case IS_LONG: \
251 : (holder).value.lval = ((op)->value.lval ? 1 : 0); \
252 : break; \
253 : case IS_DOUBLE: \
254 : (holder).value.lval = ((op)->value.dval ? 1 : 0); \
255 : break; \
256 : case IS_STRING: \
257 : if ((op)->value.str.len == 0 \
258 : || ((op)->value.str.len==1 && (op)->value.str.val[0]=='0')) { \
259 : (holder).value.lval = 0; \
260 : } else { \
261 : (holder).value.lval = 1; \
262 : } \
263 : break; \
264 : case IS_ARRAY: \
265 : (holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
266 : break; \
267 : case IS_OBJECT: \
268 : (holder) = (*(op)); \
269 : zval_copy_ctor(&(holder)); \
270 : convert_to_boolean(&(holder)); \
271 : break; \
272 : default: \
273 : (holder).value.lval = 0; \
274 : break; \
275 : } \
276 : (holder).type = IS_BOOL; \
277 : (op) = &(holder); \
278 : }
279 :
280 :
281 : #define convert_object_to_type(op, ctype, conv_func) \
282 : if (Z_OBJ_HT_P(op)->cast_object) { \
283 : zval dst; \
284 : if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) { \
285 : zend_error(E_RECOVERABLE_ERROR, \
286 : "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name, \
287 : zend_get_type_by_const(ctype)); \
288 : } else { \
289 : zval_dtor(op); \
290 : Z_TYPE_P(op) = ctype; \
291 : op->value = dst.value; \
292 : } \
293 : } else { \
294 : if(Z_OBJ_HT_P(op)->get) { \
295 : zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
296 : if(Z_TYPE_P(newop) != IS_OBJECT) { \
297 : /* for safety - avoid loop */ \
298 : zval_dtor(op); \
299 : *op = *newop; \
300 : FREE_ZVAL(newop); \
301 : conv_func(op); \
302 : } \
303 : } \
304 : }
305 :
306 : ZEND_API void convert_to_long(zval *op)
307 701723 : {
308 701723 : if ((op)->type != IS_LONG) {
309 19889 : convert_to_long_base(op, 10);
310 : }
311 701723 : }
312 :
313 : ZEND_API void convert_to_long_base(zval *op, int base)
314 23717 : {
315 : char *strval;
316 : long tmp;
317 :
318 23717 : switch (op->type) {
319 : case IS_NULL:
320 1211 : op->value.lval = 0;
321 1211 : break;
322 : case IS_RESOURCE: {
323 : TSRMLS_FETCH();
324 :
325 145 : zend_list_delete(op->value.lval);
326 : }
327 : /* break missing intentionally */
328 : case IS_BOOL:
329 : case IS_LONG:
330 8775 : break;
331 : case IS_DOUBLE:
332 8714 : DVAL_TO_LVAL(op->value.dval, op->value.lval);
333 8714 : break;
334 : case IS_STRING:
335 3896 : strval = op->value.str.val;
336 3896 : op->value.lval = strtol(strval, NULL, base);
337 3896 : STR_FREE(strval);
338 3896 : break;
339 : case IS_ARRAY:
340 1020 : tmp = (zend_hash_num_elements(op->value.ht)?1:0);
341 1020 : zval_dtor(op);
342 1020 : op->value.lval = tmp;
343 1020 : break;
344 : case IS_OBJECT:
345 : {
346 101 : int retval = 1;
347 : TSRMLS_FETCH();
348 :
349 101 : convert_object_to_type(op, IS_LONG, convert_to_long);
350 :
351 101 : if (op->type == IS_LONG) {
352 101 : return;
353 : }
354 :
355 0 : if (EG(ze1_compatibility_mode)) {
356 0 : HashTable *ht = Z_OBJPROP_P(op);
357 0 : if (ht) {
358 0 : retval = (zend_hash_num_elements(ht)?1:0);
359 : }
360 : } else {
361 0 : zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
362 : }
363 0 : zval_dtor(op);
364 0 : ZVAL_LONG(op, retval);
365 0 : return;
366 : }
367 : default:
368 0 : zend_error(E_WARNING, "Cannot convert to ordinal value");
369 0 : zval_dtor(op);
370 0 : op->value.lval = 0;
371 : break;
372 : }
373 :
374 23616 : op->type = IS_LONG;
375 : }
376 :
377 :
378 : ZEND_API void convert_to_double(zval *op)
379 330582 : {
380 : char *strval;
381 : double tmp;
382 :
383 330582 : switch (op->type) {
384 : case IS_NULL:
385 335 : op->value.dval = 0.0;
386 335 : break;
387 : case IS_RESOURCE: {
388 : TSRMLS_FETCH();
389 :
390 57 : zend_list_delete(op->value.lval);
391 : }
392 : /* break missing intentionally */
393 : case IS_BOOL:
394 : case IS_LONG:
395 256420 : op->value.dval = (double) op->value.lval;
396 256420 : break;
397 : case IS_DOUBLE:
398 72368 : break;
399 : case IS_STRING:
400 1050 : strval = op->value.str.val;
401 :
402 1050 : op->value.dval = zend_strtod(strval, NULL);
403 1050 : STR_FREE(strval);
404 1050 : break;
405 : case IS_ARRAY:
406 380 : tmp = (zend_hash_num_elements(op->value.ht)?1:0);
407 380 : zval_dtor(op);
408 380 : op->value.dval = tmp;
409 380 : break;
410 : case IS_OBJECT:
411 : {
412 29 : double retval = 1.0;
413 : TSRMLS_FETCH();
414 :
415 29 : convert_object_to_type(op, IS_DOUBLE, convert_to_double);
416 :
417 29 : if (op->type == IS_DOUBLE) {
418 29 : return;
419 : }
420 :
421 0 : if (EG(ze1_compatibility_mode)) {
422 0 : HashTable *ht = Z_OBJPROP_P(op);
423 0 : if (ht) {
424 0 : retval = (zend_hash_num_elements(ht)?1.0:0.0);
425 : }
426 : } else {
427 0 : zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
428 : }
429 :
430 0 : zval_dtor(op);
431 0 : ZVAL_DOUBLE(op, retval);
432 0 : break;
433 : }
434 : default:
435 0 : zend_error(E_WARNING, "Cannot convert to real value (type=%d)", op->type);
436 0 : zval_dtor(op);
437 0 : op->value.dval = 0;
438 : break;
439 : }
440 330553 : op->type = IS_DOUBLE;
441 : }
442 :
443 :
444 : ZEND_API void convert_to_null(zval *op)
445 1093 : {
446 1093 : if (Z_TYPE_P(op) == IS_OBJECT) {
447 6 : if (Z_OBJ_HT_P(op)->cast_object) {
448 : zval *org;
449 : TSRMLS_FETCH();
450 :
451 6 : ALLOC_ZVAL(org);
452 6 : *org = *op;
453 6 : if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
454 0 : zval_dtor(org);
455 0 : return;
456 : }
457 6 : *op = *org;
458 6 : FREE_ZVAL(org);
459 : }
460 : }
461 :
462 1093 : zval_dtor(op);
463 1093 : Z_TYPE_P(op) = IS_NULL;
464 : }
465 :
466 :
467 : ZEND_API void convert_to_boolean(zval *op)
468 1735618 : {
469 : char *strval;
470 : int tmp;
471 :
472 1735618 : switch (op->type) {
473 : case IS_BOOL:
474 3423 : break;
475 : case IS_NULL:
476 107 : op->value.lval = 0;
477 107 : break;
478 : case IS_RESOURCE: {
479 : TSRMLS_FETCH();
480 :
481 11 : zend_list_delete(op->value.lval);
482 : }
483 : /* break missing intentionally */
484 : case IS_LONG:
485 1660821 : op->value.lval = (op->value.lval ? 1 : 0);
486 1660821 : break;
487 : case IS_DOUBLE:
488 167 : op->value.lval = (op->value.dval ? 1 : 0);
489 167 : break;
490 : case IS_STRING:
491 248 : strval = op->value.str.val;
492 :
493 310 : if (op->value.str.len == 0
494 : || (op->value.str.len==1 && op->value.str.val[0]=='0')) {
495 62 : op->value.lval = 0;
496 : } else {
497 186 : op->value.lval = 1;
498 : }
499 248 : STR_FREE(strval);
500 248 : break;
501 : case IS_ARRAY:
502 30 : tmp = (zend_hash_num_elements(op->value.ht)?1:0);
503 30 : zval_dtor(op);
504 30 : op->value.lval = tmp;
505 30 : break;
506 : case IS_OBJECT:
507 : {
508 70822 : zend_bool retval = 1;
509 : TSRMLS_FETCH();
510 :
511 70822 : convert_object_to_type(op, IS_BOOL, convert_to_boolean);
512 :
513 70822 : if (op->type == IS_BOOL) {
514 70822 : return;
515 : }
516 :
517 0 : if (EG(ze1_compatibility_mode)) {
518 0 : HashTable *ht = Z_OBJPROP_P(op);
519 0 : if (ht) {
520 0 : retval = (zend_hash_num_elements(ht)?1:0);
521 : }
522 : }
523 :
524 0 : zval_dtor(op);
525 0 : ZVAL_BOOL(op, retval);
526 0 : break;
527 : }
528 : default:
529 0 : zval_dtor(op);
530 0 : op->value.lval = 0;
531 : break;
532 : }
533 1664796 : op->type = IS_BOOL;
534 : }
535 :
536 : ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
537 2017847 : {
538 : long lval;
539 : double dval;
540 :
541 2017847 : switch (op->type) {
542 : case IS_NULL:
543 2676 : op->value.str.val = STR_EMPTY_ALLOC();
544 2676 : op->value.str.len = 0;
545 2676 : break;
546 : case IS_STRING:
547 0 : break;
548 : case IS_BOOL:
549 9242 : if (op->value.lval) {
550 873 : op->value.str.val = estrndup_rel("1", 1);
551 873 : op->value.str.len = 1;
552 : } else {
553 8369 : op->value.str.val = STR_EMPTY_ALLOC();
554 8369 : op->value.str.len = 0;
555 : }
556 9242 : break;
557 : case IS_RESOURCE: {
558 163 : long tmp = op->value.lval;
559 : TSRMLS_FETCH();
560 :
561 163 : zend_list_delete(op->value.lval);
562 163 : op->value.str.len = zend_spprintf(&op->value.str.val, 0, "Resource id #%ld", tmp);
563 163 : break;
564 : }
565 : case IS_LONG:
566 2002639 : lval = op->value.lval;
567 :
568 2002639 : op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%ld", lval); /* SAFE */
569 2002639 : break;
570 : case IS_DOUBLE: {
571 : TSRMLS_FETCH();
572 2148 : dval = op->value.dval;
573 2148 : op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), dval); /* SAFE */
574 : /* %G already handles removing trailing zeros from the fractional part, yay */
575 2148 : break;
576 : }
577 : case IS_ARRAY:
578 690 : zend_error(E_NOTICE, "Array to string conversion");
579 690 : zval_dtor(op);
580 690 : op->value.str.val = estrndup_rel("Array", sizeof("Array")-1);
581 690 : op->value.str.len = sizeof("Array")-1;
582 690 : break;
583 : case IS_OBJECT: {
584 : TSRMLS_FETCH();
585 :
586 289 : convert_object_to_type(op, IS_STRING, convert_to_string);
587 :
588 278 : if (op->type == IS_STRING) {
589 235 : return;
590 : }
591 :
592 43 : zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
593 43 : zval_dtor(op);
594 43 : op->value.str.val = estrndup_rel("Object", sizeof("Object")-1);
595 43 : op->value.str.len = sizeof("Object")-1;
596 43 : break;
597 : }
598 : default:
599 0 : zval_dtor(op);
600 0 : ZVAL_BOOL(op, 0);
601 : break;
602 : }
603 2017601 : op->type = IS_STRING;
604 : }
605 :
606 :
607 : static void convert_scalar_to_array(zval *op, int type)
608 336 : {
609 : zval *entry;
610 :
611 336 : ALLOC_ZVAL(entry);
612 336 : *entry = *op;
613 336 : INIT_PZVAL(entry);
614 :
615 336 : switch (type) {
616 : case IS_ARRAY:
617 222 : ALLOC_HASHTABLE(op->value.ht);
618 222 : zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
619 222 : zend_hash_index_update(op->value.ht, 0, (void *) &entry, sizeof(zval *), NULL);
620 222 : op->type = IS_ARRAY;
621 222 : break;
622 : case IS_OBJECT:
623 : {
624 : /* OBJECTS_OPTIMIZE */
625 : TSRMLS_FETCH();
626 :
627 114 : object_init(op);
628 114 : zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
629 : }
630 : break;
631 : }
632 336 : }
633 :
634 :
635 : ZEND_API void convert_to_array(zval *op)
636 13775 : {
637 : TSRMLS_FETCH();
638 :
639 13775 : switch (op->type) {
640 : case IS_ARRAY:
641 13509 : return;
642 : break;
643 : /* OBJECTS_OPTIMIZE */
644 : case IS_OBJECT:
645 : {
646 : zval *tmp;
647 : HashTable *ht;
648 :
649 15 : ALLOC_HASHTABLE(ht);
650 15 : zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
651 15 : if (Z_OBJ_HT_P(op)->get_properties) {
652 15 : HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
653 15 : if(obj_ht) {
654 15 : zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
655 : }
656 : } else {
657 0 : convert_object_to_type(op, IS_ARRAY, convert_to_array);
658 :
659 0 : if (op->type == IS_ARRAY) {
660 0 : zend_hash_destroy(ht);
661 0 : FREE_HASHTABLE(ht);
662 0 : return;
663 : }
664 : }
665 15 : zval_dtor(op);
666 15 : op->type = IS_ARRAY;
667 15 : op->value.ht = ht;
668 : }
669 15 : return;
670 : case IS_NULL:
671 29 : ALLOC_HASHTABLE(op->value.ht);
672 29 : zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
673 29 : op->type = IS_ARRAY;
674 29 : break;
675 : default:
676 222 : convert_scalar_to_array(op, IS_ARRAY);
677 : break;
678 : }
679 : }
680 :
681 :
682 : ZEND_API void convert_to_object(zval *op)
683 198 : {
684 198 : switch (op->type) {
685 : case IS_ARRAY:
686 : {
687 : /* OBJECTS_OPTIMIZE */
688 : TSRMLS_FETCH();
689 :
690 67 : object_and_properties_init(op, zend_standard_class_def, op->value.ht);
691 67 : return;
692 : break;
693 : }
694 : case IS_OBJECT:
695 10 : return;
696 : case IS_NULL:
697 : {
698 : /* OBJECTS_OPTIMIZE */
699 : TSRMLS_FETCH();
700 :
701 7 : object_init(op);
702 7 : break;
703 : }
704 : default:
705 114 : convert_scalar_to_array(op, IS_OBJECT);
706 : break;
707 : }
708 : }
709 :
710 : ZEND_API void multi_convert_to_long_ex(int argc, ...)
711 3 : {
712 : zval **arg;
713 : va_list ap;
714 :
715 3 : va_start(ap, argc);
716 :
717 18 : while (argc--) {
718 12 : arg = va_arg(ap, zval **);
719 12 : convert_to_long_ex(arg);
720 : }
721 :
722 3 : va_end(ap);
723 3 : }
724 :
725 : ZEND_API void multi_convert_to_double_ex(int argc, ...)
726 0 : {
727 : zval **arg;
728 : va_list ap;
729 :
730 0 : va_start(ap, argc);
731 :
732 0 : while (argc--) {
733 0 : arg = va_arg(ap, zval **);
734 0 : convert_to_double_ex(arg);
735 : }
736 :
737 0 : va_end(ap);
738 0 : }
739 :
740 : ZEND_API void multi_convert_to_string_ex(int argc, ...)
741 0 : {
742 : zval **arg;
743 : va_list ap;
744 :
745 0 : va_start(ap, argc);
746 :
747 0 : while (argc--) {
748 0 : arg = va_arg(ap, zval **);
749 0 : convert_to_string_ex(arg);
750 : }
751 :
752 0 : va_end(ap);
753 0 : }
754 :
755 : ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
756 220531 : {
757 : zval op1_copy, op2_copy;
758 :
759 220531 : if (op1->type == IS_ARRAY && op2->type == IS_ARRAY) {
760 : zval *tmp;
761 :
762 5 : if ((result == op1) && (result == op2)) {
763 : /* $a += $a */
764 1 : return SUCCESS;
765 : }
766 4 : if (result != op1) {
767 3 : *result = *op1;
768 3 : zval_copy_ctor(result);
769 : }
770 4 : zend_hash_merge(result->value.ht, op2->value.ht, (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
771 4 : return SUCCESS;
772 : }
773 220526 : zendi_convert_scalar_to_number(op1, op1_copy, result);
774 220526 : zendi_convert_scalar_to_number(op2, op2_copy, result);
775 :
776 :
777 220526 : if (op1->type == IS_LONG && op2->type == IS_LONG) {
778 218950 : long lval = op1->value.lval + op2->value.lval;
779 :
780 : /* check for overflow by comparing sign bits */
781 218970 : if ( (op1->value.lval & LONG_SIGN_MASK) == (op2->value.lval & LONG_SIGN_MASK)
782 : && (op1->value.lval & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
783 :
784 20 : result->value.dval = (double) op1->value.lval + (double) op2->value.lval;
785 20 : result->type = IS_DOUBLE;
786 : } else {
787 218930 : result->value.lval = lval;
788 218930 : result->type = IS_LONG;
789 : }
790 218950 : return SUCCESS;
791 : }
792 1576 : if ((op1->type == IS_DOUBLE && op2->type == IS_LONG)
793 : || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) {
794 1356 : result->value.dval = (op1->type == IS_LONG ?
795 : (((double) op1->value.lval) + op2->value.dval) :
796 : (op1->value.dval + ((double) op2->value.lval)));
797 1356 : result->type = IS_DOUBLE;
798 1356 : return SUCCESS;
799 : }
800 220 : if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
801 216 : result->type = IS_DOUBLE;
802 216 : result->value.dval = op1->value.dval + op2->value.dval;
803 216 : return SUCCESS;
804 : }
805 4 : zend_error(E_ERROR, "Unsupported operand types");
806 0 : return FAILURE; /* unknown datatype */
807 : }
808 :
809 :
810 : ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
811 197669 : {
812 : zval op1_copy, op2_copy;
813 :
814 197669 : zendi_convert_scalar_to_number(op1, op1_copy, result);
815 197669 : zendi_convert_scalar_to_number(op2, op2_copy, result);
816 :
817 197669 : if (op1->type == IS_LONG && op2->type == IS_LONG) {
818 195383 : long lval = op1->value.lval - op2->value.lval;
819 :
820 : /* check for overflow by comparing sign bits */
821 195400 : if ( (op1->value.lval & LONG_SIGN_MASK) != (op2->value.lval & LONG_SIGN_MASK)
822 : && (op1->value.lval & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
823 :
824 17 : result->value.dval = (double) op1->value.lval - (double) op2->value.lval;
825 17 : result->type = IS_DOUBLE;
826 : } else {
827 195366 : result->value.lval = lval;
828 195366 : result->type = IS_LONG;
829 : }
830 195383 : return SUCCESS;
831 : }
832 2286 : if ((op1->type == IS_DOUBLE && op2->type == IS_LONG)
833 : || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) {
834 2080 : result->value.dval = (op1->type == IS_LONG ?
835 : (((double) op1->value.lval) - op2->value.dval) :
836 : (op1->value.dval - ((double) op2->value.lval)));
837 2080 : result->type = IS_DOUBLE;
838 2080 : return SUCCESS;
839 : }
840 206 : if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
841 205 : result->type = IS_DOUBLE;
842 205 : result->value.dval = op1->value.dval - op2->value.dval;
843 205 : return SUCCESS;
844 : }
845 1 : zend_error(E_ERROR, "Unsupported operand types");
846 0 : return FAILURE; /* unknown datatype */
847 : }
848 :
849 :
850 : ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
851 5018 : {
852 : zval op1_copy, op2_copy;
853 :
854 5018 : zendi_convert_scalar_to_number(op1, op1_copy, result);
855 5018 : zendi_convert_scalar_to_number(op2, op2_copy, result);
856 :
857 5018 : if (op1->type == IS_LONG && op2->type == IS_LONG) {
858 : long overflow;
859 :
860 4687 : ZEND_SIGNED_MULTIPLY_LONG(op1->value.lval,op2->value.lval, result->value.lval,result->value.dval,overflow);
861 4687 : result->type = overflow ? IS_DOUBLE : IS_LONG;
862 4687 : return SUCCESS;
863 : }
864 331 : if ((op1->type == IS_DOUBLE && op2->type == IS_LONG)
865 : || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) {
866 121 : result->value.dval = (op1->type == IS_LONG ?
867 : (((double) op1->value.lval) * op2->value.dval) :
868 : (op1->value.dval * ((double) op2->value.lval)));
869 121 : result->type = IS_DOUBLE;
870 121 : return SUCCESS;
871 : }
872 210 : if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
873 209 : result->type = IS_DOUBLE;
874 209 : result->value.dval = op1->value.dval * op2->value.dval;
875 209 : return SUCCESS;
876 : }
877 1 : zend_error(E_ERROR, "Unsupported operand types");
878 0 : return FAILURE; /* unknown datatype */
879 : }
880 :
881 : ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
882 67726 : {
883 : zval op1_copy, op2_copy;
884 :
885 67726 : zendi_convert_scalar_to_number(op1, op1_copy, result);
886 67726 : zendi_convert_scalar_to_number(op2, op2_copy, result);
887 :
888 67726 : if ((op2->type == IS_LONG && op2->value.lval == 0) || (op2->type == IS_DOUBLE && op2->value.dval == 0.0)) {
889 45 : zend_error(E_WARNING, "Division by zero");
890 45 : ZVAL_BOOL(result, 0);
891 45 : return FAILURE; /* division by zero */
892 : }
893 67681 : if (op1->type == IS_LONG && op2->type == IS_LONG) {
894 63705 : if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
895 : /* Prevent overflow error/crash */
896 0 : ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
897 0 : return SUCCESS;
898 : }
899 63705 : if (op1->value.lval % op2->value.lval == 0) { /* integer */
900 51429 : result->type = IS_LONG;
901 51429 : result->value.lval = op1->value.lval / op2->value.lval;
902 : } else {
903 12276 : result->type = IS_DOUBLE;
904 12276 : result->value.dval = ((double) op1->value.lval) / op2->value.lval;
905 : }
906 63705 : return SUCCESS;
907 : }
908 3976 : if ((op1->type == IS_DOUBLE && op2->type == IS_LONG)
909 : || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) {
910 3915 : result->value.dval = (op1->type == IS_LONG ?
911 : (((double) op1->value.lval) / op2->value.dval) :
912 : (op1->value.dval / ((double) op2->value.lval)));
913 3915 : result->type = IS_DOUBLE;
914 3915 : return SUCCESS;
915 : }
916 61 : if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) {
917 60 : result->type = IS_DOUBLE;
918 60 : result->value.dval = op1->value.dval / op2->value.dval;
919 60 : return SUCCESS;
920 : }
921 1 : zend_error(E_ERROR, "Unsupported operand types");
922 0 : return FAILURE; /* unknown datatype */
923 : }
924 :
925 :
926 : ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
927 40975 : {
928 : zval op1_copy, op2_copy;
929 :
930 40975 : zendi_convert_to_long(op1, op1_copy, result);
931 40975 : zendi_convert_to_long(op2, op2_copy, result);
932 :
933 40975 : if (op2->value.lval == 0) {
934 43 : zend_error(E_WARNING, "Division by zero");
935 43 : ZVAL_BOOL(result, 0);
936 43 : return FAILURE; /* modulus by zero */
937 : }
938 :
939 40932 : if (op2->value.lval == -1) {
940 : /* Prevent overflow error/crash if op1==LONG_MIN */
941 3 : ZVAL_LONG(result, 0);
942 3 : return SUCCESS;
943 : }
944 :
945 40929 : result->type = IS_LONG;
946 40929 : result->value.lval = op1->value.lval % op2->value.lval;
947 40929 : return SUCCESS;
948 : }
949 :
950 :
951 :
952 : ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
953 0 : {
954 : zval op1_copy, op2_copy;
955 :
956 0 : result->type = IS_BOOL;
957 :
958 0 : zendi_convert_to_boolean(op1, op1_copy, result);
959 0 : zendi_convert_to_boolean(op2, op2_copy, result);
960 0 : result->value.lval = op1->value.lval ^ op2->value.lval;
961 0 : return SUCCESS;
962 : }
963 :
964 :
965 : ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC)
966 2726777 : {
967 : zval op1_copy;
968 :
969 2726777 : zendi_convert_to_boolean(op1, op1_copy, result);
970 :
971 2726777 : result->type = IS_BOOL;
972 2726777 : result->value.lval = !op1->value.lval;
973 2726777 : return SUCCESS;
974 : }
975 :
976 :
977 : ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
978 95 : {
979 95 : zval op1_copy = *op1;
980 :
981 95 : op1 = &op1_copy;
982 :
983 95 : if (op1->type == IS_DOUBLE) {
984 1 : op1->value.lval = (long) op1->value.dval;
985 1 : op1->type = IS_LONG;
986 : }
987 95 : if (op1->type == IS_LONG) {
988 79 : result->value.lval = ~op1->value.lval;
989 79 : result->type = IS_LONG;
990 79 : return SUCCESS;
991 : }
992 16 : if (op1->type == IS_STRING) {
993 : int i;
994 :
995 15 : result->type = IS_STRING;
996 15 : result->value.str.val = estrndup(op1->value.str.val, op1->value.str.len);
997 15 : result->value.str.len = op1->value.str.len;
998 83 : for (i = 0; i < op1->value.str.len; i++) {
999 68 : result->value.str.val[i] = ~op1->value.str.val[i];
1000 : }
1001 15 : return SUCCESS;
1002 : }
1003 1 : zend_error(E_ERROR, "Unsupported operand types");
1004 0 : return FAILURE; /* unknown datatype */
1005 : }
1006 :
1007 :
1008 : ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1009 943 : {
1010 : zval op1_copy, op2_copy;
1011 :
1012 943 : if (op1->type == IS_STRING && op2->type == IS_STRING) {
1013 : zval *longer, *shorter;
1014 : char *result_str;
1015 : int i, result_len;
1016 :
1017 200 : if (op1->value.str.len >= op2->value.str.len) {
1018 117 : longer = op1;
1019 117 : shorter = op2;
1020 : } else {
1021 83 : longer = op2;
1022 83 : shorter = op1;
1023 : }
1024 :
1025 200 : result->type = IS_STRING;
1026 200 : result_len = longer->value.str.len;
1027 200 : result_str = estrndup(longer->value.str.val, longer->value.str.len);
1028 888 : for (i = 0; i < shorter->value.str.len; i++) {
1029 688 : result_str[i] |= shorter->value.str.val[i];
1030 : }
1031 200 : if (result==op1) {
1032 1 : STR_FREE(result->value.str.val);
1033 : }
1034 200 : result->value.str.val = result_str;
1035 200 : result->value.str.len = result_len;
1036 200 : return SUCCESS;
1037 : }
1038 743 : zendi_convert_to_long(op1, op1_copy, result);
1039 743 : zendi_convert_to_long(op2, op2_copy, result);
1040 :
1041 743 : result->type = IS_LONG;
1042 743 : result->value.lval = op1->value.lval | op2->value.lval;
1043 743 : return SUCCESS;
1044 : }
1045 :
1046 :
1047 : ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1048 5131 : {
1049 : zval op1_copy, op2_copy;
1050 :
1051 5131 : if (op1->type == IS_STRING && op2->type == IS_STRING) {
1052 : zval *longer, *shorter;
1053 : char *result_str;
1054 : int i, result_len;
1055 :
1056 201 : if (op1->value.str.len >= op2->value.str.len) {
1057 117 : longer = op1;
1058 117 : shorter = op2;
1059 : } else {
1060 84 : longer = op2;
1061 84 : shorter = op1;
1062 : }
1063 :
1064 201 : result->type = IS_STRING;
1065 201 : result_len = shorter->value.str.len;
1066 201 : result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
1067 888 : for (i = 0; i < shorter->value.str.len; i++) {
1068 687 : result_str[i] &= longer->value.str.val[i];
1069 : }
1070 201 : if (result==op1) {
1071 1 : STR_FREE(result->value.str.val);
1072 : }
1073 201 : result->value.str.val = result_str;
1074 201 : result->value.str.len = result_len;
1075 201 : return SUCCESS;
1076 : }
1077 :
1078 :
1079 4930 : zendi_convert_to_long(op1, op1_copy, result);
1080 4930 : zendi_convert_to_long(op2, op2_copy, result);
1081 :
1082 4930 : result->type = IS_LONG;
1083 4930 : result->value.lval = op1->value.lval & op2->value.lval;
1084 4930 : return SUCCESS;
1085 : }
1086 :
1087 :
1088 : ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1089 214 : {
1090 : zval op1_copy, op2_copy;
1091 :
1092 214 : if (op1->type == IS_STRING && op2->type == IS_STRING) {
1093 : zval *longer, *shorter;
1094 : char *result_str;
1095 : int i, result_len;
1096 :
1097 202 : if (op1->value.str.len >= op2->value.str.len) {
1098 118 : longer = op1;
1099 118 : shorter = op2;
1100 : } else {
1101 84 : longer = op2;
1102 84 : shorter = op1;
1103 : }
1104 :
1105 202 : result->type = IS_STRING;
1106 202 : result_len = shorter->value.str.len;
1107 202 : result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
1108 892 : for (i = 0; i < shorter->value.str.len; i++) {
1109 690 : result_str[i] ^= longer->value.str.val[i];
1110 : }
1111 202 : if (result==op1) {
1112 1 : STR_FREE(result->value.str.val);
1113 : }
1114 202 : result->value.str.val = result_str;
1115 202 : result->value.str.len = result_len;
1116 202 : return SUCCESS;
1117 : }
1118 :
1119 12 : zendi_convert_to_long(op1, op1_copy, result);
1120 12 : zendi_convert_to_long(op2, op2_copy, result);
1121 :
1122 12 : result->type = IS_LONG;
1123 12 : result->value.lval = op1->value.lval ^ op2->value.lval;
1124 12 : return SUCCESS;
1125 : }
1126 :
1127 :
1128 : ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1129 3124 : {
1130 : zval op1_copy, op2_copy;
1131 :
1132 3124 : zendi_convert_to_long(op1, op1_copy, result);
1133 3124 : zendi_convert_to_long(op2, op2_copy, result);
1134 3124 : result->value.lval = op1->value.lval << op2->value.lval;
1135 3124 : result->type = IS_LONG;
1136 3124 : return SUCCESS;
1137 : }
1138 :
1139 :
1140 : ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1141 219 : {
1142 : zval op1_copy, op2_copy;
1143 :
1144 219 : zendi_convert_to_long(op1, op1_copy, result);
1145 219 : zendi_convert_to_long(op2, op2_copy, result);
1146 219 : result->value.lval = op1->value.lval >> op2->value.lval;
1147 219 : result->type = IS_LONG;
1148 219 : return SUCCESS;
1149 : }
1150 :
1151 :
1152 :
1153 : /* must support result==op1 */
1154 : ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2)
1155 723687 : {
1156 723687 : result->value.str.len = op1->value.str.len + 1;
1157 723687 : result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1);
1158 723687 : result->value.str.val[result->value.str.len - 1] = (char) op2->value.lval;
1159 723687 : result->value.str.val[result->value.str.len] = 0;
1160 723687 : result->type = IS_STRING;
1161 723687 : return SUCCESS;
1162 : }
1163 :
1164 :
1165 : /* must support result==op1 */
1166 : ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2)
1167 2315117 : {
1168 2315117 : int length = op1->value.str.len + op2->value.str.len;
1169 :
1170 2315117 : result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
1171 2315117 : memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
1172 2315117 : result->value.str.val[length] = 0;
1173 2315117 : result->value.str.len = length;
1174 2315117 : result->type = IS_STRING;
1175 2315117 : return SUCCESS;
1176 : }
1177 :
1178 :
1179 : ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1180 2389618 : {
1181 : zval op1_copy, op2_copy;
1182 2389618 : int use_copy1 = 0, use_copy2 = 0;
1183 :
1184 2389618 : if (op1->type != IS_STRING) {
1185 1311 : zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1186 : }
1187 2389618 : if (op2->type != IS_STRING) {
1188 34867 : zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1189 : }
1190 :
1191 2389618 : if (use_copy1) {
1192 : /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1193 : * we have to free it.
1194 : */
1195 1311 : if (result == op1) {
1196 7 : zval_dtor(op1);
1197 : }
1198 1311 : op1 = &op1_copy;
1199 : }
1200 2389618 : if (use_copy2) {
1201 34867 : op2 = &op2_copy;
1202 : }
1203 2389618 : if (result==op1) { /* special case, perform operations on result */
1204 1930709 : uint res_len = op1->value.str.len + op2->value.str.len;
1205 :
1206 1930709 : result->value.str.val = erealloc(result->value.str.val, res_len+1);
1207 :
1208 1930709 : memcpy(result->value.str.val+result->value.str.len, op2->value.str.val, op2->value.str.len);
1209 1930709 : result->value.str.val[res_len]=0;
1210 1930709 : result->value.str.len = res_len;
1211 : } else {
1212 458909 : result->value.str.len = op1->value.str.len + op2->value.str.len;
1213 458909 : result->value.str.val = (char *) emalloc(result->value.str.len + 1);
1214 458909 : memcpy(result->value.str.val, op1->value.str.val, op1->value.str.len);
1215 458909 : memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
1216 458909 : result->value.str.val[result->value.str.len] = 0;
1217 458909 : result->type = IS_STRING;
1218 : }
1219 2389618 : if (use_copy1) {
1220 1311 : zval_dtor(op1);
1221 : }
1222 2389618 : if (use_copy2) {
1223 34867 : zval_dtor(op2);
1224 : }
1225 2389618 : return SUCCESS;
1226 : }
1227 :
1228 :
1229 : ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1230 636480 : {
1231 : zval op1_copy, op2_copy;
1232 636480 : int use_copy1 = 0, use_copy2 = 0;
1233 :
1234 636480 : if (op1->type != IS_STRING) {
1235 412946 : zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1236 : }
1237 636480 : if (op2->type != IS_STRING) {
1238 484178 : zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1239 : }
1240 :
1241 636480 : if (use_copy1) {
1242 412946 : op1 = &op1_copy;
1243 : }
1244 636480 : if (use_copy2) {
1245 484178 : op2 = &op2_copy;
1246 : }
1247 :
1248 636480 : result->value.lval = zend_binary_zval_strcmp(op1, op2);
1249 636480 : result->type = IS_LONG;
1250 :
1251 636480 : if (use_copy1) {
1252 412946 : zval_dtor(op1);
1253 : }
1254 636480 : if (use_copy2) {
1255 484178 : zval_dtor(op2);
1256 : }
1257 636480 : return SUCCESS;
1258 : }
1259 :
1260 : #if HAVE_STRCOLL
1261 : ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1262 33 : {
1263 : zval op1_copy, op2_copy;
1264 33 : int use_copy1 = 0, use_copy2 = 0;
1265 :
1266 33 : if (op1->type != IS_STRING) {
1267 0 : zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1268 : }
1269 33 : if (op2->type != IS_STRING) {
1270 0 : zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1271 : }
1272 :
1273 33 : if (use_copy1) {
1274 0 : op1 = &op1_copy;
1275 : }
1276 33 : if (use_copy2) {
1277 0 : op2 = &op2_copy;
1278 : }
1279 :
1280 33 : result->value.lval = strcoll(op1->value.str.val, op2->value.str.val);
1281 33 : result->type = IS_LONG;
1282 :
1283 33 : if (use_copy1) {
1284 0 : zval_dtor(op1);
1285 : }
1286 33 : if (use_copy2) {
1287 0 : zval_dtor(op2);
1288 : }
1289 33 : return SUCCESS;
1290 : }
1291 : #endif
1292 :
1293 : ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1294 926 : {
1295 : zval op1_copy, op2_copy;
1296 :
1297 926 : op1_copy = *op1;
1298 926 : zval_copy_ctor(&op1_copy);
1299 :
1300 926 : op2_copy = *op2;
1301 926 : zval_copy_ctor(&op2_copy);
1302 :
1303 926 : convert_to_double(&op1_copy);
1304 926 : convert_to_double(&op2_copy);
1305 :
1306 926 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
1307 :
1308 926 : return SUCCESS;
1309 : }
1310 :
1311 :
1312 : static inline void zend_free_obj_get_result(zval *op)
1313 12578432 : {
1314 12578432 : if (op) {
1315 421 : if (op->refcount == 0) {
1316 1 : zval_dtor(op);
1317 1 : FREE_ZVAL(op);
1318 : } else {
1319 420 : zval_ptr_dtor(&op);
1320 : }
1321 : }
1322 12578432 : }
1323 :
1324 : #define COMPARE_RETURN_AND_FREE(retval) \
1325 : zend_free_obj_get_result(op1_free); \
1326 : zend_free_obj_get_result(op2_free); \
1327 : return retval;
1328 :
1329 : ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1330 6289264 : {
1331 : zval op1_copy, op2_copy;
1332 : zval *op1_free, *op2_free;
1333 6289264 : int op1_obj = Z_TYPE_P(op1) == IS_OBJECT;
1334 6289264 : int op2_obj = Z_TYPE_P(op2) == IS_OBJECT;
1335 : int eq_comp = op1_obj && op2_obj && (Z_OBJ_HANDLER_P(op1,compare_objects)
1336 6289264 : == Z_OBJ_HANDLER_P(op2,compare_objects));
1337 :
1338 6289373 : if (op1_obj && !eq_comp) {
1339 269 : if (Z_TYPE_P(op2) == IS_NULL) {
1340 48 : ZVAL_LONG(result, 1);
1341 48 : return SUCCESS;
1342 221 : } else if (Z_OBJ_HT_P(op1)->get) {
1343 1 : op1 = op1_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
1344 327 : } else if (!op2_obj && Z_OBJ_HT_P(op1)->cast_object) {
1345 219 : ALLOC_INIT_ZVAL(op1_free);
1346 219 : if (Z_OBJ_HT_P(op1)->cast_object(op1, op1_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
1347 112 : op2_free = NULL;
1348 112 : ZVAL_LONG(result, 1);
1349 112 : COMPARE_RETURN_AND_FREE(SUCCESS);
1350 : }
1351 107 : op1 = op1_free;
1352 : } else {
1353 1 : op1_free = NULL;
1354 : }
1355 109 : op1_obj = Z_TYPE_P(op1) == IS_OBJECT;
1356 109 : eq_comp = op1_obj && op2_obj && (Z_OBJ_HANDLER_P(op1,compare_objects)
1357 : == Z_OBJ_HANDLER_P(op2,compare_objects));
1358 : } else {
1359 6288995 : op1_free = NULL;
1360 : }
1361 6289199 : if (op2_obj && !eq_comp) {
1362 217 : if (Z_TYPE_P(op1) == IS_NULL) {
1363 15 : op2_free = NULL;
1364 15 : ZVAL_LONG(result, -1);
1365 15 : COMPARE_RETURN_AND_FREE(SUCCESS);
1366 202 : } else if (Z_OBJ_HT_P(op2)->get) {
1367 0 : op2 = op2_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
1368 296 : } else if (!op1_obj && Z_OBJ_HT_P(op2)->cast_object) {
1369 201 : ALLOC_INIT_ZVAL(op2_free);
1370 201 : if (Z_OBJ_HT_P(op2)->cast_object(op2, op2_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
1371 107 : ZVAL_LONG(result, -1);
1372 107 : COMPARE_RETURN_AND_FREE(SUCCESS);
1373 : }
1374 94 : op2 = op2_free;
1375 : } else {
1376 1 : op2_free = NULL;
1377 : }
1378 95 : op2_obj = Z_TYPE_P(op2) == IS_OBJECT;
1379 95 : eq_comp = op1_obj && op2_obj && (Z_OBJ_HANDLER_P(op1,compare_objects)
1380 : == Z_OBJ_HANDLER_P(op2,compare_objects));
1381 : } else {
1382 6288887 : op2_free = NULL;
1383 : }
1384 :
1385 6288982 : if ((Z_TYPE_P(op1) == IS_NULL && Z_TYPE_P(op2) == IS_STRING)
1386 : || (Z_TYPE_P(op2) == IS_NULL && Z_TYPE_P(op1) == IS_STRING)) {
1387 225 : if (Z_TYPE_P(op1) == IS_NULL) {
1388 96 : ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1389 96 : COMPARE_RETURN_AND_FREE(SUCCESS);
1390 : } else {
1391 129 : ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
1392 129 : COMPARE_RETURN_AND_FREE(SUCCESS);
1393 : }
1394 : }
1395 :
1396 6288757 : if (op1->type == IS_STRING && op2->type == IS_STRING) {
1397 796849 : zendi_smart_strcmp(result, op1, op2);
1398 796849 : COMPARE_RETURN_AND_FREE(SUCCESS);
1399 : }
1400 :
1401 5491908 : if (Z_TYPE_P(op1) == IS_BOOL || Z_TYPE_P(op2) == IS_BOOL
1402 : || Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op2) == IS_NULL) {
1403 8148 : zendi_convert_to_boolean(op1, op1_copy, result);
1404 8148 : zendi_convert_to_boolean(op2, op2_copy, result);
1405 8148 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1406 8148 : COMPARE_RETURN_AND_FREE(SUCCESS);
1407 : }
1408 :
1409 : /* If both are objects sharing the same comparision handler then use is */
1410 5483760 : if (eq_comp) {
1411 383 : if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
1412 : /* object handles are identical, apprently this is the same object */
1413 23 : ZVAL_LONG(result, 0);
1414 23 : COMPARE_RETURN_AND_FREE(SUCCESS);
1415 : }
1416 360 : ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
1417 360 : COMPARE_RETURN_AND_FREE(SUCCESS);
1418 : }
1419 :
1420 5483377 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1421 5483377 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1422 :
1423 5483377 : if (Z_TYPE_P(op1) == IS_LONG && Z_TYPE_P(op2) == IS_LONG) {
1424 5405742 : ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1425 5405742 : COMPARE_RETURN_AND_FREE(SUCCESS);
1426 : }
1427 77635 : if ((Z_TYPE_P(op1) == IS_DOUBLE || Z_TYPE_P(op1) == IS_LONG)
1428 : && (Z_TYPE_P(op2) == IS_DOUBLE || Z_TYPE_P(op2) == IS_LONG)) {
1429 76791 : Z_DVAL_P(result) = (Z_TYPE_P(op1) == IS_LONG ? (double) Z_LVAL_P(op1) : Z_DVAL_P(op1)) - (Z_TYPE_P(op2) == IS_LONG ? (double) Z_LVAL_P(op2) : Z_DVAL_P(op2));
1430 76791 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1431 76791 : COMPARE_RETURN_AND_FREE(SUCCESS);
1432 : }
1433 844 : if (Z_TYPE_P(op1)==IS_ARRAY && Z_TYPE_P(op2)==IS_ARRAY) {
1434 293 : zend_compare_arrays(result, op1, op2 TSRMLS_CC);
1435 293 : COMPARE_RETURN_AND_FREE(SUCCESS);
1436 : }
1437 :
1438 551 : if (Z_TYPE_P(op1)==IS_ARRAY) {
1439 271 : ZVAL_LONG(result, 1);
1440 271 : COMPARE_RETURN_AND_FREE(SUCCESS);
1441 : }
1442 280 : if (Z_TYPE_P(op2)==IS_ARRAY) {
1443 280 : ZVAL_LONG(result, -1);
1444 280 : COMPARE_RETURN_AND_FREE(SUCCESS);
1445 : }
1446 0 : if (Z_TYPE_P(op1)==IS_OBJECT) {
1447 0 : ZVAL_LONG(result, 1);
1448 0 : COMPARE_RETURN_AND_FREE(SUCCESS);
1449 : }
1450 0 : if (Z_TYPE_P(op2)==IS_OBJECT) {
1451 0 : ZVAL_LONG(result, -1);
1452 0 : COMPARE_RETURN_AND_FREE(SUCCESS);
1453 : }
1454 :
1455 0 : ZVAL_BOOL(result, 0);
1456 0 : COMPARE_RETURN_AND_FREE(FAILURE);
1457 : }
1458 :
1459 :
1460 : static int hash_zval_identical_function(const zval **z1, const zval **z2)
1461 445 : {
1462 : zval result;
1463 : TSRMLS_FETCH();
1464 :
1465 : /* is_identical_function() returns 1 in case of identity and 0 in case
1466 : * of a difference;
1467 : * whereas this comparison function is expected to return 0 on identity,
1468 : * and non zero otherwise.
1469 : */
1470 445 : if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
1471 0 : return 1;
1472 : }
1473 445 : return !result.value.lval;
1474 : }
1475 :
1476 :
1477 : ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1478 1918208 : {
1479 1918208 : result->type = IS_BOOL;
1480 1918208 : if (op1->type != op2->type) {
1481 1258299 : result->value.lval = 0;
1482 1258299 : return SUCCESS;
1483 : }
1484 659909 : switch (op1->type) {
1485 : case IS_NULL:
1486 198 : result->value.lval = (op2->type==IS_NULL);
1487 198 : break;
1488 : case IS_BOOL:
1489 : case IS_LONG:
1490 : case IS_RESOURCE:
1491 651124 : result->value.lval = (op1->value.lval == op2->value.lval);
1492 651124 : break;
1493 : case IS_DOUBLE:
1494 186 : result->value.lval = (op1->value.dval == op2->value.dval);
1495 186 : break;
1496 : case IS_STRING:
1497 8600 : if ((op1->value.str.len == op2->value.str.len)
1498 : && (!memcmp(op1->value.str.val, op2->value.str.val, op1->value.str.len))) {
1499 256 : result->value.lval = 1;
1500 : } else {
1501 8088 : result->value.lval = 0;
1502 : }
1503 8344 : break;
1504 : case IS_ARRAY:
1505 40 : if (zend_hash_compare(op1->value.ht, op2->value.ht, (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) {
1506 33 : result->value.lval = 1;
1507 : } else {
1508 7 : result->value.lval = 0;
1509 : }
1510 40 : break;
1511 : case IS_OBJECT:
1512 17 : if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
1513 17 : if (EG(ze1_compatibility_mode)) {
1514 0 : zend_compare_objects(result, op1, op2 TSRMLS_CC);
1515 : /* comparison returns 0 in case of equality and
1516 : * 1 in case of ineqaulity, we need to reverse it
1517 : */
1518 0 : result->value.lval = !result->value.lval;
1519 : } else {
1520 17 : result->value.lval = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
1521 : }
1522 : } else {
1523 0 : result->value.lval = 0;
1524 : }
1525 17 : break;
1526 : default:
1527 0 : ZVAL_BOOL(result, 0);
1528 0 : return FAILURE;
1529 : }
1530 659909 : return SUCCESS;
1531 : }
1532 :
1533 :
1534 : ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1535 345560 : {
1536 345560 : result->type = IS_BOOL;
1537 345560 : if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1538 0 : return FAILURE;
1539 : }
1540 345560 : result->value.lval = !result->value.lval;
1541 345560 : return SUCCESS;
1542 : }
1543 :
1544 :
1545 : ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1546 1540315 : {
1547 1540315 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1548 0 : return FAILURE;
1549 : }
1550 1540315 : convert_to_boolean(result);
1551 1540315 : if (result->value.lval == 0) {
1552 421039 : result->value.lval = 1;
1553 : } else {
1554 1119276 : result->value.lval = 0;
1555 : }
1556 1540315 : return SUCCESS;
1557 : }
1558 :
1559 :
1560 : ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1561 119951 : {
1562 119951 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1563 0 : return FAILURE;
1564 : }
1565 119951 : convert_to_boolean(result);
1566 119951 : if (result->value.lval) {
1567 19730 : result->value.lval = 1;
1568 : } else {
1569 100221 : result->value.lval = 0;
1570 : }
1571 119951 : return SUCCESS;
1572 : }
1573 :
1574 :
1575 : ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1576 4310305 : {
1577 4310305 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1578 0 : return FAILURE;
1579 : }
1580 4310305 : if (result->type == IS_LONG) {
1581 4310305 : result->type = IS_BOOL;
1582 4310305 : if (result->value.lval < 0) {
1583 3952625 : result->value.lval = 1;
1584 : } else {
1585 357680 : result->value.lval = 0;
1586 : }
1587 4310305 : return SUCCESS;
1588 : }
1589 0 : if (result->type == IS_DOUBLE) {
1590 0 : result->type = IS_BOOL;
1591 0 : if (result->value.dval < 0) {
1592 0 : result->value.lval = 1;
1593 : } else {
1594 0 : result->value.lval = 0;
1595 : }
1596 0 : return SUCCESS;
1597 : }
1598 0 : zend_error(E_ERROR, "Unsupported operand types");
1599 0 : return FAILURE;
1600 : }
1601 :
1602 :
1603 : ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1604 312831 : {
1605 312831 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1606 0 : return FAILURE;
1607 : }
1608 312831 : if (result->type == IS_LONG) {
1609 312831 : result->type = IS_BOOL;
1610 312831 : if (result->value.lval <= 0) {
1611 259172 : result->value.lval = 1;
1612 : } else {
1613 53659 : result->value.lval = 0;
1614 : }
1615 312831 : return SUCCESS;
1616 : }
1617 0 : if (result->type == IS_DOUBLE) {
1618 0 : result->type = IS_BOOL;
1619 0 : if (result->value.dval <= 0) {
1620 0 : result->value.lval = 1;
1621 : } else {
1622 0 : result->value.lval = 0;
1623 : }
1624 0 : return SUCCESS;
1625 : }
1626 0 : zend_error(E_ERROR, "Unsupported operand types");
1627 0 : return FAILURE;
1628 : }
1629 :
1630 :
1631 : ZEND_API zend_bool instanceof_function_ex(zend_class_entry *instance_ce, zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC)
1632 27826 : {
1633 : zend_uint i;
1634 :
1635 41641 : for (i=0; i<instance_ce->num_interfaces; i++) {
1636 15406 : if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
1637 1591 : return 1;
1638 : }
1639 : }
1640 26235 : if (!interfaces_only) {
1641 72524 : while (instance_ce) {
1642 30117 : if (instance_ce == ce) {
1643 10061 : return 1;
1644 : }
1645 20056 : instance_ce = instance_ce->parent;
1646 : }
1647 : }
1648 :
1649 16174 : return 0;
1650 : }
1651 :
1652 : ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, zend_class_entry *ce TSRMLS_DC)
1653 27580 : {
1654 27580 : return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
1655 : }
1656 :
1657 : #define LOWER_CASE 1
1658 : #define UPPER_CASE 2
1659 : #define NUMERIC 3
1660 :
1661 :
1662 : static void increment_string(zval *str)
1663 40 : {
1664 40 : int carry=0;
1665 40 : int pos=str->value.str.len-1;
1666 40 : char *s=str->value.str.val;
1667 : char *t;
1668 40 : int last=0; /* Shut up the compiler warning */
1669 : int ch;
1670 :
1671 40 : if (str->value.str.len == 0) {
1672 1 : STR_FREE(str->value.str.val);
1673 1 : str->value.str.val = estrndup("1", sizeof("1")-1);
1674 1 : str->value.str.len = 1;
1675 1 : return;
1676 : }
1677 :
1678 82 : while (pos >= 0) {
1679 43 : ch = s[pos];
1680 74 : if (ch >= 'a' && ch <= 'z') {
1681 31 : if (ch == 'z') {
1682 2 : s[pos] = 'a';
1683 2 : carry=1;
1684 : } else {
1685 29 : s[pos]++;
1686 29 : carry=0;
1687 : }
1688 31 : last=LOWER_CASE;
1689 18 : } else if (ch >= 'A' && ch <= 'Z') {
1690 6 : if (ch == 'Z') {
1691 0 : s[pos] = 'A';
1692 0 : carry=1;
1693 : } else {
1694 6 : s[pos]++;
1695 6 : carry=0;
1696 : }
1697 6 : last=UPPER_CASE;
1698 8 : } else if (ch >= '0' && ch <= '9') {
1699 2 : if (ch == '9') {
1700 2 : s[pos] = '0';
1701 2 : carry=1;
1702 : } else {
1703 0 : s[pos]++;
1704 0 : carry=0;
1705 : }
1706 2 : last = NUMERIC;
1707 : } else {
1708 4 : carry=0;
1709 4 : break;
1710 : }
1711 39 : if (carry == 0) {
1712 35 : break;
1713 : }
1714 4 : pos--;
1715 : }
1716 :
1717 39 : if (carry) {
1718 0 : t = (char *) emalloc(str->value.str.len+1+1);
1719 0 : memcpy(t+1, str->value.str.val, str->value.str.len);
1720 0 : str->value.str.len++;
1721 0 : t[str->value.str.len] = '\0';
1722 0 : switch (last) {
1723 : case NUMERIC:
1724 0 : t[0] = '1';
1725 0 : break;
1726 : case UPPER_CASE:
1727 0 : t[0] = 'A';
1728 0 : break;
1729 : case LOWER_CASE:
1730 0 : t[0] = 'a';
1731 : break;
1732 : }
1733 0 : STR_FREE(str->value.str.val);
1734 0 : str->value.str.val = t;
1735 : }
1736 : }
1737 :
1738 :
1739 : ZEND_API int increment_function(zval *op1)
1740 4311474 : {
1741 4311474 : switch (op1->type) {
1742 : case IS_LONG:
1743 4311296 : if (op1->value.lval == LONG_MAX) {
1744 : /* switch to double */
1745 2 : double d = (double)op1->value.lval;
1746 2 : ZVAL_DOUBLE(op1, d+1);
1747 : } else {
1748 4311294 : op1->value.lval++;
1749 : }
1750 4311296 : break;
1751 : case IS_DOUBLE:
1752 1 : op1->value.dval = op1->value.dval + 1;
1753 1 : break;
1754 : case IS_NULL:
1755 17 : op1->value.lval = 1;
1756 17 : op1->type = IS_LONG;
1757 17 : break;
1758 : case IS_STRING: {
1759 : long lval;
1760 : double dval;
1761 155 : char *strval = op1->value.str.val;
1762 :
1763 155 : switch (is_numeric_string(strval, op1->value.str.len, &lval, &dval, 0)) {
1764 : case IS_LONG:
1765 108 : if (lval == LONG_MAX) {
1766 : /* switch to double */
1767 1 : double d = (double)lval;
1768 1 : ZVAL_DOUBLE(op1, d+1);
1769 : } else {
1770 107 : op1->value.lval = lval+1;
1771 107 : op1->type = IS_LONG;
1772 : }
1773 108 : efree(strval); /* should never be empty_string */
1774 108 : break;
1775 : case IS_DOUBLE:
1776 7 : op1->value.dval = dval+1;
1777 7 : op1->type = IS_DOUBLE;
1778 7 : efree(strval); /* should never be empty_string */
1779 7 : break;
1780 : default:
1781 : /* Perl style string increment */
1782 40 : increment_string(op1);
1783 : break;
1784 : }
1785 : }
1786 155 : break;
1787 : default:
1788 5 : return FAILURE;
1789 : }
1790 4311469 : return SUCCESS;
1791 : }
1792 :
1793 :
1794 : ZEND_API int decrement_function(zval *op1)
1795 910617 : {
1796 : long lval;
1797 : double dval;
1798 :
1799 910617 : switch (op1->type) {
1800 : case IS_LONG:
1801 561592 : if (op1->value.lval == LONG_MIN) {
1802 1 : double d = (double)op1->value.lval;
1803 1 : ZVAL_DOUBLE(op1, d-1);
1804 : } else {
1805 561591 : op1->value.lval--;
1806 : }
1807 561592 : break;
1808 : case IS_DOUBLE:
1809 348986 : op1->value.dval = op1->value.dval - 1;
1810 348986 : break;
1811 : case IS_STRING: /* Like perl we only support string increment */
1812 33 : if (op1->value.str.len == 0) { /* consider as 0 */
1813 1 : STR_FREE(op1->value.str.val);
1814 1 : op1->value.lval = -1;
1815 1 : op1->type = IS_LONG;
1816 1 : break;
1817 : }
1818 32 : switch (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, &dval, 0)) {
1819 : case IS_LONG:
1820 8 : STR_FREE(op1->value.str.val);
1821 8 : if (lval == LONG_MIN) {
1822 1 : double d = (double)lval;
1823 1 : ZVAL_DOUBLE(op1, d-1);
1824 : } else {
1825 7 : op1->value.lval = lval-1;
1826 7 : op1->type = IS_LONG;
1827 : }
1828 8 : break;
1829 : case IS_DOUBLE:
1830 7 : STR_FREE(op1->value.str.val);
1831 7 : op1->value.dval = dval - 1;
1832 7 : op1->type = IS_DOUBLE;
1833 : break;
1834 : }
1835 32 : break;
1836 : default:
1837 6 : return FAILURE;
1838 : }
1839 :
1840 910611 : return SUCCESS;
1841 : }
1842 :
1843 :
1844 : ZEND_API int zval_is_true(zval *op)
1845 3378 : {
1846 3378 : convert_to_boolean(op);
1847 3378 : return (op->value.lval ? 1 : 0);
1848 : }
1849 :
1850 : #ifdef ZEND_USE_TOLOWER_L
1851 : ZEND_API void zend_update_current_locale(void)
1852 : {
1853 : current_locale = _get_current_locale();
1854 : }
1855 : #endif
1856 :
1857 : ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length)
1858 46463204 : {
1859 46463204 : register unsigned char *str = (unsigned char*)source;
1860 46463204 : register unsigned char *result = (unsigned char*)dest;
1861 46463204 : register unsigned char *end = str + length;
1862 :
1863 709643047 : while (str < end) {
1864 616716639 : *result++ = zend_tolower((int)*str++);
1865 : }
1866 46463204 : *result = '\0';
1867 :
1868 46463204 : return dest;
1869 : }
1870 :
1871 : ZEND_API void zend_str_tolower(char *str, unsigned int length)
1872 1492009 : {
1873 1492009 : register unsigned char *p = (unsigned char*)str;
1874 1492009 : register unsigned char *end = p + length;
1875 :
1876 16622628 : while (p < end) {
1877 13638610 : *p = zend_tolower((int)*p);
1878 13638610 : p++;
1879 : }
1880 1492009 : }
1881 :
1882 : ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2)
1883 1985650 : {
1884 : int retval;
1885 :
1886 1985650 : retval = memcmp(s1, s2, MIN(len1, len2));
1887 1985650 : if (!retval) {
1888 832448 : return (len1 - len2);
1889 : } else {
1890 1153202 : return retval;
1891 : }
1892 : }
1893 :
1894 : ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint length)
1895 9808 : {
1896 : int retval;
1897 :
1898 9808 : retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
1899 9808 : if (!retval) {
1900 9576 : return (MIN(length, len1) - MIN(length, len2));
1901 : } else {
1902 232 : return retval;
1903 : }
1904 : }
1905 :
1906 :
1907 : ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2)
1908 26892 : {
1909 : int len;
1910 : int c1, c2;
1911 :
1912 26892 : len = MIN(len1, len2);
1913 :
1914 112083 : while (len--) {
1915 84693 : c1 = zend_tolower((int)*(unsigned char *)s1++);
1916 84693 : c2 = zend_tolower((int)*(unsigned char *)s2++);
1917 84693 : if (c1 != c2) {
1918 26394 : return c1 - c2;
1919 : }
1920 : }
1921 :
1922 498 : return len1 - len2;
1923 : }
1924 :
1925 :
1926 : ZEND_API int zend_binary_strncasecmp(char *s1, uint len1, char *s2, uint len2, uint length)
1927 13788 : {
1928 : int len;
1929 : int c1, c2;
1930 :
1931 13788 : len = MIN(length, MIN(len1, len2));
1932 :
1933 33569 : while (len--) {
1934 6234 : c1 = zend_tolower((int)*(unsigned char *)s1++);
1935 6234 : c2 = zend_tolower((int)*(unsigned char *)s2++);
1936 6234 : if (c1 != c2) {
1937 241 : return c1 - c2;
1938 : }
1939 : }
1940 :
1941 13547 : return MIN(length, len1) - MIN(length, len2);
1942 : }
1943 :
1944 :
1945 : ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2)
1946 1985425 : {
1947 1985425 : return zend_binary_strcmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len);
1948 : }
1949 :
1950 : ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3)
1951 9781 : {
1952 9781 : return zend_binary_strncmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len, s3->value.lval);
1953 : }
1954 :
1955 :
1956 : ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2)
1957 1030 : {
1958 1030 : return zend_binary_strcasecmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len);
1959 : }
1960 :
1961 :
1962 : ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3)
1963 13759 : {
1964 13759 : return zend_binary_strncasecmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len, s3->value.lval);
1965 : }
1966 :
1967 :
1968 : ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
1969 796849 : {
1970 : int ret1, ret2;
1971 : long lval1, lval2;
1972 : double dval1, dval2;
1973 :
1974 1096899 : if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1, 0)) &&
1975 : (ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0))) {
1976 400071 : if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
1977 100021 : if (ret1!=IS_DOUBLE) {
1978 24 : dval1 = (double) lval1;
1979 99997 : } else if (ret2!=IS_DOUBLE) {
1980 20 : dval2 = (double) lval2;
1981 99977 : } else if (dval1 == dval2 && !zend_finite(dval1)) {
1982 : /* Both values overflowed and have the same sign,
1983 : * so a numeric comparison would be inaccurate */
1984 0 : goto string_cmp;
1985 : }
1986 100021 : result->value.dval = dval1 - dval2;
1987 100021 : result->value.lval = ZEND_NORMALIZE_BOOL(result->value.dval);
1988 100021 : result->type = IS_LONG;
1989 : } else { /* they both have to be long's */
1990 200029 : result->value.lval = lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0);
1991 200029 : result->type = IS_LONG;
1992 : }
1993 : } else {
1994 496799 : string_cmp:
1995 496799 : result->value.lval = zend_binary_zval_strcmp(s1, s2);
1996 496799 : result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
1997 496799 : result->type = IS_LONG;
1998 : }
1999 : return;
2000 : }
2001 :
2002 :
2003 : static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC)
2004 504 : {
2005 : zval result;
2006 :
2007 504 : if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
2008 0 : return 1;
2009 : }
2010 504 : return result.value.lval;
2011 : }
2012 :
2013 : ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC)
2014 312 : {
2015 312 : return zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2016 : }
2017 :
2018 :
2019 :
2020 : ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC)
2021 293 : {
2022 293 : result->type = IS_LONG;
2023 293 : result->value.lval = zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2024 293 : }
2025 :
2026 :
2027 : ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC)
2028 293 : {
2029 293 : zend_compare_symbol_tables(result, a1->value.ht, a2->value.ht TSRMLS_CC);
2030 293 : }
2031 :
2032 :
2033 : ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
2034 0 : {
2035 0 : result->type = IS_LONG;
2036 :
2037 0 : if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
2038 0 : result->value.lval = 0;
2039 0 : return;
2040 : }
2041 :
2042 0 : if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2043 0 : result->value.lval = 1;
2044 : } else {
2045 0 : result->value.lval = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
2046 : }
2047 : }
2048 :
2049 : ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
2050 16729 : {
2051 : TSRMLS_FETCH();
2052 :
2053 16729 : op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), (double)op->value.dval);
2054 16729 : }
2055 :
2056 : /*
2057 : * Local variables:
2058 : * tab-width: 4
2059 : * c-basic-offset: 4
2060 : * indent-tabs-mode: t
2061 : * End:
2062 : */
|