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