1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2017 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 | Dmitry Stogov <dmitry@zend.com> |
18 +----------------------------------------------------------------------+
19 */
20
21 /* $Id$ */
22
23 #include <ctype.h>
24
25 #include "zend.h"
26 #include "zend_operators.h"
27 #include "zend_variables.h"
28 #include "zend_globals.h"
29 #include "zend_list.h"
30 #include "zend_API.h"
31 #include "zend_strtod.h"
32 #include "zend_exceptions.h"
33 #include "zend_closures.h"
34
35 #if ZEND_USE_TOLOWER_L
36 #include <locale.h>
37 static _locale_t current_locale = NULL;
38 /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
39 #define zend_tolower(c) _tolower_l(c, current_locale)
40 #else
41 #define zend_tolower(c) tolower(c)
42 #endif
43
44 #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
45
46 static const unsigned char tolower_map[256] = {
47 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
48 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
49 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
50 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
51 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
52 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
53 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
54 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
55 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
56 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
57 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
58 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
59 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
60 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
61 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
62 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
63 };
64
65 #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)])
66
67 /**
68 * Functions using locale lowercase:
69 zend_binary_strncasecmp_l
70 zend_binary_strcasecmp_l
71 zend_binary_zval_strcasecmp
72 zend_binary_zval_strncasecmp
73 string_compare_function_ex
74 string_case_compare_function
75 * Functions using ascii lowercase:
76 zend_str_tolower_copy
77 zend_str_tolower_dup
78 zend_str_tolower
79 zend_binary_strcasecmp
80 zend_binary_strncasecmp
81 */
82
zend_atoi(const char * str,int str_len)83 ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, int str_len) /* {{{ */
84 {
85 int retval;
86
87 if (!str_len) {
88 str_len = (int)strlen(str);
89 }
90 retval = ZEND_STRTOL(str, NULL, 0);
91 if (str_len>0) {
92 switch (str[str_len-1]) {
93 case 'g':
94 case 'G':
95 retval *= 1024;
96 /* break intentionally missing */
97 case 'm':
98 case 'M':
99 retval *= 1024;
100 /* break intentionally missing */
101 case 'k':
102 case 'K':
103 retval *= 1024;
104 break;
105 }
106 }
107 return retval;
108 }
109 /* }}} */
110
zend_atol(const char * str,int str_len)111 ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len) /* {{{ */
112 {
113 zend_long retval;
114
115 if (!str_len) {
116 str_len = (int)strlen(str);
117 }
118 retval = ZEND_STRTOL(str, NULL, 0);
119 if (str_len>0) {
120 switch (str[str_len-1]) {
121 case 'g':
122 case 'G':
123 retval *= 1024;
124 /* break intentionally missing */
125 case 'm':
126 case 'M':
127 retval *= 1024;
128 /* break intentionally missing */
129 case 'k':
130 case 'K':
131 retval *= 1024;
132 break;
133 }
134 }
135 return retval;
136 }
137 /* }}} */
138
zend_unwrap_reference(zval * op)139 static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
140 {
141 if (Z_REFCOUNT_P(op) == 1) {
142 ZVAL_UNREF(op);
143 } else {
144 Z_DELREF_P(op);
145 ZVAL_COPY(op, Z_REFVAL_P(op));
146 }
147 }
148 /* }}} */
149
convert_scalar_to_number(zval * op)150 ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
151 {
152 try_again:
153 switch (Z_TYPE_P(op)) {
154 case IS_REFERENCE:
155 zend_unwrap_reference(op);
156 goto try_again;
157 case IS_STRING:
158 {
159 zend_string *str;
160
161 str = Z_STR_P(op);
162 if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
163 ZVAL_LONG(op, 0);
164 }
165 zend_string_release(str);
166 break;
167 }
168 case IS_NULL:
169 case IS_FALSE:
170 ZVAL_LONG(op, 0);
171 break;
172 case IS_TRUE:
173 ZVAL_LONG(op, 1);
174 break;
175 case IS_RESOURCE:
176 {
177 zend_long l = Z_RES_HANDLE_P(op);
178 zval_ptr_dtor(op);
179 ZVAL_LONG(op, l);
180 }
181 break;
182 case IS_OBJECT:
183 convert_to_long_base(op, 10);
184 break;
185 }
186 }
187 /* }}} */
188
189 /* {{{ zendi_convert_scalar_to_number */
190 #define zendi_convert_scalar_to_number(op, holder, result) \
191 if (Z_TYPE_P(op) != IS_LONG) { \
192 if (op==result && Z_TYPE_P(op) != IS_OBJECT) { \
193 convert_scalar_to_number(op); \
194 } else { \
195 switch (Z_TYPE_P(op)) { \
196 case IS_STRING: \
197 if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
198 ZVAL_LONG(&(holder), 0); \
199 } \
200 (op) = &(holder); \
201 break; \
202 case IS_NULL: \
203 case IS_FALSE: \
204 ZVAL_LONG(&(holder), 0); \
205 (op) = &(holder); \
206 break; \
207 case IS_TRUE: \
208 ZVAL_LONG(&(holder), 1); \
209 (op) = &(holder); \
210 break; \
211 case IS_RESOURCE: \
212 ZVAL_LONG(&(holder), Z_RES_HANDLE_P(op)); \
213 (op) = &(holder); \
214 break; \
215 case IS_OBJECT: \
216 ZVAL_COPY(&(holder), op); \
217 convert_to_long_base(&(holder), 10); \
218 if (UNEXPECTED(EG(exception))) { \
219 return FAILURE; \
220 } \
221 if (Z_TYPE(holder) == IS_LONG) { \
222 if (op == result) { \
223 zval_ptr_dtor(op); \
224 ZVAL_LONG(op, Z_LVAL(holder)); \
225 } else { \
226 (op) = &(holder); \
227 } \
228 } \
229 break; \
230 } \
231 } \
232 }
233
234 /* }}} */
235
236 /* {{{ convert_object_to_type: dst will be either ctype or UNDEF */
237 #define convert_object_to_type(op, dst, ctype, conv_func) \
238 ZVAL_UNDEF(dst); \
239 if (Z_OBJ_HT_P(op)->cast_object) { \
240 if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \
241 zend_error(E_RECOVERABLE_ERROR, \
242 "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\
243 zend_get_type_by_const(ctype)); \
244 } \
245 } else if (Z_OBJ_HT_P(op)->get) { \
246 zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \
247 if (Z_TYPE_P(newop) != IS_OBJECT) { \
248 /* for safety - avoid loop */ \
249 ZVAL_COPY_VALUE(dst, newop); \
250 conv_func(dst); \
251 } \
252 }
253
254 /* }}} */
255
256 #define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, op, op_func) \
257 do { \
258 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \
259 if (Z_ISREF_P(op1)) { \
260 op1 = Z_REFVAL_P(op1); \
261 if (Z_TYPE_P(op1) == IS_LONG) { \
262 op1_lval = Z_LVAL_P(op1); \
263 break; \
264 } \
265 } \
266 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func); \
267 op1_lval = _zval_get_long_func(op1); \
268 if (UNEXPECTED(EG(exception))) { \
269 return FAILURE; \
270 } \
271 } else { \
272 op1_lval = Z_LVAL_P(op1); \
273 } \
274 } while (0); \
275 do { \
276 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { \
277 if (Z_ISREF_P(op2)) { \
278 op2 = Z_REFVAL_P(op2); \
279 if (Z_TYPE_P(op2) == IS_LONG) { \
280 op2_lval = Z_LVAL_P(op2); \
281 break; \
282 } \
283 } \
284 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op); \
285 op2_lval = _zval_get_long_func(op2); \
286 if (UNEXPECTED(EG(exception))) { \
287 return FAILURE; \
288 } \
289 } else { \
290 op2_lval = Z_LVAL_P(op2); \
291 } \
292 } while (0);
293
convert_to_long(zval * op)294 ZEND_API void ZEND_FASTCALL convert_to_long(zval *op) /* {{{ */
295 {
296 if (Z_TYPE_P(op) != IS_LONG) {
297 convert_to_long_base(op, 10);
298 }
299 }
300 /* }}} */
301
convert_to_long_base(zval * op,int base)302 ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */
303 {
304 zend_long tmp;
305
306 try_again:
307 switch (Z_TYPE_P(op)) {
308 case IS_NULL:
309 case IS_FALSE:
310 ZVAL_LONG(op, 0);
311 break;
312 case IS_TRUE:
313 ZVAL_LONG(op, 1);
314 break;
315 case IS_RESOURCE:
316 tmp = Z_RES_HANDLE_P(op);
317 zval_ptr_dtor(op);
318 ZVAL_LONG(op, tmp);
319 break;
320 case IS_LONG:
321 break;
322 case IS_DOUBLE:
323 ZVAL_LONG(op, zend_dval_to_lval(Z_DVAL_P(op)));
324 break;
325 case IS_STRING:
326 {
327 zend_string *str = Z_STR_P(op);
328
329 ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base));
330 zend_string_release(str);
331 }
332 break;
333 case IS_ARRAY:
334 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
335 zval_ptr_dtor(op);
336 ZVAL_LONG(op, tmp);
337 break;
338 case IS_OBJECT:
339 {
340 zval dst;
341
342 convert_object_to_type(op, &dst, IS_LONG, convert_to_long);
343 zval_dtor(op);
344
345 if (Z_TYPE(dst) == IS_LONG) {
346 ZVAL_COPY_VALUE(op, &dst);
347 } else {
348
349 ZVAL_LONG(op, 1);
350 }
351 return;
352 }
353 case IS_REFERENCE:
354 zend_unwrap_reference(op);
355 goto try_again;
356 EMPTY_SWITCH_DEFAULT_CASE()
357 }
358 }
359 /* }}} */
360
convert_to_double(zval * op)361 ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
362 {
363 double tmp;
364
365 try_again:
366 switch (Z_TYPE_P(op)) {
367 case IS_NULL:
368 case IS_FALSE:
369 ZVAL_DOUBLE(op, 0.0);
370 break;
371 case IS_TRUE:
372 ZVAL_DOUBLE(op, 1.0);
373 break;
374 case IS_RESOURCE: {
375 double d = (double) Z_RES_HANDLE_P(op);
376 zval_ptr_dtor(op);
377 ZVAL_DOUBLE(op, d);
378 }
379 break;
380 case IS_LONG:
381 ZVAL_DOUBLE(op, (double) Z_LVAL_P(op));
382 break;
383 case IS_DOUBLE:
384 break;
385 case IS_STRING:
386 {
387 zend_string *str = Z_STR_P(op);
388
389 ZVAL_DOUBLE(op, zend_strtod(ZSTR_VAL(str), NULL));
390 zend_string_release(str);
391 }
392 break;
393 case IS_ARRAY:
394 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
395 zval_ptr_dtor(op);
396 ZVAL_DOUBLE(op, tmp);
397 break;
398 case IS_OBJECT:
399 {
400 zval dst;
401
402 convert_object_to_type(op, &dst, IS_DOUBLE, convert_to_double);
403 zval_dtor(op);
404
405 if (Z_TYPE(dst) == IS_DOUBLE) {
406 ZVAL_COPY_VALUE(op, &dst);
407 } else {
408 ZVAL_DOUBLE(op, 1.0);
409 }
410 break;
411 }
412 case IS_REFERENCE:
413 zend_unwrap_reference(op);
414 goto try_again;
415 EMPTY_SWITCH_DEFAULT_CASE()
416 }
417 }
418 /* }}} */
419
convert_to_null(zval * op)420 ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */
421 {
422 if (Z_TYPE_P(op) == IS_OBJECT) {
423 if (Z_OBJ_HT_P(op)->cast_object) {
424 zval org;
425
426 ZVAL_COPY_VALUE(&org, op);
427 if (Z_OBJ_HT_P(op)->cast_object(&org, op, IS_NULL) == SUCCESS) {
428 zval_dtor(&org);
429 return;
430 }
431 ZVAL_COPY_VALUE(op, &org);
432 }
433 }
434
435 zval_ptr_dtor(op);
436 ZVAL_NULL(op);
437 }
438 /* }}} */
439
convert_to_boolean(zval * op)440 ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
441 {
442 int tmp;
443
444 try_again:
445 switch (Z_TYPE_P(op)) {
446 case IS_FALSE:
447 case IS_TRUE:
448 break;
449 case IS_NULL:
450 ZVAL_FALSE(op);
451 break;
452 case IS_RESOURCE: {
453 zend_long l = (Z_RES_HANDLE_P(op) ? 1 : 0);
454
455 zval_ptr_dtor(op);
456 ZVAL_BOOL(op, l);
457 }
458 break;
459 case IS_LONG:
460 ZVAL_BOOL(op, Z_LVAL_P(op) ? 1 : 0);
461 break;
462 case IS_DOUBLE:
463 ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0);
464 break;
465 case IS_STRING:
466 {
467 zend_string *str = Z_STR_P(op);
468
469 if (ZSTR_LEN(str) == 0
470 || (ZSTR_LEN(str) == 1 && ZSTR_VAL(str)[0] == '0')) {
471 ZVAL_FALSE(op);
472 } else {
473 ZVAL_TRUE(op);
474 }
475 zend_string_release(str);
476 }
477 break;
478 case IS_ARRAY:
479 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
480 zval_ptr_dtor(op);
481 ZVAL_BOOL(op, tmp);
482 break;
483 case IS_OBJECT:
484 {
485 zval dst;
486
487 convert_object_to_type(op, &dst, _IS_BOOL, convert_to_boolean);
488 zval_dtor(op);
489
490 if (Z_TYPE(dst) == IS_FALSE || Z_TYPE(dst) == IS_TRUE) {
491 ZVAL_COPY_VALUE(op, &dst);
492 } else {
493 ZVAL_TRUE(op);
494 }
495 break;
496 }
497 case IS_REFERENCE:
498 zend_unwrap_reference(op);
499 goto try_again;
500 EMPTY_SWITCH_DEFAULT_CASE()
501 }
502 }
503 /* }}} */
504
_convert_to_cstring(zval * op ZEND_FILE_LINE_DC)505 ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {{{ */
506 {
507 if (Z_TYPE_P(op) == IS_DOUBLE) {
508 zend_string *str;
509 double dval = Z_DVAL_P(op);
510
511 str = zend_strpprintf(0, "%.*H", (int) EG(precision), dval);
512 ZVAL_NEW_STR(op, str);
513 } else {
514 _convert_to_string(op ZEND_FILE_LINE_CC);
515 }
516 }
517 /* }}} */
518
_convert_to_string(zval * op ZEND_FILE_LINE_DC)519 ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
520 {
521 try_again:
522 switch (Z_TYPE_P(op)) {
523 case IS_UNDEF:
524 case IS_NULL:
525 case IS_FALSE: {
526 ZVAL_EMPTY_STRING(op);
527 break;
528 }
529 case IS_TRUE:
530 if (CG(one_char_string)['1']) {
531 ZVAL_INTERNED_STR(op, CG(one_char_string)['1']);
532 } else {
533 ZVAL_NEW_STR(op, zend_string_init("1", 1, 0));
534 }
535 break;
536 case IS_STRING:
537 break;
538 case IS_RESOURCE: {
539 char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
540 int len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
541 zval_ptr_dtor(op);
542 ZVAL_NEW_STR(op, zend_string_init(buf, len, 0));
543 break;
544 }
545 case IS_LONG: {
546 ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op)));
547 break;
548 }
549 case IS_DOUBLE: {
550 zend_string *str;
551 double dval = Z_DVAL_P(op);
552
553 str = zend_strpprintf(0, "%.*G", (int) EG(precision), dval);
554 /* %G already handles removing trailing zeros from the fractional part, yay */
555 ZVAL_NEW_STR(op, str);
556 break;
557 }
558 case IS_ARRAY:
559 zend_error(E_NOTICE, "Array to string conversion");
560 zval_ptr_dtor(op);
561 ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0));
562 break;
563 case IS_OBJECT: {
564 zval dst;
565
566 convert_object_to_type(op, &dst, IS_STRING, convert_to_string);
567 zval_dtor(op);
568
569 if (Z_TYPE(dst) == IS_STRING) {
570 ZVAL_COPY_VALUE(op, &dst);
571 } else {
572 ZVAL_NEW_STR(op, zend_string_init("Object", sizeof("Object")-1, 0));
573 }
574 break;
575 }
576 case IS_REFERENCE:
577 zend_unwrap_reference(op);
578 goto try_again;
579 EMPTY_SWITCH_DEFAULT_CASE()
580 }
581 }
582 /* }}} */
583
convert_scalar_to_array(zval * op)584 static void convert_scalar_to_array(zval *op) /* {{{ */
585 {
586 zval entry;
587
588 ZVAL_COPY_VALUE(&entry, op);
589
590 ZVAL_NEW_ARR(op);
591 zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
592 zend_hash_index_add_new(Z_ARRVAL_P(op), 0, &entry);
593 }
594 /* }}} */
595
convert_to_array(zval * op)596 ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */
597 {
598 try_again:
599 switch (Z_TYPE_P(op)) {
600 case IS_ARRAY:
601 break;
602 /* OBJECTS_OPTIMIZE */
603 case IS_OBJECT:
604 if (Z_OBJCE_P(op) == zend_ce_closure) {
605 convert_scalar_to_array(op);
606 } else {
607 if (Z_OBJ_HT_P(op)->get_properties) {
608 HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op);
609 if (obj_ht) {
610 zval arr;
611
612 if (!Z_OBJCE_P(op)->default_properties_count &&
613 obj_ht == Z_OBJ_P(op)->properties &&
614 !ZEND_HASH_GET_APPLY_COUNT(Z_OBJ_P(op)->properties)) {
615 /* fast copy */
616 if (EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) {
617 ZVAL_ARR(&arr, obj_ht);
618 if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(op)->properties) & IS_ARRAY_IMMUTABLE))) {
619 GC_REFCOUNT(Z_OBJ_P(op)->properties)++;
620 }
621 } else {
622 ZVAL_ARR(&arr, zend_array_dup(obj_ht));
623 }
624 zval_dtor(op);
625 ZVAL_COPY_VALUE(op, &arr);
626 } else {
627 ZVAL_ARR(&arr, zend_array_dup(obj_ht));
628 zval_dtor(op);
629 ZVAL_COPY_VALUE(op, &arr);
630 }
631 return;
632 }
633 } else {
634 zval dst;
635 convert_object_to_type(op, &dst, IS_ARRAY, convert_to_array);
636
637 if (Z_TYPE(dst) == IS_ARRAY) {
638 zval_dtor(op);
639 ZVAL_COPY_VALUE(op, &dst);
640 return;
641 }
642 }
643
644 zval_dtor(op);
645 array_init(op);
646 }
647 break;
648 case IS_NULL:
649 ZVAL_NEW_ARR(op);
650 zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
651 break;
652 case IS_REFERENCE:
653 zend_unwrap_reference(op);
654 goto try_again;
655 default:
656 convert_scalar_to_array(op);
657 break;
658 }
659 }
660 /* }}} */
661
convert_to_object(zval * op)662 ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
663 {
664 try_again:
665 switch (Z_TYPE_P(op)) {
666 case IS_ARRAY:
667 {
668 HashTable *ht = Z_ARR_P(op);
669 if (Z_IMMUTABLE_P(op)) {
670 /* TODO: try not to duplicate immutable arrays as well ??? */
671 ht = zend_array_dup(ht);
672 }
673 object_and_properties_init(op, zend_standard_class_def, ht);
674 break;
675 }
676 case IS_OBJECT:
677 break;
678 case IS_NULL:
679 object_init(op);
680 break;
681 case IS_REFERENCE:
682 zend_unwrap_reference(op);
683 goto try_again;
684 default: {
685 zval tmp;
686 ZVAL_COPY_VALUE(&tmp, op);
687 object_init(op);
688 zend_hash_str_add_new(Z_OBJPROP_P(op), "scalar", sizeof("scalar")-1, &tmp);
689 break;
690 }
691 }
692 }
693 /* }}} */
694
multi_convert_to_long_ex(int argc,...)695 ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
696 {
697 zval *arg;
698 va_list ap;
699
700 va_start(ap, argc);
701
702 while (argc--) {
703 arg = va_arg(ap, zval *);
704 convert_to_long_ex(arg);
705 }
706
707 va_end(ap);
708 }
709 /* }}} */
710
multi_convert_to_double_ex(int argc,...)711 ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
712 {
713 zval *arg;
714 va_list ap;
715
716 va_start(ap, argc);
717
718 while (argc--) {
719 arg = va_arg(ap, zval *);
720 convert_to_double_ex(arg);
721 }
722
723 va_end(ap);
724 }
725 /* }}} */
726
multi_convert_to_string_ex(int argc,...)727 ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
728 {
729 zval *arg;
730 va_list ap;
731
732 va_start(ap, argc);
733
734 while (argc--) {
735 arg = va_arg(ap, zval *);
736 convert_to_string_ex(arg);
737 }
738
739 va_end(ap);
740 }
741 /* }}} */
742
_zval_get_long_func(zval * op)743 ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */
744 {
745 try_again:
746 switch (Z_TYPE_P(op)) {
747 case IS_NULL:
748 case IS_FALSE:
749 return 0;
750 case IS_TRUE:
751 return 1;
752 case IS_RESOURCE:
753 return Z_RES_HANDLE_P(op);
754 case IS_LONG:
755 return Z_LVAL_P(op);
756 case IS_DOUBLE:
757 return zend_dval_to_lval(Z_DVAL_P(op));
758 case IS_STRING:
759 return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10);
760 case IS_ARRAY:
761 return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
762 case IS_OBJECT:
763 {
764 zval dst;
765 convert_object_to_type(op, &dst, IS_LONG, convert_to_long);
766 if (Z_TYPE(dst) == IS_LONG) {
767 return Z_LVAL(dst);
768 } else {
769 return 1;
770 }
771 }
772 case IS_REFERENCE:
773 op = Z_REFVAL_P(op);
774 goto try_again;
775 EMPTY_SWITCH_DEFAULT_CASE()
776 }
777 return 0;
778 }
779 /* }}} */
780
_zval_get_double_func(zval * op)781 ZEND_API double ZEND_FASTCALL _zval_get_double_func(zval *op) /* {{{ */
782 {
783 try_again:
784 switch (Z_TYPE_P(op)) {
785 case IS_NULL:
786 case IS_FALSE:
787 return 0.0;
788 case IS_TRUE:
789 return 1.0;
790 case IS_RESOURCE:
791 return (double) Z_RES_HANDLE_P(op);
792 case IS_LONG:
793 return (double) Z_LVAL_P(op);
794 case IS_DOUBLE:
795 return Z_DVAL_P(op);
796 case IS_STRING:
797 return zend_strtod(Z_STRVAL_P(op), NULL);
798 case IS_ARRAY:
799 return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1.0 : 0.0;
800 case IS_OBJECT:
801 {
802 zval dst;
803 convert_object_to_type(op, &dst, IS_DOUBLE, convert_to_double);
804
805 if (Z_TYPE(dst) == IS_DOUBLE) {
806 return Z_DVAL(dst);
807 } else {
808 return 1.0;
809 }
810 }
811 case IS_REFERENCE:
812 op = Z_REFVAL_P(op);
813 goto try_again;
814 EMPTY_SWITCH_DEFAULT_CASE()
815 }
816 return 0.0;
817 }
818 /* }}} */
819
_zval_get_string_func(zval * op)820 ZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op) /* {{{ */
821 {
822 try_again:
823 switch (Z_TYPE_P(op)) {
824 case IS_UNDEF:
825 case IS_NULL:
826 case IS_FALSE:
827 return ZSTR_EMPTY_ALLOC();
828 case IS_TRUE:
829 if (CG(one_char_string)['1']) {
830 return CG(one_char_string)['1'];
831 } else {
832 return zend_string_init("1", 1, 0);
833 }
834 case IS_RESOURCE: {
835 char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
836 int len;
837
838 len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
839 return zend_string_init(buf, len, 0);
840 }
841 case IS_LONG: {
842 return zend_long_to_str(Z_LVAL_P(op));
843 }
844 case IS_DOUBLE: {
845 return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
846 }
847 case IS_ARRAY:
848 zend_error(E_NOTICE, "Array to string conversion");
849 return zend_string_init("Array", sizeof("Array")-1, 0);
850 case IS_OBJECT: {
851 zval tmp;
852 if (Z_OBJ_HT_P(op)->cast_object) {
853 if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) {
854 return Z_STR(tmp);
855 }
856 } else if (Z_OBJ_HT_P(op)->get) {
857 zval *z = Z_OBJ_HT_P(op)->get(op, &tmp);
858 if (Z_TYPE_P(z) != IS_OBJECT) {
859 zend_string *str = zval_get_string(z);
860 zval_ptr_dtor(z);
861 return str;
862 }
863 zval_ptr_dtor(z);
864 }
865 zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
866 return ZSTR_EMPTY_ALLOC();
867 }
868 case IS_REFERENCE:
869 op = Z_REFVAL_P(op);
870 goto try_again;
871 case IS_STRING:
872 return zend_string_copy(Z_STR_P(op));
873 EMPTY_SWITCH_DEFAULT_CASE()
874 }
875 return NULL;
876 }
877 /* }}} */
878
add_function(zval * result,zval * op1,zval * op2)879 ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
880 {
881 zval op1_copy, op2_copy;
882 int converted = 0;
883
884 while (1) {
885 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
886 case TYPE_PAIR(IS_LONG, IS_LONG): {
887 zend_long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
888
889 /* check for overflow by comparing sign bits */
890 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
891 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
892
893 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
894 } else {
895 ZVAL_LONG(result, lval);
896 }
897 return SUCCESS;
898 }
899
900 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
901 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
902 return SUCCESS;
903
904 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
905 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
906 return SUCCESS;
907
908 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
909 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
910 return SUCCESS;
911
912 case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
913 if ((result == op1) && (result == op2)) {
914 /* $a += $a */
915 return SUCCESS;
916 }
917 if (result != op1) {
918 ZVAL_DUP(result, op1);
919 }
920 zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
921 return SUCCESS;
922
923 default:
924 if (Z_ISREF_P(op1)) {
925 op1 = Z_REFVAL_P(op1);
926 } else if (Z_ISREF_P(op2)) {
927 op2 = Z_REFVAL_P(op2);
928 } else if (!converted) {
929 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
930
931 if (EXPECTED(op1 != op2)) {
932 zendi_convert_scalar_to_number(op1, op1_copy, result);
933 zendi_convert_scalar_to_number(op2, op2_copy, result);
934 } else {
935 zendi_convert_scalar_to_number(op1, op1_copy, result);
936 op2 = op1;
937 }
938 converted = 1;
939 } else {
940 zend_throw_error(NULL, "Unsupported operand types");
941 return FAILURE; /* unknown datatype */
942 }
943 }
944 }
945 }
946 /* }}} */
947
sub_function(zval * result,zval * op1,zval * op2)948 ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
949 {
950 zval op1_copy, op2_copy;
951 int converted = 0;
952
953 while (1) {
954 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
955 case TYPE_PAIR(IS_LONG, IS_LONG): {
956 zend_long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
957
958 /* check for overflow by comparing sign bits */
959 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
960 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
961
962 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
963 } else {
964 ZVAL_LONG(result, lval);
965 }
966 return SUCCESS;
967
968 }
969 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
970 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
971 return SUCCESS;
972
973 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
974 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
975 return SUCCESS;
976
977 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
978 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
979 return SUCCESS;
980
981 default:
982 if (Z_ISREF_P(op1)) {
983 op1 = Z_REFVAL_P(op1);
984 } else if (Z_ISREF_P(op2)) {
985 op2 = Z_REFVAL_P(op2);
986 } else if (!converted) {
987 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
988
989 if (EXPECTED(op1 != op2)) {
990 zendi_convert_scalar_to_number(op1, op1_copy, result);
991 zendi_convert_scalar_to_number(op2, op2_copy, result);
992 } else {
993 zendi_convert_scalar_to_number(op1, op1_copy, result);
994 op2 = op1;
995 }
996 converted = 1;
997 } else {
998 zend_throw_error(NULL, "Unsupported operand types");
999 return FAILURE; /* unknown datatype */
1000 }
1001 }
1002 }
1003 }
1004 /* }}} */
1005
mul_function(zval * result,zval * op1,zval * op2)1006 ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* {{{ */
1007 {
1008 zval op1_copy, op2_copy;
1009 int converted = 0;
1010
1011 while (1) {
1012 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1013 case TYPE_PAIR(IS_LONG, IS_LONG): {
1014 zend_long overflow;
1015
1016 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
1017 Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
1018 return SUCCESS;
1019
1020 }
1021 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1022 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
1023 return SUCCESS;
1024
1025 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1026 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
1027 return SUCCESS;
1028
1029 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1030 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
1031 return SUCCESS;
1032
1033 default:
1034 if (Z_ISREF_P(op1)) {
1035 op1 = Z_REFVAL_P(op1);
1036 } else if (Z_ISREF_P(op2)) {
1037 op2 = Z_REFVAL_P(op2);
1038 } else if (!converted) {
1039 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function);
1040
1041 if (EXPECTED(op1 != op2)) {
1042 zendi_convert_scalar_to_number(op1, op1_copy, result);
1043 zendi_convert_scalar_to_number(op2, op2_copy, result);
1044 } else {
1045 zendi_convert_scalar_to_number(op1, op1_copy, result);
1046 op2 = op1;
1047 }
1048 converted = 1;
1049 } else {
1050 zend_throw_error(NULL, "Unsupported operand types");
1051 return FAILURE; /* unknown datatype */
1052 }
1053 }
1054 }
1055 }
1056 /* }}} */
1057
pow_function(zval * result,zval * op1,zval * op2)1058 ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* {{{ */
1059 {
1060 zval op1_copy, op2_copy;
1061 int converted = 0;
1062
1063 while (1) {
1064 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1065 case TYPE_PAIR(IS_LONG, IS_LONG):
1066 if (Z_LVAL_P(op2) >= 0) {
1067 zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
1068
1069 if (i == 0) {
1070 ZVAL_LONG(result, 1L);
1071 return SUCCESS;
1072 } else if (l2 == 0) {
1073 ZVAL_LONG(result, 0);
1074 return SUCCESS;
1075 }
1076
1077 while (i >= 1) {
1078 zend_long overflow;
1079 double dval = 0.0;
1080
1081 if (i % 2) {
1082 --i;
1083 ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
1084 if (overflow) {
1085 ZVAL_DOUBLE(result, dval * pow(l2, i));
1086 return SUCCESS;
1087 }
1088 } else {
1089 i /= 2;
1090 ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
1091 if (overflow) {
1092 ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
1093 return SUCCESS;
1094 }
1095 }
1096 }
1097 /* i == 0 */
1098 ZVAL_LONG(result, l1);
1099 } else {
1100 ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
1101 }
1102 return SUCCESS;
1103
1104 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1105 ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
1106 return SUCCESS;
1107
1108 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1109 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
1110 return SUCCESS;
1111
1112 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1113 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
1114 return SUCCESS;
1115
1116 default:
1117 if (Z_ISREF_P(op1)) {
1118 op1 = Z_REFVAL_P(op1);
1119 } else if (Z_ISREF_P(op2)) {
1120 op2 = Z_REFVAL_P(op2);
1121 } else if (!converted) {
1122 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function);
1123
1124 if (EXPECTED(op1 != op2)) {
1125 if (Z_TYPE_P(op1) == IS_ARRAY) {
1126 ZVAL_LONG(result, 0);
1127 return SUCCESS;
1128 } else {
1129 zendi_convert_scalar_to_number(op1, op1_copy, result);
1130 }
1131 if (Z_TYPE_P(op2) == IS_ARRAY) {
1132 ZVAL_LONG(result, 1L);
1133 return SUCCESS;
1134 } else {
1135 zendi_convert_scalar_to_number(op2, op2_copy, result);
1136 }
1137 } else {
1138 if (Z_TYPE_P(op1) == IS_ARRAY) {
1139 ZVAL_LONG(result, 0);
1140 return SUCCESS;
1141 } else {
1142 zendi_convert_scalar_to_number(op1, op1_copy, result);
1143 }
1144 op2 = op1;
1145 }
1146 converted = 1;
1147 } else {
1148 zend_throw_error(NULL, "Unsupported operand types");
1149 return FAILURE;
1150 }
1151 }
1152 }
1153 }
1154 /* }}} */
1155
div_function(zval * result,zval * op1,zval * op2)1156 ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {{{ */
1157 {
1158 zval op1_copy, op2_copy;
1159 int converted = 0;
1160
1161 while (1) {
1162 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1163 case TYPE_PAIR(IS_LONG, IS_LONG):
1164 if (Z_LVAL_P(op2) == 0) {
1165 zend_error(E_WARNING, "Division by zero");
1166 ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1) / (double) Z_LVAL_P(op2)));
1167 return SUCCESS;
1168 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
1169 /* Prevent overflow error/crash */
1170 ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
1171 return SUCCESS;
1172 }
1173 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
1174 ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
1175 } else {
1176 ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1177 }
1178 return SUCCESS;
1179
1180 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1181 if (Z_LVAL_P(op2) == 0) {
1182 zend_error(E_WARNING, "Division by zero");
1183 }
1184 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1185 return SUCCESS;
1186
1187 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1188 if (Z_DVAL_P(op2) == 0) {
1189 zend_error(E_WARNING, "Division by zero");
1190 }
1191 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1192 return SUCCESS;
1193
1194 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1195 if (Z_DVAL_P(op2) == 0) {
1196 zend_error(E_WARNING, "Division by zero");
1197 }
1198 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1199 return SUCCESS;
1200
1201 default:
1202 if (Z_ISREF_P(op1)) {
1203 op1 = Z_REFVAL_P(op1);
1204 } else if (Z_ISREF_P(op2)) {
1205 op2 = Z_REFVAL_P(op2);
1206 } else if (!converted) {
1207 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function);
1208 if (EXPECTED(op1 != op2)) {
1209 zendi_convert_scalar_to_number(op1, op1_copy, result);
1210 zendi_convert_scalar_to_number(op2, op2_copy, result);
1211 } else {
1212 zendi_convert_scalar_to_number(op1, op1_copy, result);
1213 op2 = op1;
1214 }
1215 converted = 1;
1216 } else {
1217 zend_throw_error(NULL, "Unsupported operand types");
1218 return FAILURE; /* unknown datatype */
1219 }
1220 }
1221 }
1222 }
1223 /* }}} */
1224
mod_function(zval * result,zval * op1,zval * op2)1225 ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {{{ */
1226 {
1227 zend_long op1_lval, op2_lval;
1228
1229 convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function);
1230
1231 if (op2_lval == 0) {
1232 /* modulus by zero */
1233 if (EG(current_execute_data) && !CG(in_compilation)) {
1234 zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
1235 } else {
1236 zend_error_noreturn(E_ERROR, "Modulo by zero");
1237 }
1238 if (op1 != result) {
1239 ZVAL_UNDEF(result);
1240 }
1241 return FAILURE;
1242 }
1243
1244 if (op1 == result) {
1245 zval_dtor(result);
1246 }
1247
1248 if (op2_lval == -1) {
1249 /* Prevent overflow error/crash if op1==LONG_MIN */
1250 ZVAL_LONG(result, 0);
1251 return SUCCESS;
1252 }
1253
1254 ZVAL_LONG(result, op1_lval % op2_lval);
1255 return SUCCESS;
1256 }
1257 /* }}} */
1258
boolean_xor_function(zval * result,zval * op1,zval * op2)1259 ZEND_API int ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */
1260 {
1261 int op1_val, op2_val;
1262
1263 do {
1264 if (Z_TYPE_P(op1) == IS_FALSE) {
1265 op1_val = 0;
1266 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1267 op1_val = 1;
1268 } else {
1269 if (Z_ISREF_P(op1)) {
1270 op1 = Z_REFVAL_P(op1);
1271 if (Z_TYPE_P(op1) == IS_FALSE) {
1272 op1_val = 0;
1273 break;
1274 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1275 op1_val = 1;
1276 break;
1277 }
1278 }
1279 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR, boolean_xor_function);
1280 op1_val = zval_is_true(op1);
1281 }
1282 } while (0);
1283 do {
1284 if (Z_TYPE_P(op2) == IS_FALSE) {
1285 op2_val = 0;
1286 } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1287 op2_val = 1;
1288 } else {
1289 if (Z_ISREF_P(op2)) {
1290 op2 = Z_REFVAL_P(op2);
1291 if (Z_TYPE_P(op2) == IS_FALSE) {
1292 op2_val = 0;
1293 break;
1294 } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1295 op2_val = 1;
1296 break;
1297 }
1298 }
1299 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR);
1300 op2_val = zval_is_true(op2);
1301 }
1302 } while (0);
1303
1304 ZVAL_BOOL(result, op1_val ^ op2_val);
1305 return SUCCESS;
1306 }
1307 /* }}} */
1308
boolean_not_function(zval * result,zval * op1)1309 ZEND_API int ZEND_FASTCALL boolean_not_function(zval *result, zval *op1) /* {{{ */
1310 {
1311 if (Z_TYPE_P(op1) < IS_TRUE) {
1312 ZVAL_TRUE(result);
1313 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1314 ZVAL_FALSE(result);
1315 } else {
1316 if (Z_ISREF_P(op1)) {
1317 op1 = Z_REFVAL_P(op1);
1318 if (Z_TYPE_P(op1) < IS_TRUE) {
1319 ZVAL_TRUE(result);
1320 return SUCCESS;
1321 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1322 ZVAL_FALSE(result);
1323 return SUCCESS;
1324 }
1325 }
1326 ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
1327
1328 ZVAL_BOOL(result, !zval_is_true(op1));
1329 }
1330 return SUCCESS;
1331 }
1332 /* }}} */
1333
bitwise_not_function(zval * result,zval * op1)1334 ZEND_API int ZEND_FASTCALL bitwise_not_function(zval *result, zval *op1) /* {{{ */
1335 {
1336 try_again:
1337 switch (Z_TYPE_P(op1)) {
1338 case IS_LONG:
1339 ZVAL_LONG(result, ~Z_LVAL_P(op1));
1340 return SUCCESS;
1341 case IS_DOUBLE:
1342 ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1343 return SUCCESS;
1344 case IS_STRING: {
1345 size_t i;
1346
1347 if (Z_STRLEN_P(op1) == 1) {
1348 zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1);
1349 if (CG(one_char_string)[not]) {
1350 ZVAL_INTERNED_STR(result, CG(one_char_string)[not]);
1351 } else {
1352 ZVAL_NEW_STR(result, zend_string_init((char *) ¬, 1, 0));
1353 }
1354 } else {
1355 ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
1356 for (i = 0; i < Z_STRLEN_P(op1); i++) {
1357 Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1358 }
1359 Z_STRVAL_P(result)[i] = 0;
1360 }
1361 return SUCCESS;
1362 }
1363 case IS_REFERENCE:
1364 op1 = Z_REFVAL_P(op1);
1365 goto try_again;
1366 default:
1367 ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
1368
1369 zend_throw_error(NULL, "Unsupported operand types");
1370 return FAILURE;
1371 }
1372 }
1373 /* }}} */
1374
bitwise_or_function(zval * result,zval * op1,zval * op2)1375 ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2) /* {{{ */
1376 {
1377 zend_long op1_lval, op2_lval;
1378
1379 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1380 ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
1381 return SUCCESS;
1382 }
1383
1384 ZVAL_DEREF(op1);
1385 ZVAL_DEREF(op2);
1386
1387 if (Z_TYPE_P(op1) == IS_STRING && EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1388 zval *longer, *shorter;
1389 zend_string *str;
1390 size_t i;
1391
1392 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1393 if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1394 zend_uchar or = (zend_uchar) (*Z_STRVAL_P(op1) | *Z_STRVAL_P(op2));
1395 if (result==op1) {
1396 zend_string_release(Z_STR_P(result));
1397 }
1398 if (CG(one_char_string)[or]) {
1399 ZVAL_INTERNED_STR(result, CG(one_char_string)[or]);
1400 } else {
1401 ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0));
1402 }
1403 return SUCCESS;
1404 }
1405 longer = op1;
1406 shorter = op2;
1407 } else {
1408 longer = op2;
1409 shorter = op1;
1410 }
1411
1412 str = zend_string_alloc(Z_STRLEN_P(longer), 0);
1413 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1414 ZSTR_VAL(str)[i] = Z_STRVAL_P(longer)[i] | Z_STRVAL_P(shorter)[i];
1415 }
1416 memcpy(ZSTR_VAL(str) + i, Z_STRVAL_P(longer) + i, Z_STRLEN_P(longer) - i + 1);
1417 if (result==op1) {
1418 zend_string_release(Z_STR_P(result));
1419 }
1420 ZVAL_NEW_STR(result, str);
1421 return SUCCESS;
1422 }
1423
1424 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1425 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function);
1426 op1_lval = _zval_get_long_func(op1);
1427 if (UNEXPECTED(EG(exception))) {
1428 return FAILURE;
1429 }
1430 } else {
1431 op1_lval = Z_LVAL_P(op1);
1432 }
1433 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1434 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR);
1435 op2_lval = _zval_get_long_func(op2);
1436 if (UNEXPECTED(EG(exception))) {
1437 return FAILURE;
1438 }
1439 } else {
1440 op2_lval = Z_LVAL_P(op2);
1441 }
1442
1443 if (op1 == result) {
1444 zval_dtor(result);
1445 }
1446 ZVAL_LONG(result, op1_lval | op2_lval);
1447 return SUCCESS;
1448 }
1449 /* }}} */
1450
bitwise_and_function(zval * result,zval * op1,zval * op2)1451 ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2) /* {{{ */
1452 {
1453 zend_long op1_lval, op2_lval;
1454
1455 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1456 ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
1457 return SUCCESS;
1458 }
1459
1460 ZVAL_DEREF(op1);
1461 ZVAL_DEREF(op2);
1462
1463 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1464 zval *longer, *shorter;
1465 zend_string *str;
1466 size_t i;
1467
1468 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1469 if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1470 zend_uchar and = (zend_uchar) (*Z_STRVAL_P(op1) & *Z_STRVAL_P(op2));
1471 if (result==op1) {
1472 zend_string_release(Z_STR_P(result));
1473 }
1474 if (CG(one_char_string)[and]) {
1475 ZVAL_INTERNED_STR(result, CG(one_char_string)[and]);
1476 } else {
1477 ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0));
1478 }
1479 return SUCCESS;
1480 }
1481 longer = op1;
1482 shorter = op2;
1483 } else {
1484 longer = op2;
1485 shorter = op1;
1486 }
1487
1488 str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1489 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1490 ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] & Z_STRVAL_P(longer)[i];
1491 }
1492 ZSTR_VAL(str)[i] = 0;
1493 if (result==op1) {
1494 zend_string_release(Z_STR_P(result));
1495 }
1496 ZVAL_NEW_STR(result, str);
1497 return SUCCESS;
1498 }
1499
1500 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1501 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
1502 op1_lval = _zval_get_long_func(op1);
1503 if (UNEXPECTED(EG(exception))) {
1504 return FAILURE;
1505 }
1506 } else {
1507 op1_lval = Z_LVAL_P(op1);
1508 }
1509 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1510 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND);
1511 op2_lval = _zval_get_long_func(op2);
1512 if (UNEXPECTED(EG(exception))) {
1513 return FAILURE;
1514 }
1515 } else {
1516 op2_lval = Z_LVAL_P(op2);
1517 }
1518
1519 if (op1 == result) {
1520 zval_dtor(result);
1521 }
1522 ZVAL_LONG(result, op1_lval & op2_lval);
1523 return SUCCESS;
1524 }
1525 /* }}} */
1526
bitwise_xor_function(zval * result,zval * op1,zval * op2)1527 ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */
1528 {
1529 zend_long op1_lval, op2_lval;
1530
1531 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1532 ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
1533 return SUCCESS;
1534 }
1535
1536 ZVAL_DEREF(op1);
1537 ZVAL_DEREF(op2);
1538
1539 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1540 zval *longer, *shorter;
1541 zend_string *str;
1542 size_t i;
1543
1544 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1545 if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1546 zend_uchar xor = (zend_uchar) (*Z_STRVAL_P(op1) ^ *Z_STRVAL_P(op2));
1547 if (result==op1) {
1548 zend_string_release(Z_STR_P(result));
1549 }
1550 if (CG(one_char_string)[xor]) {
1551 ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]);
1552 } else {
1553 ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0));
1554 }
1555 return SUCCESS;
1556 }
1557 longer = op1;
1558 shorter = op2;
1559 } else {
1560 longer = op2;
1561 shorter = op1;
1562 }
1563
1564 str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1565 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1566 ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] ^ Z_STRVAL_P(longer)[i];
1567 }
1568 ZSTR_VAL(str)[i] = 0;
1569 if (result==op1) {
1570 zend_string_release(Z_STR_P(result));
1571 }
1572 ZVAL_NEW_STR(result, str);
1573 return SUCCESS;
1574 }
1575
1576 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1577 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
1578 op1_lval = _zval_get_long_func(op1);
1579 if (UNEXPECTED(EG(exception))) {
1580 return FAILURE;
1581 }
1582 } else {
1583 op1_lval = Z_LVAL_P(op1);
1584 }
1585 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1586 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR);
1587 op2_lval = _zval_get_long_func(op2);
1588 if (UNEXPECTED(EG(exception))) {
1589 return FAILURE;
1590 }
1591 } else {
1592 op2_lval = Z_LVAL_P(op2);
1593 }
1594
1595 if (op1 == result) {
1596 zval_dtor(result);
1597 }
1598 ZVAL_LONG(result, op1_lval ^ op2_lval);
1599 return SUCCESS;
1600 }
1601 /* }}} */
1602
shift_left_function(zval * result,zval * op1,zval * op2)1603 ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2) /* {{{ */
1604 {
1605 zend_long op1_lval, op2_lval;
1606
1607 convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function);
1608
1609 /* prevent wrapping quirkiness on some processors where << 64 + x == << x */
1610 if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1611 if (EXPECTED(op2_lval > 0)) {
1612 if (op1 == result) {
1613 zval_dtor(result);
1614 }
1615 ZVAL_LONG(result, 0);
1616 return SUCCESS;
1617 } else {
1618 if (EG(current_execute_data) && !CG(in_compilation)) {
1619 zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1620 } else {
1621 zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1622 }
1623 if (op1 != result) {
1624 ZVAL_UNDEF(result);
1625 }
1626 return FAILURE;
1627 }
1628 }
1629
1630 if (op1 == result) {
1631 zval_dtor(result);
1632 }
1633
1634 ZVAL_LONG(result, op1_lval << op2_lval);
1635 return SUCCESS;
1636 }
1637 /* }}} */
1638
shift_right_function(zval * result,zval * op1,zval * op2)1639 ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2) /* {{{ */
1640 {
1641 zend_long op1_lval, op2_lval;
1642
1643 convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function);
1644
1645 /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
1646 if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1647 if (EXPECTED(op2_lval > 0)) {
1648 if (op1 == result) {
1649 zval_dtor(result);
1650 }
1651 ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
1652 return SUCCESS;
1653 } else {
1654 if (EG(current_execute_data) && !CG(in_compilation)) {
1655 zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1656 } else {
1657 zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1658 }
1659 if (op1 != result) {
1660 ZVAL_UNDEF(result);
1661 }
1662 return FAILURE;
1663 }
1664 }
1665
1666 if (op1 == result) {
1667 zval_dtor(result);
1668 }
1669
1670 ZVAL_LONG(result, op1_lval >> op2_lval);
1671 return SUCCESS;
1672 }
1673 /* }}} */
1674
concat_function(zval * result,zval * op1,zval * op2)1675 ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /* {{{ */
1676 {
1677 zval *orig_op1 = op1;
1678 zval op1_copy, op2_copy;
1679 int use_copy1 = 0, use_copy2 = 0;
1680
1681 do {
1682 if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
1683 if (Z_ISREF_P(op1)) {
1684 op1 = Z_REFVAL_P(op1);
1685 if (Z_TYPE_P(op1) == IS_STRING) break;
1686 }
1687 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function);
1688 use_copy1 = zend_make_printable_zval(op1, &op1_copy);
1689 if (use_copy1) {
1690 if (UNEXPECTED(EG(exception))) {
1691 zval_dtor(&op1_copy);
1692 return FAILURE;
1693 }
1694 if (result == op1) {
1695 if (UNEXPECTED(op1 == op2)) {
1696 op2 = &op1_copy;
1697 }
1698 }
1699 op1 = &op1_copy;
1700 }
1701 }
1702 } while (0);
1703 do {
1704 if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
1705 if (Z_ISREF_P(op2)) {
1706 op2 = Z_REFVAL_P(op2);
1707 if (Z_TYPE_P(op2) == IS_STRING) break;
1708 }
1709 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT);
1710 use_copy2 = zend_make_printable_zval(op2, &op2_copy);
1711 if (use_copy2) {
1712 if (UNEXPECTED(EG(exception))) {
1713 if (UNEXPECTED(use_copy1)) {
1714 zval_dtor(op1);
1715 }
1716 zval_dtor(&op2_copy);
1717 return FAILURE;
1718 }
1719 op2 = &op2_copy;
1720 }
1721 }
1722 } while (0);
1723
1724 {
1725 size_t op1_len = Z_STRLEN_P(op1);
1726 size_t op2_len = Z_STRLEN_P(op2);
1727 size_t result_len = op1_len + op2_len;
1728 zend_string *result_str;
1729
1730 if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) {
1731 zend_throw_error(NULL, "String size overflow");
1732 if (UNEXPECTED(use_copy1)) {
1733 zval_dtor(op1);
1734 }
1735 if (UNEXPECTED(use_copy2)) {
1736 zval_dtor(op2);
1737 }
1738 if (orig_op1 != result) {
1739 ZVAL_UNDEF(result);
1740 }
1741 return FAILURE;
1742 }
1743
1744 if (result == op1 && Z_REFCOUNTED_P(result)) {
1745 /* special case, perform operations on result */
1746 result_str = zend_string_extend(Z_STR_P(result), result_len, 0);
1747 } else {
1748 result_str = zend_string_alloc(result_len, 0);
1749 memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
1750 if (result == orig_op1) {
1751 zval_dtor(orig_op1);
1752 }
1753 }
1754
1755 /* This has to happen first to account for the cases where result == op1 == op2 and
1756 * the realloc is done. In this case this line will also update Z_STRVAL_P(op2) to
1757 * point to the new string. The first op2_len bytes of result will still be the same. */
1758 ZVAL_NEW_STR(result, result_str);
1759
1760 memcpy(ZSTR_VAL(result_str) + op1_len, Z_STRVAL_P(op2), op2_len);
1761 ZSTR_VAL(result_str)[result_len] = '\0';
1762 }
1763
1764 if (UNEXPECTED(use_copy1)) {
1765 zval_dtor(op1);
1766 }
1767 if (UNEXPECTED(use_copy2)) {
1768 zval_dtor(op2);
1769 }
1770 return SUCCESS;
1771 }
1772 /* }}} */
1773
string_compare_function_ex(zval * op1,zval * op2,zend_bool case_insensitive)1774 ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, zend_bool case_insensitive) /* {{{ */
1775 {
1776 zend_string *str1 = zval_get_string(op1);
1777 zend_string *str2 = zval_get_string(op2);
1778 int ret;
1779
1780 if (case_insensitive) {
1781 ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
1782 } else {
1783 ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
1784 }
1785
1786 zend_string_release(str1);
1787 zend_string_release(str2);
1788 return ret;
1789 }
1790 /* }}} */
1791
string_compare_function(zval * op1,zval * op2)1792 ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2) /* {{{ */
1793 {
1794 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
1795 EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1796 if (Z_STR_P(op1) == Z_STR_P(op2)) {
1797 return 0;
1798 } else {
1799 return zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1800 }
1801 } else {
1802 zend_string *str1 = zval_get_string(op1);
1803 zend_string *str2 = zval_get_string(op2);
1804 int ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
1805
1806 zend_string_release(str1);
1807 zend_string_release(str2);
1808 return ret;
1809 }
1810 }
1811 /* }}} */
1812
string_case_compare_function(zval * op1,zval * op2)1813 ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2) /* {{{ */
1814 {
1815 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
1816 EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1817 if (Z_STR_P(op1) == Z_STR_P(op2)) {
1818 return 0;
1819 } else {
1820 return zend_binary_strcasecmp_l(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1821 }
1822 } else {
1823 zend_string *str1 = zval_get_string(op1);
1824 zend_string *str2 = zval_get_string(op2);
1825 int ret = zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1));
1826
1827 zend_string_release(str1);
1828 zend_string_release(str2);
1829 return ret;
1830 }
1831 }
1832 /* }}} */
1833
1834 #if HAVE_STRCOLL
string_locale_compare_function(zval * op1,zval * op2)1835 ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2) /* {{{ */
1836 {
1837 zend_string *str1 = zval_get_string(op1);
1838 zend_string *str2 = zval_get_string(op2);
1839 int ret = strcoll(ZSTR_VAL(str1), ZSTR_VAL(str2));
1840
1841 zend_string_release(str1);
1842 zend_string_release(str2);
1843 return ret;
1844 }
1845 /* }}} */
1846 #endif
1847
numeric_compare_function(zval * op1,zval * op2)1848 ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2) /* {{{ */
1849 {
1850 double d1, d2;
1851
1852 d1 = zval_get_double(op1);
1853 d2 = zval_get_double(op2);
1854
1855 return ZEND_NORMALIZE_BOOL(d1 - d2);
1856 }
1857 /* }}} */
1858
zend_free_obj_get_result(zval * op)1859 static inline void zend_free_obj_get_result(zval *op) /* {{{ */
1860 {
1861 if (Z_REFCOUNTED_P(op)) {
1862 if (Z_REFCOUNT_P(op) == 0) {
1863 zval_dtor(op);
1864 } else {
1865 zval_ptr_dtor(op);
1866 }
1867 }
1868 }
1869 /* }}} */
1870
convert_compare_result_to_long(zval * result)1871 static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
1872 {
1873 if (Z_TYPE_P(result) == IS_DOUBLE) {
1874 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1875 } else {
1876 convert_to_long(result);
1877 }
1878 }
1879 /* }}} */
1880
compare_function(zval * result,zval * op1,zval * op2)1881 ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1882 {
1883 int ret;
1884 int converted = 0;
1885 zval op1_copy, op2_copy;
1886 zval *op_free, tmp_free;
1887
1888 while (1) {
1889 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1890 case TYPE_PAIR(IS_LONG, IS_LONG):
1891 ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1892 return SUCCESS;
1893
1894 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1895 Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1896 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1897 return SUCCESS;
1898
1899 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1900 Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1901 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1902 return SUCCESS;
1903
1904 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1905 if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
1906 ZVAL_LONG(result, 0);
1907 } else {
1908 Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1909 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1910 }
1911 return SUCCESS;
1912
1913 case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1914 ZVAL_LONG(result, zend_compare_arrays(op1, op2));
1915 return SUCCESS;
1916
1917 case TYPE_PAIR(IS_NULL, IS_NULL):
1918 case TYPE_PAIR(IS_NULL, IS_FALSE):
1919 case TYPE_PAIR(IS_FALSE, IS_NULL):
1920 case TYPE_PAIR(IS_FALSE, IS_FALSE):
1921 case TYPE_PAIR(IS_TRUE, IS_TRUE):
1922 ZVAL_LONG(result, 0);
1923 return SUCCESS;
1924
1925 case TYPE_PAIR(IS_NULL, IS_TRUE):
1926 ZVAL_LONG(result, -1);
1927 return SUCCESS;
1928
1929 case TYPE_PAIR(IS_TRUE, IS_NULL):
1930 ZVAL_LONG(result, 1);
1931 return SUCCESS;
1932
1933 case TYPE_PAIR(IS_STRING, IS_STRING):
1934 if (Z_STR_P(op1) == Z_STR_P(op2)) {
1935 ZVAL_LONG(result, 0);
1936 return SUCCESS;
1937 }
1938 ZVAL_LONG(result, zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)));
1939 return SUCCESS;
1940
1941 case TYPE_PAIR(IS_NULL, IS_STRING):
1942 ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
1943 return SUCCESS;
1944
1945 case TYPE_PAIR(IS_STRING, IS_NULL):
1946 ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
1947 return SUCCESS;
1948
1949 case TYPE_PAIR(IS_OBJECT, IS_NULL):
1950 ZVAL_LONG(result, 1);
1951 return SUCCESS;
1952
1953 case TYPE_PAIR(IS_NULL, IS_OBJECT):
1954 ZVAL_LONG(result, -1);
1955 return SUCCESS;
1956
1957 default:
1958 if (Z_ISREF_P(op1)) {
1959 op1 = Z_REFVAL_P(op1);
1960 continue;
1961 } else if (Z_ISREF_P(op2)) {
1962 op2 = Z_REFVAL_P(op2);
1963 continue;
1964 }
1965
1966 if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
1967 ret = Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2);
1968 if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) {
1969 convert_compare_result_to_long(result);
1970 }
1971 return ret;
1972 } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
1973 ret = Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2);
1974 if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) {
1975 convert_compare_result_to_long(result);
1976 }
1977 return ret;
1978 }
1979
1980 if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
1981 if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
1982 /* object handles are identical, apparently this is the same object */
1983 ZVAL_LONG(result, 0);
1984 return SUCCESS;
1985 }
1986 if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
1987 ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2));
1988 return SUCCESS;
1989 }
1990 }
1991 if (Z_TYPE_P(op1) == IS_OBJECT) {
1992 if (Z_OBJ_HT_P(op1)->get) {
1993 zval rv;
1994 op_free = Z_OBJ_HT_P(op1)->get(op1, &rv);
1995 ret = compare_function(result, op_free, op2);
1996 zend_free_obj_get_result(op_free);
1997 return ret;
1998 } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1999 ZVAL_UNDEF(&tmp_free);
2000 if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) {
2001 ZVAL_LONG(result, 1);
2002 zend_free_obj_get_result(&tmp_free);
2003 return SUCCESS;
2004 }
2005 ret = compare_function(result, &tmp_free, op2);
2006 zend_free_obj_get_result(&tmp_free);
2007 return ret;
2008 }
2009 }
2010 if (Z_TYPE_P(op2) == IS_OBJECT) {
2011 if (Z_OBJ_HT_P(op2)->get) {
2012 zval rv;
2013 op_free = Z_OBJ_HT_P(op2)->get(op2, &rv);
2014 ret = compare_function(result, op1, op_free);
2015 zend_free_obj_get_result(op_free);
2016 return ret;
2017 } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
2018 ZVAL_UNDEF(&tmp_free);
2019 if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) {
2020 ZVAL_LONG(result, -1);
2021 zend_free_obj_get_result(&tmp_free);
2022 return SUCCESS;
2023 }
2024 ret = compare_function(result, op1, &tmp_free);
2025 zend_free_obj_get_result(&tmp_free);
2026 return ret;
2027 } else if (Z_TYPE_P(op1) == IS_OBJECT) {
2028 ZVAL_LONG(result, 1);
2029 return SUCCESS;
2030 }
2031 }
2032 if (!converted) {
2033 if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) {
2034 ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0);
2035 return SUCCESS;
2036 } else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) {
2037 ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0);
2038 return SUCCESS;
2039 } else if (Z_TYPE_P(op1) == IS_TRUE) {
2040 ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1);
2041 return SUCCESS;
2042 } else if (Z_TYPE_P(op2) == IS_TRUE) {
2043 ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
2044 return SUCCESS;
2045 } else {
2046 zendi_convert_scalar_to_number(op1, op1_copy, result);
2047 zendi_convert_scalar_to_number(op2, op2_copy, result);
2048 converted = 1;
2049 }
2050 } else if (Z_TYPE_P(op1)==IS_ARRAY) {
2051 ZVAL_LONG(result, 1);
2052 return SUCCESS;
2053 } else if (Z_TYPE_P(op2)==IS_ARRAY) {
2054 ZVAL_LONG(result, -1);
2055 return SUCCESS;
2056 } else if (Z_TYPE_P(op1)==IS_OBJECT) {
2057 ZVAL_LONG(result, 1);
2058 return SUCCESS;
2059 } else if (Z_TYPE_P(op2)==IS_OBJECT) {
2060 ZVAL_LONG(result, -1);
2061 return SUCCESS;
2062 } else {
2063 ZVAL_LONG(result, 0);
2064 return FAILURE;
2065 }
2066 }
2067 }
2068 }
2069 /* }}} */
2070
hash_zval_identical_function(zval * z1,zval * z2)2071 static int hash_zval_identical_function(zval *z1, zval *z2) /* {{{ */
2072 {
2073 zval result;
2074
2075 /* is_identical_function() returns 1 in case of identity and 0 in case
2076 * of a difference;
2077 * whereas this comparison function is expected to return 0 on identity,
2078 * and non zero otherwise.
2079 */
2080 ZVAL_DEREF(z1);
2081 ZVAL_DEREF(z2);
2082 if (is_identical_function(&result, z1, z2)==FAILURE) {
2083 return 1;
2084 }
2085 return Z_TYPE(result) != IS_TRUE;
2086 }
2087 /* }}} */
2088
zend_is_identical(zval * op1,zval * op2)2089 ZEND_API int ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2) /* {{{ */
2090 {
2091 if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
2092 return 0;
2093 }
2094 switch (Z_TYPE_P(op1)) {
2095 case IS_NULL:
2096 case IS_FALSE:
2097 case IS_TRUE:
2098 return 1;
2099 case IS_LONG:
2100 return (Z_LVAL_P(op1) == Z_LVAL_P(op2));
2101 case IS_RESOURCE:
2102 return (Z_RES_P(op1) == Z_RES_P(op2));
2103 case IS_DOUBLE:
2104 return (Z_DVAL_P(op1) == Z_DVAL_P(op2));
2105 case IS_STRING:
2106 return (Z_STR_P(op1) == Z_STR_P(op2) ||
2107 (Z_STRLEN_P(op1) == Z_STRLEN_P(op2) &&
2108 memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0));
2109 case IS_ARRAY:
2110 return (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
2111 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1) == 0);
2112 case IS_OBJECT:
2113 return (Z_OBJ_P(op1) == Z_OBJ_P(op2) && Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2));
2114 default:
2115 return 0;
2116 }
2117 }
2118 /* }}} */
2119
is_identical_function(zval * result,zval * op1,zval * op2)2120 ZEND_API int ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
2121 {
2122 ZVAL_BOOL(result, zend_is_identical(op1, op2));
2123 return SUCCESS;
2124 }
2125 /* }}} */
2126
is_not_identical_function(zval * result,zval * op1,zval * op2)2127 ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
2128 {
2129 ZVAL_BOOL(result, !zend_is_identical(op1, op2));
2130 return SUCCESS;
2131 }
2132 /* }}} */
2133
is_equal_function(zval * result,zval * op1,zval * op2)2134 ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2135 {
2136 if (compare_function(result, op1, op2) == FAILURE) {
2137 return FAILURE;
2138 }
2139 ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
2140 return SUCCESS;
2141 }
2142 /* }}} */
2143
is_not_equal_function(zval * result,zval * op1,zval * op2)2144 ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2145 {
2146 if (compare_function(result, op1, op2) == FAILURE) {
2147 return FAILURE;
2148 }
2149 ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
2150 return SUCCESS;
2151 }
2152 /* }}} */
2153
is_smaller_function(zval * result,zval * op1,zval * op2)2154 ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2) /* {{{ */
2155 {
2156 if (compare_function(result, op1, op2) == FAILURE) {
2157 return FAILURE;
2158 }
2159 ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
2160 return SUCCESS;
2161 }
2162 /* }}} */
2163
is_smaller_or_equal_function(zval * result,zval * op1,zval * op2)2164 ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2165 {
2166 if (compare_function(result, op1, op2) == FAILURE) {
2167 return FAILURE;
2168 }
2169 ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
2170 return SUCCESS;
2171 }
2172 /* }}} */
2173
instanceof_interface_only(const zend_class_entry * instance_ce,const zend_class_entry * ce)2174 static zend_bool ZEND_FASTCALL instanceof_interface_only(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2175 {
2176 uint32_t i;
2177
2178 for (i = 0; i < instance_ce->num_interfaces; i++) {
2179 if (instanceof_interface_only(instance_ce->interfaces[i], ce)) {
2180 return 1;
2181 }
2182 }
2183 return 0;
2184 }
2185 /* }}} */
2186
instanceof_class(const zend_class_entry * instance_ce,const zend_class_entry * ce)2187 static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2188 {
2189 while (instance_ce) {
2190 if (instance_ce == ce) {
2191 return 1;
2192 }
2193 instance_ce = instance_ce->parent;
2194 }
2195 return 0;
2196 }
2197 /* }}} */
2198
instanceof_interface(const zend_class_entry * instance_ce,const zend_class_entry * ce)2199 static zend_bool ZEND_FASTCALL instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2200 {
2201 uint32_t i;
2202
2203 for (i = 0; i < instance_ce->num_interfaces; i++) {
2204 if (instanceof_interface(instance_ce->interfaces[i], ce)) {
2205 return 1;
2206 }
2207 }
2208 return instanceof_class(instance_ce, ce);
2209 }
2210 /* }}} */
2211
instanceof_function_ex(const zend_class_entry * instance_ce,const zend_class_entry * ce,zend_bool interfaces_only)2212 ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
2213 {
2214 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2215 if (!interfaces_only) {
2216 if (instanceof_interface_only(instance_ce, ce)) {
2217 return 1;
2218 }
2219 } else {
2220 return instanceof_interface(instance_ce, ce);
2221 }
2222 }
2223 if (!interfaces_only) {
2224 return instanceof_class(instance_ce, ce);
2225 }
2226 return 0;
2227 }
2228 /* }}} */
2229
instanceof_function(const zend_class_entry * instance_ce,const zend_class_entry * ce)2230 ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2231 {
2232 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2233 return instanceof_interface(instance_ce, ce);
2234 } else {
2235 return instanceof_class(instance_ce, ce);
2236 }
2237 }
2238 /* }}} */
2239
2240 #define LOWER_CASE 1
2241 #define UPPER_CASE 2
2242 #define NUMERIC 3
2243
increment_string(zval * str)2244 static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */
2245 {
2246 int carry=0;
2247 size_t pos=Z_STRLEN_P(str)-1;
2248 char *s;
2249 zend_string *t;
2250 int last=0; /* Shut up the compiler warning */
2251 int ch;
2252
2253 if (Z_STRLEN_P(str) == 0) {
2254 zend_string_release(Z_STR_P(str));
2255 if (CG(one_char_string)['1']) {
2256 ZVAL_INTERNED_STR(str, CG(one_char_string)['1']);
2257 } else {
2258 Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0);
2259 Z_TYPE_INFO_P(str) = IS_STRING_EX;
2260 }
2261 return;
2262 }
2263
2264 if (!Z_REFCOUNTED_P(str)) {
2265 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2266 Z_TYPE_INFO_P(str) = IS_STRING_EX;
2267 } else if (Z_REFCOUNT_P(str) > 1) {
2268 Z_DELREF_P(str);
2269 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2270 } else {
2271 zend_string_forget_hash_val(Z_STR_P(str));
2272 }
2273 s = Z_STRVAL_P(str);
2274
2275 do {
2276 ch = s[pos];
2277 if (ch >= 'a' && ch <= 'z') {
2278 if (ch == 'z') {
2279 s[pos] = 'a';
2280 carry=1;
2281 } else {
2282 s[pos]++;
2283 carry=0;
2284 }
2285 last=LOWER_CASE;
2286 } else if (ch >= 'A' && ch <= 'Z') {
2287 if (ch == 'Z') {
2288 s[pos] = 'A';
2289 carry=1;
2290 } else {
2291 s[pos]++;
2292 carry=0;
2293 }
2294 last=UPPER_CASE;
2295 } else if (ch >= '0' && ch <= '9') {
2296 if (ch == '9') {
2297 s[pos] = '0';
2298 carry=1;
2299 } else {
2300 s[pos]++;
2301 carry=0;
2302 }
2303 last = NUMERIC;
2304 } else {
2305 carry=0;
2306 break;
2307 }
2308 if (carry == 0) {
2309 break;
2310 }
2311 } while (pos-- > 0);
2312
2313 if (carry) {
2314 t = zend_string_alloc(Z_STRLEN_P(str)+1, 0);
2315 memcpy(ZSTR_VAL(t) + 1, Z_STRVAL_P(str), Z_STRLEN_P(str));
2316 ZSTR_VAL(t)[Z_STRLEN_P(str) + 1] = '\0';
2317 switch (last) {
2318 case NUMERIC:
2319 ZSTR_VAL(t)[0] = '1';
2320 break;
2321 case UPPER_CASE:
2322 ZSTR_VAL(t)[0] = 'A';
2323 break;
2324 case LOWER_CASE:
2325 ZSTR_VAL(t)[0] = 'a';
2326 break;
2327 }
2328 zend_string_free(Z_STR_P(str));
2329 ZVAL_NEW_STR(str, t);
2330 }
2331 }
2332 /* }}} */
2333
increment_function(zval * op1)2334 ZEND_API int ZEND_FASTCALL increment_function(zval *op1) /* {{{ */
2335 {
2336 try_again:
2337 switch (Z_TYPE_P(op1)) {
2338 case IS_LONG:
2339 fast_long_increment_function(op1);
2340 break;
2341 case IS_DOUBLE:
2342 Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2343 break;
2344 case IS_NULL:
2345 ZVAL_LONG(op1, 1);
2346 break;
2347 case IS_STRING: {
2348 zend_long lval;
2349 double dval;
2350
2351 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2352 case IS_LONG:
2353 zend_string_release(Z_STR_P(op1));
2354 if (lval == ZEND_LONG_MAX) {
2355 /* switch to double */
2356 double d = (double)lval;
2357 ZVAL_DOUBLE(op1, d+1);
2358 } else {
2359 ZVAL_LONG(op1, lval+1);
2360 }
2361 break;
2362 case IS_DOUBLE:
2363 zend_string_release(Z_STR_P(op1));
2364 ZVAL_DOUBLE(op1, dval+1);
2365 break;
2366 default:
2367 /* Perl style string increment */
2368 increment_string(op1);
2369 break;
2370 }
2371 }
2372 break;
2373 case IS_OBJECT:
2374 if (Z_OBJ_HANDLER_P(op1, get)
2375 && Z_OBJ_HANDLER_P(op1, set)) {
2376 /* proxy object */
2377 zval rv;
2378 zval *val;
2379
2380 val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);
2381 Z_TRY_ADDREF_P(val);
2382 increment_function(val);
2383 Z_OBJ_HANDLER_P(op1, set)(op1, val);
2384 zval_ptr_dtor(val);
2385 } else if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2386 zval op2;
2387 int res;
2388
2389 ZVAL_LONG(&op2, 1);
2390 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, &op2);
2391 zval_ptr_dtor(&op2);
2392
2393 return res;
2394 }
2395 return FAILURE;
2396 case IS_REFERENCE:
2397 op1 = Z_REFVAL_P(op1);
2398 goto try_again;
2399 default:
2400 return FAILURE;
2401 }
2402 return SUCCESS;
2403 }
2404 /* }}} */
2405
decrement_function(zval * op1)2406 ZEND_API int ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */
2407 {
2408 zend_long lval;
2409 double dval;
2410
2411 try_again:
2412 switch (Z_TYPE_P(op1)) {
2413 case IS_LONG:
2414 fast_long_decrement_function(op1);
2415 break;
2416 case IS_DOUBLE:
2417 Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2418 break;
2419 case IS_STRING: /* Like perl we only support string increment */
2420 if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
2421 zend_string_release(Z_STR_P(op1));
2422 ZVAL_LONG(op1, -1);
2423 break;
2424 }
2425 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2426 case IS_LONG:
2427 zend_string_release(Z_STR_P(op1));
2428 if (lval == ZEND_LONG_MIN) {
2429 double d = (double)lval;
2430 ZVAL_DOUBLE(op1, d-1);
2431 } else {
2432 ZVAL_LONG(op1, lval-1);
2433 }
2434 break;
2435 case IS_DOUBLE:
2436 zend_string_release(Z_STR_P(op1));
2437 ZVAL_DOUBLE(op1, dval - 1);
2438 break;
2439 }
2440 break;
2441 case IS_OBJECT:
2442 if (Z_OBJ_HANDLER_P(op1, get)
2443 && Z_OBJ_HANDLER_P(op1, set)) {
2444 /* proxy object */
2445 zval rv;
2446 zval *val;
2447
2448 val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);
2449 Z_TRY_ADDREF_P(val);
2450 decrement_function(val);
2451 Z_OBJ_HANDLER_P(op1, set)(op1, val);
2452 zval_ptr_dtor(val);
2453 } else if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2454 zval op2;
2455 int res;
2456
2457 ZVAL_LONG(&op2, 1);
2458 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, &op2);
2459 zval_ptr_dtor(&op2);
2460
2461 return res;
2462 }
2463 return FAILURE;
2464 case IS_REFERENCE:
2465 op1 = Z_REFVAL_P(op1);
2466 goto try_again;
2467 default:
2468 return FAILURE;
2469 }
2470
2471 return SUCCESS;
2472 }
2473 /* }}} */
2474
zend_is_true(zval * op)2475 ZEND_API int ZEND_FASTCALL zend_is_true(zval *op) /* {{{ */
2476 {
2477 return i_zend_is_true(op);
2478 }
2479 /* }}} */
2480
zend_object_is_true(zval * op)2481 ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */
2482 {
2483 if (Z_OBJ_HT_P(op)->cast_object) {
2484 zval tmp;
2485 if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL) == SUCCESS) {
2486 return Z_TYPE(tmp) == IS_TRUE;
2487 }
2488 zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", ZSTR_VAL(Z_OBJ_P(op)->ce->name));
2489 } else if (Z_OBJ_HT_P(op)->get) {
2490 int result;
2491 zval rv;
2492 zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv);
2493
2494 if (Z_TYPE_P(tmp) != IS_OBJECT) {
2495 /* for safety - avoid loop */
2496 result = i_zend_is_true(tmp);
2497 zval_ptr_dtor(tmp);
2498 return result;
2499 }
2500 }
2501 return 1;
2502 }
2503 /* }}} */
2504
2505 #ifdef ZEND_USE_TOLOWER_L
zend_update_current_locale(void)2506 ZEND_API void zend_update_current_locale(void) /* {{{ */
2507 {
2508 current_locale = _get_current_locale();
2509 }
2510 /* }}} */
2511 #endif
2512
zend_str_tolower_copy(char * dest,const char * source,size_t length)2513 ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length) /* {{{ */
2514 {
2515 register unsigned char *str = (unsigned char*)source;
2516 register unsigned char *result = (unsigned char*)dest;
2517 register unsigned char *end = str + length;
2518
2519 while (str < end) {
2520 *result++ = zend_tolower_ascii(*str++);
2521 }
2522 *result = '\0';
2523
2524 return dest;
2525 }
2526 /* }}} */
2527
zend_str_tolower_dup(const char * source,size_t length)2528 ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length) /* {{{ */
2529 {
2530 return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2531 }
2532 /* }}} */
2533
zend_str_tolower(char * str,size_t length)2534 ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length) /* {{{ */
2535 {
2536 register unsigned char *p = (unsigned char*)str;
2537 register unsigned char *end = p + length;
2538
2539 while (p < end) {
2540 *p = zend_tolower_ascii(*p);
2541 p++;
2542 }
2543 }
2544 /* }}} */
2545
zend_str_tolower_dup_ex(const char * source,size_t length)2546 ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length) /* {{{ */
2547 {
2548 register const unsigned char *p = (const unsigned char*)source;
2549 register const unsigned char *end = p + length;
2550
2551 while (p < end) {
2552 if (*p != zend_tolower_ascii(*p)) {
2553 char *res = (char*)emalloc(length + 1);
2554 register unsigned char *r;
2555
2556 if (p != (const unsigned char*)source) {
2557 memcpy(res, source, p - (const unsigned char*)source);
2558 }
2559 r = (unsigned char*)p + (res - source);
2560 while (p < end) {
2561 *r = zend_tolower_ascii(*p);
2562 p++;
2563 r++;
2564 }
2565 *r = '\0';
2566 return res;
2567 }
2568 p++;
2569 }
2570 return NULL;
2571 }
2572 /* }}} */
2573
zend_string_tolower(zend_string * str)2574 ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str) /* {{{ */
2575 {
2576 register unsigned char *p = (unsigned char*)ZSTR_VAL(str);
2577 register unsigned char *end = p + ZSTR_LEN(str);
2578
2579 while (p < end) {
2580 if (*p != zend_tolower_ascii(*p)) {
2581 zend_string *res = zend_string_alloc(ZSTR_LEN(str), 0);
2582 register unsigned char *r;
2583
2584 if (p != (unsigned char*)ZSTR_VAL(str)) {
2585 memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*)ZSTR_VAL(str));
2586 }
2587 r = p + (ZSTR_VAL(res) - ZSTR_VAL(str));
2588 while (p < end) {
2589 *r = zend_tolower_ascii(*p);
2590 p++;
2591 r++;
2592 }
2593 *r = '\0';
2594 return res;
2595 }
2596 p++;
2597 }
2598 return zend_string_copy(str);
2599 }
2600 /* }}} */
2601
zend_binary_strcmp(const char * s1,size_t len1,const char * s2,size_t len2)2602 ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2603 {
2604 int retval;
2605
2606 if (s1 == s2) {
2607 return 0;
2608 }
2609 retval = memcmp(s1, s2, MIN(len1, len2));
2610 if (!retval) {
2611 return (int)(len1 - len2);
2612 } else {
2613 return retval;
2614 }
2615 }
2616 /* }}} */
2617
zend_binary_strncmp(const char * s1,size_t len1,const char * s2,size_t len2,size_t length)2618 ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2619 {
2620 int retval;
2621
2622 if (s1 == s2) {
2623 return 0;
2624 }
2625 retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2626 if (!retval) {
2627 return (int)(MIN(length, len1) - MIN(length, len2));
2628 } else {
2629 return retval;
2630 }
2631 }
2632 /* }}} */
2633
zend_binary_strcasecmp(const char * s1,size_t len1,const char * s2,size_t len2)2634 ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2635 {
2636 size_t len;
2637 int c1, c2;
2638
2639 if (s1 == s2) {
2640 return 0;
2641 }
2642
2643 len = MIN(len1, len2);
2644 while (len--) {
2645 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2646 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2647 if (c1 != c2) {
2648 return c1 - c2;
2649 }
2650 }
2651
2652 return (int)(len1 - len2);
2653 }
2654 /* }}} */
2655
zend_binary_strncasecmp(const char * s1,size_t len1,const char * s2,size_t len2,size_t length)2656 ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2657 {
2658 size_t len;
2659 int c1, c2;
2660
2661 if (s1 == s2) {
2662 return 0;
2663 }
2664 len = MIN(length, MIN(len1, len2));
2665 while (len--) {
2666 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2667 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2668 if (c1 != c2) {
2669 return c1 - c2;
2670 }
2671 }
2672
2673 return (int)(MIN(length, len1) - MIN(length, len2));
2674 }
2675 /* }}} */
2676
zend_binary_strcasecmp_l(const char * s1,size_t len1,const char * s2,size_t len2)2677 ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2678 {
2679 size_t len;
2680 int c1, c2;
2681
2682 if (s1 == s2) {
2683 return 0;
2684 }
2685
2686 len = MIN(len1, len2);
2687 while (len--) {
2688 c1 = zend_tolower((int)*(unsigned char *)s1++);
2689 c2 = zend_tolower((int)*(unsigned char *)s2++);
2690 if (c1 != c2) {
2691 return c1 - c2;
2692 }
2693 }
2694
2695 return (int)(len1 - len2);
2696 }
2697 /* }}} */
2698
zend_binary_strncasecmp_l(const char * s1,size_t len1,const char * s2,size_t len2,size_t length)2699 ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2700 {
2701 size_t len;
2702 int c1, c2;
2703
2704 if (s1 == s2) {
2705 return 0;
2706 }
2707 len = MIN(length, MIN(len1, len2));
2708 while (len--) {
2709 c1 = zend_tolower((int)*(unsigned char *)s1++);
2710 c2 = zend_tolower((int)*(unsigned char *)s2++);
2711 if (c1 != c2) {
2712 return c1 - c2;
2713 }
2714 }
2715
2716 return (int)(MIN(length, len1) - MIN(length, len2));
2717 }
2718 /* }}} */
2719
zend_binary_zval_strcmp(zval * s1,zval * s2)2720 ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2721 {
2722 return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2723 }
2724 /* }}} */
2725
zend_binary_zval_strncmp(zval * s1,zval * s2,zval * s3)2726 ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2727 {
2728 return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2729 }
2730 /* }}} */
2731
zend_binary_zval_strcasecmp(zval * s1,zval * s2)2732 ZEND_API int ZEND_FASTCALL zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
2733 {
2734 return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2735 }
2736 /* }}} */
2737
zend_binary_zval_strncasecmp(zval * s1,zval * s2,zval * s3)2738 ZEND_API int ZEND_FASTCALL zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2739 {
2740 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));
2741 }
2742 /* }}} */
2743
zendi_smart_strcmp(zend_string * s1,zend_string * s2)2744 ZEND_API zend_long ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2) /* {{{ */
2745 {
2746 int ret1, ret2;
2747 int oflow1, oflow2;
2748 zend_long lval1 = 0, lval2 = 0;
2749 double dval1 = 0.0, dval2 = 0.0;
2750
2751 if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, 0, &oflow1)) &&
2752 (ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, 0, &oflow2))) {
2753 #if ZEND_ULONG_MAX == 0xFFFFFFFF
2754 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
2755 ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
2756 || (oflow1 == -1 && dval1 < -9007199254740991.))) {
2757 #else
2758 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
2759 #endif
2760 /* both values are integers overflown to the same side, and the
2761 * double comparison may have resulted in crucial accuracy lost */
2762 goto string_cmp;
2763 }
2764 if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) {
2765 if (ret1 != IS_DOUBLE) {
2766 if (oflow2) {
2767 /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
2768 return -1 * oflow2;
2769 }
2770 dval1 = (double) lval1;
2771 } else if (ret2 != IS_DOUBLE) {
2772 if (oflow1) {
2773 return oflow1;
2774 }
2775 dval2 = (double) lval2;
2776 } else if (dval1 == dval2 && !zend_finite(dval1)) {
2777 /* Both values overflowed and have the same sign,
2778 * so a numeric comparison would be inaccurate */
2779 goto string_cmp;
2780 }
2781 dval1 = dval1 - dval2;
2782 return ZEND_NORMALIZE_BOOL(dval1);
2783 } else { /* they both have to be long's */
2784 return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0);
2785 }
2786 } else {
2787 int strcmp_ret;
2788 string_cmp:
2789 strcmp_ret = zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len);
2790 return ZEND_NORMALIZE_BOOL(strcmp_ret);
2791 }
2792 }
2793 /* }}} */
2794
2795 static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
2796 {
2797 zval result;
2798
2799 if (compare_function(&result, z1, z2)==FAILURE) {
2800 return 1;
2801 }
2802 return Z_LVAL(result);
2803 }
2804 /* }}} */
2805
2806 ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2) /* {{{ */
2807 {
2808 return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0);
2809 }
2810 /* }}} */
2811
2812 ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2) /* {{{ */
2813 {
2814 return zend_compare_symbol_tables(Z_ARRVAL_P(a1), Z_ARRVAL_P(a2));
2815 }
2816 /* }}} */
2817
2818 ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2) /* {{{ */
2819 {
2820 if (Z_OBJ_P(o1) == Z_OBJ_P(o2)) {
2821 return 0;
2822 }
2823
2824 if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2825 return 1;
2826 } else {
2827 return Z_OBJ_HT_P(o1)->compare_objects(o1, o2);
2828 }
2829 }
2830 /* }}} */
2831
2832 ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2833 {
2834 zend_string *str;
2835
2836 str = zend_strpprintf(0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2837 ZVAL_NEW_STR(op, str);
2838 }
2839 /* }}} */
2840
2841 ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */
2842 {
2843 char buf[MAX_LENGTH_OF_LONG + 1];
2844 char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
2845 return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
2846 }
2847 /* }}} */
2848
2849 ZEND_API zend_uchar ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval) /* {{{ */ {
2850 return is_numeric_string_ex(ZSTR_VAL(str), ZSTR_LEN(str), lval, dval, -1, NULL);
2851 }
2852 /* }}} */
2853
2854 ZEND_API zend_uchar ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info) /* {{{ */
2855 {
2856 const char *ptr;
2857 int digits = 0, dp_or_e = 0;
2858 double local_dval = 0.0;
2859 zend_uchar type;
2860 zend_long tmp_lval = 0;
2861 int neg = 0;
2862
2863 if (!length) {
2864 return 0;
2865 }
2866
2867 if (oflow_info != NULL) {
2868 *oflow_info = 0;
2869 }
2870
2871 /* Skip any whitespace
2872 * This is much faster than the isspace() function */
2873 while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
2874 str++;
2875 length--;
2876 }
2877 ptr = str;
2878
2879 if (*ptr == '-') {
2880 neg = 1;
2881 ptr++;
2882 } else if (*ptr == '+') {
2883 ptr++;
2884 }
2885
2886 if (ZEND_IS_DIGIT(*ptr)) {
2887 /* Skip any leading 0s */
2888 while (*ptr == '0') {
2889 ptr++;
2890 }
2891
2892 /* Count the number of digits. If a decimal point/exponent is found,
2893 * it's a double. Otherwise, if there's a dval or no need to check for
2894 * a full match, stop when there are too many digits for a long */
2895 for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
2896 check_digits:
2897 if (ZEND_IS_DIGIT(*ptr)) {
2898 tmp_lval = tmp_lval * 10 + (*ptr) - '0';
2899 continue;
2900 } else if (*ptr == '.' && dp_or_e < 1) {
2901 goto process_double;
2902 } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
2903 const char *e = ptr + 1;
2904
2905 if (*e == '-' || *e == '+') {
2906 ptr = e++;
2907 }
2908 if (ZEND_IS_DIGIT(*e)) {
2909 goto process_double;
2910 }
2911 }
2912
2913 break;
2914 }
2915
2916 if (digits >= MAX_LENGTH_OF_LONG) {
2917 if (oflow_info != NULL) {
2918 *oflow_info = *str == '-' ? -1 : 1;
2919 }
2920 dp_or_e = -1;
2921 goto process_double;
2922 }
2923 } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
2924 process_double:
2925 type = IS_DOUBLE;
2926
2927 /* If there's a dval, do the conversion; else continue checking
2928 * the digits if we need to check for a full match */
2929 if (dval) {
2930 local_dval = zend_strtod(str, &ptr);
2931 } else if (allow_errors != 1 && dp_or_e != -1) {
2932 dp_or_e = (*ptr++ == '.') ? 1 : 2;
2933 goto check_digits;
2934 }
2935 } else {
2936 return 0;
2937 }
2938
2939 if (ptr != str + length) {
2940 if (!allow_errors) {
2941 return 0;
2942 }
2943 if (allow_errors == -1) {
2944 zend_error(E_NOTICE, "A non well formed numeric value encountered");
2945 }
2946 }
2947
2948 if (type == IS_LONG) {
2949 if (digits == MAX_LENGTH_OF_LONG - 1) {
2950 int cmp = strcmp(&ptr[-digits], long_min_digits);
2951
2952 if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
2953 if (dval) {
2954 *dval = zend_strtod(str, NULL);
2955 }
2956 if (oflow_info != NULL) {
2957 *oflow_info = *str == '-' ? -1 : 1;
2958 }
2959
2960 return IS_DOUBLE;
2961 }
2962 }
2963
2964 if (lval) {
2965 if (neg) {
2966 tmp_lval = -tmp_lval;
2967 }
2968 *lval = tmp_lval;
2969 }
2970
2971 return IS_LONG;
2972 } else {
2973 if (dval) {
2974 *dval = local_dval;
2975 }
2976
2977 return IS_DOUBLE;
2978 }
2979 }
2980 /* }}} */
2981
2982 /*
2983 * String matching - Sunday algorithm
2984 * http://www.iti.fh-flensburg.de/lang/algorithmen/pattern/sundayen.htm
2985 */
2986 static zend_always_inline void zend_memnstr_ex_pre(unsigned int td[], const char *needle, size_t needle_len, int reverse) /* {{{ */ {
2987 int i;
2988
2989 for (i = 0; i < 256; i++) {
2990 td[i] = needle_len + 1;
2991 }
2992
2993 if (reverse) {
2994 for (i = needle_len - 1; i >= 0; i--) {
2995 td[(unsigned char)needle[i]] = i + 1;
2996 }
2997 } else {
2998 for (i = 0; i < needle_len; i++) {
2999 td[(unsigned char)needle[i]] = (int)needle_len - i;
3000 }
3001 }
3002 }
3003 /* }}} */
3004
3005 ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
3006 {
3007 unsigned int td[256];
3008 register size_t i;
3009 register const char *p;
3010
3011 if (needle_len == 0 || (end - haystack) == 0) {
3012 return NULL;
3013 }
3014
3015 zend_memnstr_ex_pre(td, needle, needle_len, 0);
3016
3017 p = haystack;
3018 end -= needle_len;
3019
3020 while (p <= end) {
3021 for (i = 0; i < needle_len; i++) {
3022 if (needle[i] != p[i]) {
3023 break;
3024 }
3025 }
3026 if (i == needle_len) {
3027 return p;
3028 }
3029 if (UNEXPECTED(p == end)) {
3030 return NULL;
3031 }
3032 p += td[(unsigned char)(p[needle_len])];
3033 }
3034
3035 return NULL;
3036 }
3037 /* }}} */
3038
3039 ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
3040 {
3041 unsigned int td[256];
3042 register size_t i;
3043 register const char *p;
3044
3045 if (needle_len == 0 || (end - haystack) == 0) {
3046 return NULL;
3047 }
3048
3049 zend_memnstr_ex_pre(td, needle, needle_len, 1);
3050
3051 p = end;
3052 p -= needle_len;
3053
3054 while (p >= haystack) {
3055 for (i = 0; i < needle_len; i++) {
3056 if (needle[i] != p[i]) {
3057 break;
3058 }
3059 }
3060
3061 if (i == needle_len) {
3062 return (const char *)p;
3063 }
3064
3065 if (UNEXPECTED(p == haystack)) {
3066 return NULL;
3067 }
3068
3069 p -= td[(unsigned char)(p[-1])];
3070 }
3071
3072 return NULL;
3073 }
3074 /* }}} */
3075
3076 #if !ZEND_DVAL_TO_LVAL_CAST_OK
3077 # if SIZEOF_ZEND_LONG == 4
3078 ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
3079 {
3080 double two_pow_32 = pow(2., 32.),
3081 dmod;
3082
3083 dmod = fmod(d, two_pow_32);
3084 if (dmod < 0) {
3085 /* we're going to make this number positive; call ceil()
3086 * to simulate rounding towards 0 of the negative number */
3087 dmod = ceil(dmod);// + two_pow_32;
3088 }
3089 return (zend_long)(zend_ulong)dmod;
3090 }
3091 #else
3092 ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
3093 {
3094 double two_pow_64 = pow(2., 64.),
3095 dmod;
3096
3097 dmod = fmod(d, two_pow_64);
3098 if (dmod < 0) {
3099 /* no need to call ceil; original double must have had no
3100 * fractional part, hence dmod does not have one either */
3101 dmod += two_pow_64;
3102 }
3103 return (zend_long)(zend_ulong)dmod;
3104 }
3105 #endif
3106 #endif
3107
3108 /*
3109 * Local variables:
3110 * tab-width: 4
3111 * c-basic-offset: 4
3112 * indent-tabs-mode: t
3113 * End:
3114 */
3115