php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_operators.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Dmitry Stogov <dmitry@php.net> |
18 +----------------------------------------------------------------------+
19*/
20
21#include <ctype.h>
22
23#include "zend.h"
24#include "zend_operators.h"
25#include "zend_variables.h"
26#include "zend_globals.h"
27#include "zend_list.h"
28#include "zend_API.h"
29#include "zend_strtod.h"
30#include "zend_exceptions.h"
31#include "zend_closures.h"
32
33#include <locale.h>
34#ifdef HAVE_LANGINFO_H
35# include <langinfo.h>
36#endif
37
38#ifdef ZEND_INTRIN_AVX2_NATIVE
39#include <immintrin.h>
40#endif
41#ifdef __SSE2__
42#include <emmintrin.h>
43#endif
44#if defined(__aarch64__) || defined(_M_ARM64)
45#include <arm_neon.h>
46#endif
47
48#if defined(ZEND_WIN32) && !defined(ZTS) && defined(_MSC_VER)
49/* This performance improvement of tolower() on Windows gives 10-18% on bench.php */
50#define ZEND_USE_TOLOWER_L 1
51#endif
52
53#ifdef ZEND_USE_TOLOWER_L
54static _locale_t current_locale = NULL;
55/* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
56#define zend_tolower(c) _tolower_l(c, current_locale)
57#else
58#define zend_tolower(c) tolower(c)
59#endif
60
61#define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
62
63#ifdef ZEND_INTRIN_AVX2_NATIVE
64#define HAVE_BLOCKCONV
65
66#define BLOCKCONV_INIT_RANGE(start, end) \
67 const __m256i blconv_offset = _mm256_set1_epi8((signed char)(SCHAR_MIN - start)); \
68 const __m256i blconv_threshold = _mm256_set1_epi8(SCHAR_MIN + (end - start) + 1);
69
70#define BLOCKCONV_STRIDE sizeof(__m256i)
71
72#define BLOCKCONV_INIT_DELTA(delta) \
73 const __m256i blconv_delta = _mm256_set1_epi8(delta);
74
75#define BLOCKCONV_LOAD(input) \
76 __m256i blconv_operand = _mm256_loadu_si256((__m256i*)(input)); \
77 __m256i blconv_mask = _mm256_cmpgt_epi8(blconv_threshold, _mm256_add_epi8(blconv_operand, blconv_offset));
78
79#define BLOCKCONV_FOUND() _mm256_movemask_epi8(blconv_mask)
80
81#define BLOCKCONV_STORE(dest) \
82 __m256i blconv_add = _mm256_and_si256(blconv_mask, blconv_delta); \
83 __m256i blconv_result = _mm256_add_epi8(blconv_operand, blconv_add); \
84 _mm256_storeu_si256((__m256i*)(dest), blconv_result);
85
86#elif __SSE2__
87#define HAVE_BLOCKCONV
88
89/* Common code for SSE2 accelerated character case conversion */
90
91#define BLOCKCONV_INIT_RANGE(start, end) \
92 const __m128i blconv_offset = _mm_set1_epi8((signed char)(SCHAR_MIN - start)); \
93 const __m128i blconv_threshold = _mm_set1_epi8(SCHAR_MIN + (end - start) + 1);
94
95#define BLOCKCONV_STRIDE sizeof(__m128i)
96
97#define BLOCKCONV_INIT_DELTA(delta) \
98 const __m128i blconv_delta = _mm_set1_epi8(delta);
99
100#define BLOCKCONV_LOAD(input) \
101 __m128i blconv_operand = _mm_loadu_si128((__m128i*)(input)); \
102 __m128i blconv_mask = _mm_cmplt_epi8(_mm_add_epi8(blconv_operand, blconv_offset), blconv_threshold);
103
104#define BLOCKCONV_FOUND() _mm_movemask_epi8(blconv_mask)
105
106#define BLOCKCONV_STORE(dest) \
107 __m128i blconv_add = _mm_and_si128(blconv_mask, blconv_delta); \
108 __m128i blconv_result = _mm_add_epi8(blconv_operand, blconv_add); \
109 _mm_storeu_si128((__m128i *)(dest), blconv_result);
110
111#elif defined(__aarch64__) || defined(_M_ARM64)
112#define HAVE_BLOCKCONV
113
114#define BLOCKCONV_INIT_RANGE(start, end) \
115 const int8x16_t blconv_offset = vdupq_n_s8((signed char)(SCHAR_MIN - start)); \
116 const int8x16_t blconv_threshold = vdupq_n_s8(SCHAR_MIN + (end - start) + 1);
117
118#define BLOCKCONV_STRIDE sizeof(int8x16_t)
119
120#define BLOCKCONV_INIT_DELTA(delta) \
121 const int8x16_t blconv_delta = vdupq_n_s8(delta);
122
123#define BLOCKCONV_LOAD(input) \
124 int8x16_t blconv_operand = vld1q_s8((const int8_t*)(input)); \
125 uint8x16_t blconv_mask = vcltq_s8(vreinterpretq_s8_u8(vaddq_u8(vreinterpretq_u8_s8(blconv_operand), vreinterpretq_u8_s8(blconv_offset))), blconv_threshold);
126
127#define BLOCKCONV_FOUND() vmaxvq_u8(blconv_mask)
128
129#define BLOCKCONV_STORE(dest) \
130 int8x16_t blconv_add = vandq_s8(vreinterpretq_s8_u8(blconv_mask), blconv_delta); \
131 int8x16_t blconv_result = vaddq_s8(blconv_operand, blconv_add); \
132 vst1q_s8((int8_t *)(dest), blconv_result);
133
134#endif /* defined(__aarch64__) || defined(_M_ARM64) */
135
136ZEND_API const unsigned char zend_tolower_map[256] = {
1370x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1380x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
1390x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
1400x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
1410x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
1420x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
1430x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
1440x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
1450x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
1460x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
1470xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
1480xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
1490xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
1500xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
1510xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
1520xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
153};
154
155ZEND_API const unsigned char zend_toupper_map[256] = {
1560x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
1570x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
1580x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
1590x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
1600x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
1610x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
1620x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
1630x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x7b,0x7c,0x7d,0x7e,0x7f,
1640x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
1650x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
1660xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
1670xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
1680xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
1690xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
1700xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
1710xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
172};
173
174
188
189static zend_long ZEND_FASTCALL zend_atol_internal(const char *str, size_t str_len) /* {{{ */
190{
191 if (!str_len) {
192 str_len = strlen(str);
193 }
194
195 /* Perform following multiplications on unsigned to avoid overflow UB.
196 * For now overflow is silently ignored -- not clear what else can be
197 * done here, especially as the final result of this function may be
198 * used in an unsigned context (e.g. "memory_limit=3G", which overflows
199 * zend_long on 32-bit, but not size_t). */
201 if (str_len>0) {
202 switch (str[str_len-1]) {
203 case 'g':
204 case 'G':
205 retval *= 1024;
207 case 'm':
208 case 'M':
209 retval *= 1024;
211 case 'k':
212 case 'K':
213 retval *= 1024;
214 break;
215 }
216 }
217 return (zend_long) retval;
218}
219/* }}} */
220
221ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len)
222{
223 return zend_atol_internal(str, str_len);
224}
225
226ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len)
227{
228 return (int) zend_atol_internal(str, str_len);
229}
230
231/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */
232#define convert_object_to_type(op, dst, ctype) \
233 ZVAL_UNDEF(dst); \
234 if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), dst, ctype) == FAILURE) { \
235 zend_error(E_WARNING, \
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
240/* }}} */
241
243{
244try_again:
245 switch (Z_TYPE_P(op)) {
246 case IS_REFERENCE:
247 zend_unwrap_reference(op);
248 goto try_again;
249 case IS_STRING:
250 {
251 zend_string *str;
252
253 str = Z_STR_P(op);
254 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) {
255 ZVAL_LONG(op, 0);
256 }
258 break;
259 }
260 case IS_NULL:
261 case IS_FALSE:
262 ZVAL_LONG(op, 0);
263 break;
264 case IS_TRUE:
265 ZVAL_LONG(op, 1);
266 break;
267 case IS_RESOURCE:
268 {
270 zval_ptr_dtor(op);
271 ZVAL_LONG(op, l);
272 }
273 break;
274 case IS_OBJECT:
275 {
276 zval dst;
277
279 zval_ptr_dtor(op);
280
281 if (Z_TYPE(dst) == IS_LONG || Z_TYPE(dst) == IS_DOUBLE) {
282 ZVAL_COPY_VALUE(op, &dst);
283 } else {
284 ZVAL_LONG(op, 1);
285 }
286 }
287 break;
288 }
289}
290/* }}} */
291
292static zend_never_inline zval* ZEND_FASTCALL _zendi_convert_scalar_to_number_silent(zval *op, zval *holder) /* {{{ */
293{
294 switch (Z_TYPE_P(op)) {
295 case IS_NULL:
296 case IS_FALSE:
297 ZVAL_LONG(holder, 0);
298 return holder;
299 case IS_TRUE:
300 ZVAL_LONG(holder, 1);
301 return holder;
302 case IS_STRING:
303 if ((Z_TYPE_INFO_P(holder) = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL_P(holder), &Z_DVAL_P(holder), 1)) == 0) {
304 ZVAL_LONG(holder, 0);
305 }
306 return holder;
307 case IS_RESOURCE:
308 ZVAL_LONG(holder, Z_RES_HANDLE_P(op));
309 return holder;
310 case IS_OBJECT:
312 if (UNEXPECTED(EG(exception)) ||
313 UNEXPECTED(Z_TYPE_P(holder) != IS_LONG && Z_TYPE_P(holder) != IS_DOUBLE)) {
314 ZVAL_LONG(holder, 1);
315 }
316 return holder;
317 case IS_LONG:
318 case IS_DOUBLE:
319 default:
320 return op;
321 }
322}
323/* }}} */
324
325static zend_never_inline zend_result ZEND_FASTCALL _zendi_try_convert_scalar_to_number(zval *op, zval *holder) /* {{{ */
326{
327 switch (Z_TYPE_P(op)) {
328 case IS_NULL:
329 case IS_FALSE:
330 ZVAL_LONG(holder, 0);
331 return SUCCESS;
332 case IS_TRUE:
333 ZVAL_LONG(holder, 1);
334 return SUCCESS;
335 case IS_STRING:
336 {
337 bool trailing_data = false;
338 /* For BC reasons we allow errors so that we can warn on leading numeric string */
339 if (0 == (Z_TYPE_INFO_P(holder) = is_numeric_string_ex(Z_STRVAL_P(op), Z_STRLEN_P(op),
340 &Z_LVAL_P(holder), &Z_DVAL_P(holder), /* allow errors */ true, NULL, &trailing_data))) {
341 /* Will lead to invalid OP type error */
342 return FAILURE;
343 }
344 if (UNEXPECTED(trailing_data)) {
345 zend_error(E_WARNING, "A non-numeric value encountered");
346 if (UNEXPECTED(EG(exception))) {
347 return FAILURE;
348 }
349 }
350 return SUCCESS;
351 }
352 case IS_OBJECT:
353 if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), holder, _IS_NUMBER) == FAILURE
354 || EG(exception)) {
355 return FAILURE;
356 }
357 ZEND_ASSERT(Z_TYPE_P(holder) == IS_LONG || Z_TYPE_P(holder) == IS_DOUBLE);
358 return SUCCESS;
359 case IS_RESOURCE:
360 case IS_ARRAY:
361 return FAILURE;
363 }
364}
365/* }}} */
366
367static zend_always_inline zend_result zendi_try_convert_scalar_to_number(zval *op, zval *holder) /* {{{ */
368{
369 if (Z_TYPE_P(op) == IS_LONG || Z_TYPE_P(op) == IS_DOUBLE) {
370 ZVAL_COPY_VALUE(holder, op);
371 return SUCCESS;
372 } else {
373 return _zendi_try_convert_scalar_to_number(op, holder);
374 }
375}
376/* }}} */
377
378static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval *op, bool *failed) /* {{{ */
379{
380 *failed = 0;
381 switch (Z_TYPE_P(op)) {
382 case IS_NULL:
383 case IS_FALSE:
384 return 0;
385 case IS_TRUE:
386 return 1;
387 case IS_DOUBLE: {
388 double dval = Z_DVAL_P(op);
389 zend_long lval = zend_dval_to_lval(dval);
390 if (!zend_is_long_compatible(dval, lval)) {
392 if (UNEXPECTED(EG(exception))) {
393 *failed = 1;
394 }
395 }
396 return lval;
397 }
398 case IS_STRING:
399 {
400 uint8_t type;
401 zend_long lval;
402 double dval;
403 bool trailing_data = false;
404
405 /* For BC reasons we allow errors so that we can warn on leading numeric string */
406 type = is_numeric_string_ex(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval,
407 /* allow errors */ true, NULL, &trailing_data);
408 if (type == 0) {
409 *failed = 1;
410 return 0;
411 }
412 if (UNEXPECTED(trailing_data)) {
413 zend_error(E_WARNING, "A non-numeric value encountered");
414 if (UNEXPECTED(EG(exception))) {
415 *failed = 1;
416 }
417 }
418 if (EXPECTED(type == IS_LONG)) {
419 return lval;
420 } else {
421 /* Previously we used strtol here, not is_numeric_string,
422 * and strtol gives you LONG_MAX/_MIN on overflow.
423 * We use use saturating conversion to emulate strtol()'s
424 * behaviour.
425 */
426 lval = zend_dval_to_lval_cap(dval);
427 if (!zend_is_long_compatible(dval, lval)) {
429 if (UNEXPECTED(EG(exception))) {
430 *failed = 1;
431 }
432 }
433 return lval;
434 }
435 }
436 case IS_OBJECT:
437 {
438 zval dst;
439 if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &dst, IS_LONG) == FAILURE
440 || EG(exception)) {
441 *failed = 1;
442 return 0;
443 }
444 ZEND_ASSERT(Z_TYPE(dst) == IS_LONG);
445 return Z_LVAL(dst);
446 }
447 case IS_RESOURCE:
448 case IS_ARRAY:
449 *failed = 1;
450 return 0;
452 }
453}
454/* }}} */
455
457{
458 if (EXPECTED(Z_TYPE_P(op) == IS_LONG)) {
459 *failed = false;
460 return Z_LVAL_P(op);
461 }
462 return zendi_try_get_long(op, failed);
463}
464
465#define ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode) \
466 if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \
467 && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation))) { \
468 if (EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2))) { \
469 return SUCCESS; \
470 } \
471 }
472
473#define ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode) \
474 if (UNEXPECTED(Z_TYPE_P(op2) == IS_OBJECT) \
475 && UNEXPECTED(Z_OBJ_HANDLER_P(op2, do_operation)) \
476 && EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2))) { \
477 return SUCCESS; \
478 }
479
480#define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode) \
481 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode) \
482 else \
483 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode)
484
485#define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode) \
486 if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT) \
487 && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation)) \
488 && EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, NULL))) { \
489 return SUCCESS; \
490 }
491
492#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, opcode, sigil) \
493 do { \
494 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \
495 bool failed; \
496 if (Z_ISREF_P(op1)) { \
497 op1 = Z_REFVAL_P(op1); \
498 if (Z_TYPE_P(op1) == IS_LONG) { \
499 op1_lval = Z_LVAL_P(op1); \
500 break; \
501 } \
502 } \
503 ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode); \
504 op1_lval = zendi_try_get_long(op1, &failed); \
505 if (UNEXPECTED(failed)) { \
506 zend_binop_error(sigil, op1, op2); \
507 if (result != op1) { \
508 ZVAL_UNDEF(result); \
509 } \
510 return FAILURE; \
511 } \
512 } else { \
513 op1_lval = Z_LVAL_P(op1); \
514 } \
515 } while (0); \
516 do { \
517 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { \
518 bool failed; \
519 if (Z_ISREF_P(op2)) { \
520 op2 = Z_REFVAL_P(op2); \
521 if (Z_TYPE_P(op2) == IS_LONG) { \
522 op2_lval = Z_LVAL_P(op2); \
523 break; \
524 } \
525 } \
526 ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode); \
527 op2_lval = zendi_try_get_long(op2, &failed); \
528 if (UNEXPECTED(failed)) { \
529 zend_binop_error(sigil, op1, op2); \
530 if (result != op1) { \
531 ZVAL_UNDEF(result); \
532 } \
533 return FAILURE; \
534 } \
535 } else { \
536 op2_lval = Z_LVAL_P(op2); \
537 } \
538 } while (0);
539
541{
542 zend_long tmp;
543
544try_again:
545 switch (Z_TYPE_P(op)) {
546 case IS_NULL:
547 case IS_FALSE:
548 ZVAL_LONG(op, 0);
549 break;
550 case IS_TRUE:
551 ZVAL_LONG(op, 1);
552 break;
553 case IS_RESOURCE:
554 tmp = Z_RES_HANDLE_P(op);
555 zval_ptr_dtor(op);
556 ZVAL_LONG(op, tmp);
557 break;
558 case IS_LONG:
559 break;
560 case IS_DOUBLE:
561 ZVAL_LONG(op, zend_dval_to_lval(Z_DVAL_P(op)));
562 break;
563 case IS_STRING:
564 {
565 zend_string *str = Z_STR_P(op);
566 ZVAL_LONG(op, zval_get_long(op));
568 }
569 break;
570 case IS_ARRAY:
571 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
572 zval_ptr_dtor(op);
573 ZVAL_LONG(op, tmp);
574 break;
575 case IS_OBJECT:
576 {
577 zval dst;
578
580 zval_ptr_dtor(op);
581
582 if (Z_TYPE(dst) == IS_LONG) {
583 ZVAL_LONG(op, Z_LVAL(dst));
584 } else {
585 ZVAL_LONG(op, 1);
586 }
587 return;
588 }
589 case IS_REFERENCE:
590 zend_unwrap_reference(op);
591 goto try_again;
593 }
594}
595/* }}} */
596
598{
599 double tmp;
600
601try_again:
602 switch (Z_TYPE_P(op)) {
603 case IS_NULL:
604 case IS_FALSE:
605 ZVAL_DOUBLE(op, 0.0);
606 break;
607 case IS_TRUE:
608 ZVAL_DOUBLE(op, 1.0);
609 break;
610 case IS_RESOURCE: {
611 double d = (double) Z_RES_HANDLE_P(op);
612 zval_ptr_dtor(op);
613 ZVAL_DOUBLE(op, d);
614 }
615 break;
616 case IS_LONG:
617 ZVAL_DOUBLE(op, (double) Z_LVAL_P(op));
618 break;
619 case IS_DOUBLE:
620 break;
621 case IS_STRING:
622 {
623 zend_string *str = Z_STR_P(op);
624
627 }
628 break;
629 case IS_ARRAY:
630 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
631 zval_ptr_dtor(op);
632 ZVAL_DOUBLE(op, tmp);
633 break;
634 case IS_OBJECT:
635 {
636 zval dst;
637
639 zval_ptr_dtor(op);
640
641 if (Z_TYPE(dst) == IS_DOUBLE) {
642 ZVAL_DOUBLE(op, Z_DVAL(dst));
643 } else {
644 ZVAL_DOUBLE(op, 1.0);
645 }
646 break;
647 }
648 case IS_REFERENCE:
649 zend_unwrap_reference(op);
650 goto try_again;
652 }
653}
654/* }}} */
655
657{
658 zval_ptr_dtor(op);
659 ZVAL_NULL(op);
660}
661/* }}} */
662
664{
665 bool tmp;
666
667try_again:
668 switch (Z_TYPE_P(op)) {
669 case IS_FALSE:
670 case IS_TRUE:
671 break;
672 case IS_NULL:
673 ZVAL_FALSE(op);
674 break;
675 case IS_RESOURCE: {
676 zend_long l = (Z_RES_HANDLE_P(op) ? 1 : 0);
677
678 zval_ptr_dtor(op);
679 ZVAL_BOOL(op, l);
680 }
681 break;
682 case IS_LONG:
683 ZVAL_BOOL(op, Z_LVAL_P(op) ? 1 : 0);
684 break;
685 case IS_DOUBLE:
686 ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0);
687 break;
688 case IS_STRING:
689 {
690 zend_string *str = Z_STR_P(op);
691
692 if (ZSTR_LEN(str) == 0
693 || (ZSTR_LEN(str) == 1 && ZSTR_VAL(str)[0] == '0')) {
694 ZVAL_FALSE(op);
695 } else {
696 ZVAL_TRUE(op);
697 }
699 }
700 break;
701 case IS_ARRAY:
702 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
703 zval_ptr_dtor(op);
704 ZVAL_BOOL(op, tmp);
705 break;
706 case IS_OBJECT:
707 {
708 zval dst;
709
711 zval_ptr_dtor(op);
712
713 if (Z_TYPE_INFO(dst) == IS_FALSE || Z_TYPE_INFO(dst) == IS_TRUE) {
714 Z_TYPE_INFO_P(op) = Z_TYPE_INFO(dst);
715 } else {
716 ZVAL_TRUE(op);
717 }
718 break;
719 }
720 case IS_REFERENCE:
721 zend_unwrap_reference(op);
722 goto try_again;
724 }
725}
726/* }}} */
727
729{
730try_again:
731 switch (Z_TYPE_P(op)) {
732 case IS_UNDEF:
733 case IS_NULL:
734 case IS_FALSE: {
736 break;
737 }
738 case IS_TRUE:
739 ZVAL_CHAR(op, '1');
740 break;
741 case IS_STRING:
742 break;
743 case IS_RESOURCE: {
744 zend_string *str = zend_strpprintf(0, "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
745 zval_ptr_dtor(op);
746 ZVAL_NEW_STR(op, str);
747 break;
748 }
749 case IS_LONG:
751 break;
752 case IS_DOUBLE:
754 break;
755 case IS_ARRAY:
756 zend_error(E_WARNING, "Array to string conversion");
757 zval_ptr_dtor(op);
758 ZVAL_INTERNED_STR(op, ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED));
759 break;
760 case IS_OBJECT: {
761 zval tmp;
762 if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &tmp, IS_STRING) == SUCCESS) {
763 zval_ptr_dtor(op);
764 ZVAL_COPY_VALUE(op, &tmp);
765 return;
766 }
767 if (!EG(exception)) {
768 zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
769 }
770 zval_ptr_dtor(op);
772 break;
773 }
774 case IS_REFERENCE:
775 zend_unwrap_reference(op);
776 goto try_again;
778 }
779}
780/* }}} */
781
783{
784 zend_string *str;
785
787 str = zval_try_get_string_func(op);
788 if (UNEXPECTED(!str)) {
789 return 0;
790 }
791 zval_ptr_dtor(op);
792 ZVAL_STR(op, str);
793 return 1;
794}
795/* }}} */
796
797static void convert_scalar_to_array(zval *op) /* {{{ */
798{
801 ZVAL_ARR(op, ht);
802}
803/* }}} */
804
806{
807try_again:
808 switch (Z_TYPE_P(op)) {
809 case IS_ARRAY:
810 break;
811/* OBJECTS_OPTIMIZE */
812 case IS_OBJECT:
813 if (Z_OBJCE_P(op) == zend_ce_closure) {
814 convert_scalar_to_array(op);
816 /* Optimized version without rebuilding properties HashTable */
818 OBJ_RELEASE(Z_OBJ_P(op));
819 ZVAL_ARR(op, ht);
820 } else {
822 if (obj_ht) {
823 HashTable *new_obj_ht = zend_proptable_to_symtable(obj_ht,
824 (Z_OBJCE_P(op)->default_properties_count ||
826 GC_IS_RECURSIVE(obj_ht)));
827 zval_ptr_dtor(op);
828 ZVAL_ARR(op, new_obj_ht);
830 } else {
831 zval_ptr_dtor(op);
832 /*ZVAL_EMPTY_ARRAY(op);*/
833 array_init(op);
834 }
835 }
836 break;
837 case IS_NULL:
838 /*ZVAL_EMPTY_ARRAY(op);*/
839 array_init(op);
840 break;
841 case IS_REFERENCE:
842 zend_unwrap_reference(op);
843 goto try_again;
844 default:
845 convert_scalar_to_array(op);
846 break;
847 }
848}
849/* }}} */
850
852{
853try_again:
854 switch (Z_TYPE_P(op)) {
855 case IS_ARRAY:
856 {
858 zend_object *obj;
859
861 /* TODO: try not to duplicate immutable arrays as well ??? */
863 } else if (ht != Z_ARR_P(op)) {
864 zval_ptr_dtor(op);
865 } else {
866 GC_DELREF(ht);
867 }
869 obj->properties = ht;
870 ZVAL_OBJ(op, obj);
871 break;
872 }
873 case IS_OBJECT:
874 break;
875 case IS_NULL:
876 object_init(op);
877 break;
878 case IS_REFERENCE:
879 zend_unwrap_reference(op);
880 goto try_again;
881 default: {
882 zval tmp;
883 ZVAL_COPY_VALUE(&tmp, op);
884 object_init(op);
885 zend_hash_add_new(Z_OBJPROP_P(op), ZSTR_KNOWN(ZEND_STR_SCALAR), &tmp);
886 break;
887 }
888 }
889}
890/* }}} */
891
893{
894 zend_error_unchecked(E_DEPRECATED, "Implicit conversion from float %.*H to int loses precision", -1, d);
895}
897{
898 zend_error(E_DEPRECATED, "Implicit conversion from float-string \"%s\" to int loses precision", ZSTR_VAL(s));
899}
900
901ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_strict) /* {{{ */
902{
903try_again:
904 switch (Z_TYPE_P(op)) {
905 case IS_UNDEF:
906 case IS_NULL:
907 case IS_FALSE:
908 return 0;
909 case IS_TRUE:
910 return 1;
911 case IS_RESOURCE:
912 return Z_RES_HANDLE_P(op);
913 case IS_LONG:
914 return Z_LVAL_P(op);
915 case IS_DOUBLE: {
916 double dval = Z_DVAL_P(op);
917 zend_long lval = zend_dval_to_lval(dval);
918 if (UNEXPECTED(is_strict)) {
919 if (!zend_is_long_compatible(dval, lval)) {
921 }
922 }
923 return lval;
924 }
925 case IS_STRING:
926 {
927 uint8_t type;
928 zend_long lval;
929 double dval;
930 if (0 == (type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, true))) {
931 return 0;
932 } else if (EXPECTED(type == IS_LONG)) {
933 return lval;
934 } else {
935 /* Previously we used strtol here, not is_numeric_string,
936 * and strtol gives you LONG_MAX/_MIN on overflow.
937 * We use saturating conversion to emulate strtol()'s
938 * behaviour.
939 */
940 /* Most usages are expected to not be (int) casts */
941 lval = zend_dval_to_lval_cap(dval);
942 if (UNEXPECTED(is_strict)) {
943 if (!zend_is_long_compatible(dval, lval)) {
945 }
946 }
947 return lval;
948 }
949 }
950 case IS_ARRAY:
951 return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
952 case IS_OBJECT:
953 {
954 zval dst;
956 if (Z_TYPE(dst) == IS_LONG) {
957 return Z_LVAL(dst);
958 } else {
959 return 1;
960 }
961 }
962 case IS_REFERENCE:
963 op = Z_REFVAL_P(op);
964 goto try_again;
966 }
967 return 0;
968}
969/* }}} */
970
972{
973try_again:
974 switch (Z_TYPE_P(op)) {
975 case IS_NULL:
976 case IS_FALSE:
977 return 0.0;
978 case IS_TRUE:
979 return 1.0;
980 case IS_RESOURCE:
981 return (double) Z_RES_HANDLE_P(op);
982 case IS_LONG:
983 return (double) Z_LVAL_P(op);
984 case IS_DOUBLE:
985 return Z_DVAL_P(op);
986 case IS_STRING:
987 return zend_strtod(Z_STRVAL_P(op), NULL);
988 case IS_ARRAY:
989 return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1.0 : 0.0;
990 case IS_OBJECT:
991 {
992 zval dst;
994
995 if (Z_TYPE(dst) == IS_DOUBLE) {
996 return Z_DVAL(dst);
997 } else {
998 return 1.0;
999 }
1000 }
1001 case IS_REFERENCE:
1002 op = Z_REFVAL_P(op);
1003 goto try_again;
1005 }
1006 return 0.0;
1007}
1008/* }}} */
1009
1010static zend_always_inline zend_string* __zval_get_string_func(zval *op, bool try) /* {{{ */
1011{
1012try_again:
1013 switch (Z_TYPE_P(op)) {
1014 case IS_UNDEF:
1015 case IS_NULL:
1016 case IS_FALSE:
1017 return ZSTR_EMPTY_ALLOC();
1018 case IS_TRUE:
1019 return ZSTR_CHAR('1');
1020 case IS_RESOURCE:
1021 return zend_strpprintf(0, "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
1022 case IS_LONG:
1023 return zend_long_to_str(Z_LVAL_P(op));
1024 case IS_DOUBLE:
1025 return zend_double_to_str(Z_DVAL_P(op));
1026 case IS_ARRAY:
1027 zend_error(E_WARNING, "Array to string conversion");
1028 return (try && UNEXPECTED(EG(exception))) ?
1029 NULL : ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
1030 case IS_OBJECT: {
1031 zval tmp;
1032 if (Z_OBJ_HT_P(op)->cast_object(Z_OBJ_P(op), &tmp, IS_STRING) == SUCCESS) {
1033 return Z_STR(tmp);
1034 }
1035 if (!EG(exception)) {
1036 zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
1037 }
1038 return try ? NULL : ZSTR_EMPTY_ALLOC();
1039 }
1040 case IS_REFERENCE:
1041 op = Z_REFVAL_P(op);
1042 goto try_again;
1043 case IS_STRING:
1044 return zend_string_copy(Z_STR_P(op));
1046 }
1047 return NULL;
1048}
1049/* }}} */
1050
1052{
1053 return __zval_get_string_func(op, 0);
1054}
1055/* }}} */
1056
1058{
1059 return __zval_get_string_func(op, 1);
1060}
1061/* }}} */
1062
1063static ZEND_COLD zend_never_inline void ZEND_FASTCALL zend_binop_error(const char *operator, zval *op1, zval *op2) /* {{{ */ {
1064 if (EG(exception)) {
1065 return;
1066 }
1067
1068 zend_type_error("Unsupported operand types: %s %s %s",
1070}
1071/* }}} */
1072
1073static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
1074{
1075 if (result == op1 && Z_ARR_P(op1) == Z_ARR_P(op2)) {
1076 /* $a += $a */
1077 return;
1078 }
1079 if (result != op1) {
1081 } else {
1083 }
1085}
1086/* }}} */
1087
1088static zend_always_inline zend_result add_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
1089{
1090 uint8_t type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
1091
1092 if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
1093 fast_long_add_function(result, op1, op2);
1094 return SUCCESS;
1095 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
1097 return SUCCESS;
1098 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
1099 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
1100 return SUCCESS;
1101 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
1102 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
1103 return SUCCESS;
1104 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_ARRAY, IS_ARRAY))) {
1105 add_function_array(result, op1, op2);
1106 return SUCCESS;
1107 } else {
1108 return FAILURE;
1109 }
1110} /* }}} */
1111
1112static zend_never_inline zend_result ZEND_FASTCALL add_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
1113{
1114 ZVAL_DEREF(op1);
1115 ZVAL_DEREF(op2);
1116 if (add_function_fast(result, op1, op2) == SUCCESS) {
1117 return SUCCESS;
1118 }
1119
1121
1122 zval op1_copy, op2_copy;
1123 if (UNEXPECTED(zendi_try_convert_scalar_to_number(op1, &op1_copy) == FAILURE)
1124 || UNEXPECTED(zendi_try_convert_scalar_to_number(op2, &op2_copy) == FAILURE)) {
1125 zend_binop_error("+", op1, op2);
1126 if (result != op1) {
1128 }
1129 return FAILURE;
1130 }
1131
1132 if (result == op1) {
1134 }
1135
1136 if (add_function_fast(result, &op1_copy, &op2_copy) == SUCCESS) {
1137 return SUCCESS;
1138 }
1139
1140 ZEND_ASSERT(0 && "Operation must succeed");
1141 return FAILURE;
1142} /* }}} */
1143
1145{
1146 if (add_function_fast(result, op1, op2) == SUCCESS) {
1147 return SUCCESS;
1148 } else {
1149 return add_function_slow(result, op1, op2);
1150 }
1151}
1152/* }}} */
1153
1154static zend_always_inline zend_result sub_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
1155{
1156 uint8_t type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
1157
1158 if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
1159 fast_long_sub_function(result, op1, op2);
1160 return SUCCESS;
1161 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
1163 return SUCCESS;
1164 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
1165 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
1166 return SUCCESS;
1167 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
1168 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
1169 return SUCCESS;
1170 } else {
1171 return FAILURE;
1172 }
1173}
1174/* }}} */
1175
1176static zend_never_inline zend_result ZEND_FASTCALL sub_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
1177{
1178 ZVAL_DEREF(op1);
1179 ZVAL_DEREF(op2);
1180 if (sub_function_fast(result, op1, op2) == SUCCESS) {
1181 return SUCCESS;
1182 }
1183
1185
1186 zval op1_copy, op2_copy;
1187 if (UNEXPECTED(zendi_try_convert_scalar_to_number(op1, &op1_copy) == FAILURE)
1188 || UNEXPECTED(zendi_try_convert_scalar_to_number(op2, &op2_copy) == FAILURE)) {
1189 zend_binop_error("-", op1, op2);
1190 if (result != op1) {
1192 }
1193 return FAILURE;
1194 }
1195
1196 if (result == op1) {
1198 }
1199
1200 if (sub_function_fast(result, &op1_copy, &op2_copy) == SUCCESS) {
1201 return SUCCESS;
1202 }
1203
1204 ZEND_ASSERT(0 && "Operation must succeed");
1205 return FAILURE;
1206}
1207/* }}} */
1208
1210{
1211 if (sub_function_fast(result, op1, op2) == SUCCESS) {
1212 return SUCCESS;
1213 } else {
1214 return sub_function_slow(result, op1, op2);
1215 }
1216}
1217/* }}} */
1218
1219static zend_always_inline zend_result mul_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
1220{
1221 uint8_t type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
1222
1223 if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
1224 zend_long overflow;
1227 Z_LVAL_P(result), Z_DVAL_P(result), overflow);
1228 Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
1229 return SUCCESS;
1230 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
1232 return SUCCESS;
1233 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
1234 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
1235 return SUCCESS;
1236 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
1237 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
1238 return SUCCESS;
1239 } else {
1240 return FAILURE;
1241 }
1242}
1243/* }}} */
1244
1245static zend_never_inline zend_result ZEND_FASTCALL mul_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
1246{
1247 ZVAL_DEREF(op1);
1248 ZVAL_DEREF(op2);
1249 if (mul_function_fast(result, op1, op2) == SUCCESS) {
1250 return SUCCESS;
1251 }
1252
1254
1255 zval op1_copy, op2_copy;
1256 if (UNEXPECTED(zendi_try_convert_scalar_to_number(op1, &op1_copy) == FAILURE)
1257 || UNEXPECTED(zendi_try_convert_scalar_to_number(op2, &op2_copy) == FAILURE)) {
1258 zend_binop_error("*", op1, op2);
1259 if (result != op1) {
1261 }
1262 return FAILURE;
1263 }
1264
1265 if (result == op1) {
1267 }
1268
1269 if (mul_function_fast(result, &op1_copy, &op2_copy) == SUCCESS) {
1270 return SUCCESS;
1271 }
1272
1273 ZEND_ASSERT(0 && "Operation must succeed");
1274 return FAILURE;
1275}
1276/* }}} */
1277
1279{
1280 if (mul_function_fast(result, op1, op2) == SUCCESS) {
1281 return SUCCESS;
1282 } else {
1283 return mul_function_slow(result, op1, op2);
1284 }
1285}
1286/* }}} */
1287
1288static void ZEND_COLD zend_power_base_0_exponent_lt_0_error(void)
1289{
1290 zend_error(E_DEPRECATED, "Power of base 0 and negative exponent is deprecated");
1291}
1292
1293static double safe_pow(double base, double exponent)
1294{
1295 if (UNEXPECTED(base == 0.0 && exponent < 0.0)) {
1296 zend_power_base_0_exponent_lt_0_error();
1297 }
1298
1299 return pow(base, exponent);
1300}
1301
1302static zend_result ZEND_FASTCALL pow_function_base(zval *result, zval *op1, zval *op2) /* {{{ */
1303{
1304 uint8_t type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
1305
1306 if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
1307 if (Z_LVAL_P(op2) >= 0) {
1308 zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
1309
1310 if (i == 0) {
1311 ZVAL_LONG(result, 1L);
1312 return SUCCESS;
1313 } else if (l2 == 0) {
1314 ZVAL_LONG(result, 0);
1315 return SUCCESS;
1316 }
1317
1318 while (i >= 1) {
1319 zend_long overflow;
1320 double dval = 0.0;
1321
1322 if (i % 2) {
1323 --i;
1324 ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
1325 if (overflow) {
1326 ZVAL_DOUBLE(result, dval * safe_pow(l2, i));
1327 return SUCCESS;
1328 }
1329 } else {
1330 i /= 2;
1331 ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
1332 if (overflow) {
1333 ZVAL_DOUBLE(result, (double)l1 * safe_pow(dval, i));
1334 return SUCCESS;
1335 }
1336 }
1337 }
1338 /* i == 0 */
1339 ZVAL_LONG(result, l1);
1340 } else {
1341 ZVAL_DOUBLE(result, safe_pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
1342 }
1343 return SUCCESS;
1344 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
1345 ZVAL_DOUBLE(result, safe_pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
1346 return SUCCESS;
1347 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
1348 ZVAL_DOUBLE(result, safe_pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
1349 return SUCCESS;
1350 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
1351 ZVAL_DOUBLE(result, safe_pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
1352 return SUCCESS;
1353 } else {
1354 return FAILURE;
1355 }
1356}
1357/* }}} */
1358
1360{
1361 ZVAL_DEREF(op1);
1362 ZVAL_DEREF(op2);
1363 if (pow_function_base(result, op1, op2) == SUCCESS) {
1364 return SUCCESS;
1365 }
1366
1368
1369 zval op1_copy, op2_copy;
1370 if (UNEXPECTED(zendi_try_convert_scalar_to_number(op1, &op1_copy) == FAILURE)
1371 || UNEXPECTED(zendi_try_convert_scalar_to_number(op2, &op2_copy) == FAILURE)) {
1372 zend_binop_error("**", op1, op2);
1373 if (result != op1) {
1375 }
1376 return FAILURE;
1377 }
1378
1379 if (result == op1) {
1381 }
1382
1383 if (pow_function_base(result, &op1_copy, &op2_copy) == SUCCESS) {
1384 return SUCCESS;
1385 }
1386
1387 ZEND_ASSERT(0 && "Operation must succeed");
1388 return FAILURE;
1389}
1390/* }}} */
1391
1392/* Returns SUCCESS/TYPES_NOT_HANDLED/DIV_BY_ZERO */
1393#define TYPES_NOT_HANDLED 1
1394#define DIV_BY_ZERO 2
1395static int ZEND_FASTCALL div_function_base(zval *result, zval *op1, zval *op2) /* {{{ */
1396{
1397 uint8_t type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
1398
1399 if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
1400 if (Z_LVAL_P(op2) == 0) {
1401 return DIV_BY_ZERO;
1402 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
1403 /* Prevent overflow error/crash */
1404 ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
1405 return SUCCESS;
1406 }
1407 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
1409 } else {
1410 ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1411 }
1412 return SUCCESS;
1413 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
1414 if (Z_DVAL_P(op2) == 0) {
1415 return DIV_BY_ZERO;
1416 }
1418 return SUCCESS;
1419 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
1420 if (Z_LVAL_P(op2) == 0) {
1421 return DIV_BY_ZERO;
1422 }
1423 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1424 return SUCCESS;
1425 } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
1426 if (Z_DVAL_P(op2) == 0) {
1427 return DIV_BY_ZERO;
1428 }
1429 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1430 return SUCCESS;
1431 } else {
1432 return TYPES_NOT_HANDLED;
1433 }
1434}
1435/* }}} */
1436
1438{
1439 ZVAL_DEREF(op1);
1440 ZVAL_DEREF(op2);
1441
1442 int retval = div_function_base(result, op1, op2);
1443 if (EXPECTED(retval == SUCCESS)) {
1444 return SUCCESS;
1445 }
1446
1447 if (UNEXPECTED(retval == DIV_BY_ZERO)) {
1448 goto div_by_zero;
1449 }
1450
1452
1453 zval result_copy, op1_copy, op2_copy;
1454 if (UNEXPECTED(zendi_try_convert_scalar_to_number(op1, &op1_copy) == FAILURE)
1455 || UNEXPECTED(zendi_try_convert_scalar_to_number(op2, &op2_copy) == FAILURE)) {
1456 zend_binop_error("/", op1, op2);
1457 if (result != op1) {
1459 }
1460 return FAILURE;
1461 }
1462
1463 retval = div_function_base(&result_copy, &op1_copy, &op2_copy);
1464 if (retval == SUCCESS) {
1465 if (result == op1) {
1467 }
1468 ZVAL_COPY_VALUE(result, &result_copy);
1469 return SUCCESS;
1470 }
1471
1472div_by_zero:
1473 ZEND_ASSERT(retval == DIV_BY_ZERO && "TYPES_NOT_HANDLED should not occur here");
1474 if (result != op1) {
1476 }
1478 return FAILURE;
1479}
1480/* }}} */
1481
1483{
1484 zend_long op1_lval, op2_lval;
1485
1486 convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_MOD, "%");
1487
1488 if (op2_lval == 0) {
1489 /* modulus by zero */
1490 if (EG(current_execute_data) && !CG(in_compilation)) {
1492 } else {
1493 zend_error_noreturn(E_ERROR, "Modulo by zero");
1494 }
1495 if (op1 != result) {
1497 }
1498 return FAILURE;
1499 }
1500
1501 if (op1 == result) {
1503 }
1504
1505 if (op2_lval == -1) {
1506 /* Prevent overflow error/crash if op1==LONG_MIN */
1507 ZVAL_LONG(result, 0);
1508 return SUCCESS;
1509 }
1510
1511 ZVAL_LONG(result, op1_lval % op2_lval);
1512 return SUCCESS;
1513}
1514/* }}} */
1515
1517{
1518 int op1_val, op2_val;
1519
1520 do {
1521 if (Z_TYPE_P(op1) == IS_FALSE) {
1522 op1_val = 0;
1523 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1524 op1_val = 1;
1525 } else {
1526 if (Z_ISREF_P(op1)) {
1527 op1 = Z_REFVAL_P(op1);
1528 if (Z_TYPE_P(op1) == IS_FALSE) {
1529 op1_val = 0;
1530 break;
1531 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1532 op1_val = 1;
1533 break;
1534 }
1535 }
1537 op1_val = zval_is_true(op1);
1538 }
1539 } while (0);
1540 do {
1541 if (Z_TYPE_P(op2) == IS_FALSE) {
1542 op2_val = 0;
1543 } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1544 op2_val = 1;
1545 } else {
1546 if (Z_ISREF_P(op2)) {
1547 op2 = Z_REFVAL_P(op2);
1548 if (Z_TYPE_P(op2) == IS_FALSE) {
1549 op2_val = 0;
1550 break;
1551 } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1552 op2_val = 1;
1553 break;
1554 }
1555 }
1557 op2_val = zval_is_true(op2);
1558 }
1559 } while (0);
1560
1561 ZVAL_BOOL(result, op1_val ^ op2_val);
1562 return SUCCESS;
1563}
1564/* }}} */
1565
1567{
1568 if (Z_TYPE_P(op1) < IS_TRUE) {
1570 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1572 } else {
1573 if (Z_ISREF_P(op1)) {
1574 op1 = Z_REFVAL_P(op1);
1575 if (Z_TYPE_P(op1) < IS_TRUE) {
1577 return SUCCESS;
1578 } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1580 return SUCCESS;
1581 }
1582 }
1584
1586 }
1587 return SUCCESS;
1588}
1589/* }}} */
1590
1592{
1593try_again:
1594 switch (Z_TYPE_P(op1)) {
1595 case IS_LONG:
1597 return SUCCESS;
1598 case IS_DOUBLE: {
1599 zend_long lval = zend_dval_to_lval(Z_DVAL_P(op1));
1600 if (!zend_is_long_compatible(Z_DVAL_P(op1), lval)) {
1602 if (EG(exception)) {
1603 if (result != op1) {
1605 }
1606 return FAILURE;
1607 }
1608 }
1609 ZVAL_LONG(result, ~lval);
1610 return SUCCESS;
1611 }
1612 case IS_STRING: {
1613 size_t i;
1614
1615 if (Z_STRLEN_P(op1) == 1) {
1617 ZVAL_CHAR(result, not);
1618 } else {
1619 ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
1620 for (i = 0; i < Z_STRLEN_P(op1); i++) {
1621 Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1622 }
1623 Z_STRVAL_P(result)[i] = 0;
1624 }
1625 return SUCCESS;
1626 }
1627 case IS_REFERENCE:
1628 op1 = Z_REFVAL_P(op1);
1629 goto try_again;
1630 default:
1632
1633 if (result != op1) {
1635 }
1636 zend_type_error("Cannot perform bitwise not on %s", zend_zval_value_name(op1));
1637 return FAILURE;
1638 }
1639}
1640/* }}} */
1641
1643{
1644 zend_long op1_lval, op2_lval;
1645
1648 return SUCCESS;
1649 }
1650
1651 ZVAL_DEREF(op1);
1652 ZVAL_DEREF(op2);
1653
1655 zval *longer, *shorter;
1656 zend_string *str;
1657 size_t i;
1658
1659 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1660 if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1662 if (result==op1) {
1663 zval_ptr_dtor_str(result);
1664 }
1665 ZVAL_CHAR(result, or);
1666 return SUCCESS;
1667 }
1668 longer = op1;
1669 shorter = op2;
1670 } else {
1671 longer = op2;
1672 shorter = op1;
1673 }
1674
1675 str = zend_string_alloc(Z_STRLEN_P(longer), 0);
1676 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1677 ZSTR_VAL(str)[i] = Z_STRVAL_P(longer)[i] | Z_STRVAL_P(shorter)[i];
1678 }
1679 memcpy(ZSTR_VAL(str) + i, Z_STRVAL_P(longer) + i, Z_STRLEN_P(longer) - i + 1);
1680 if (result==op1) {
1681 zval_ptr_dtor_str(result);
1682 }
1683 ZVAL_NEW_STR(result, str);
1684 return SUCCESS;
1685 }
1686
1687 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1688 bool failed;
1690 op1_lval = zendi_try_get_long(op1, &failed);
1691 if (UNEXPECTED(failed)) {
1692 zend_binop_error("|", op1, op2);
1693 if (result != op1) {
1695 }
1696 return FAILURE;
1697 }
1698 } else {
1699 op1_lval = Z_LVAL_P(op1);
1700 }
1701 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1702 bool failed;
1704 op2_lval = zendi_try_get_long(op2, &failed);
1705 if (UNEXPECTED(failed)) {
1706 zend_binop_error("|", op1, op2);
1707 if (result != op1) {
1709 }
1710 return FAILURE;
1711 }
1712 } else {
1713 op2_lval = Z_LVAL_P(op2);
1714 }
1715
1716 if (op1 == result) {
1718 }
1719 ZVAL_LONG(result, op1_lval | op2_lval);
1720 return SUCCESS;
1721}
1722/* }}} */
1723
1725{
1726 zend_long op1_lval, op2_lval;
1727
1730 return SUCCESS;
1731 }
1732
1733 ZVAL_DEREF(op1);
1734 ZVAL_DEREF(op2);
1735
1736 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1737 zval *longer, *shorter;
1738 zend_string *str;
1739 size_t i;
1740
1741 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1742 if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1744 if (result==op1) {
1745 zval_ptr_dtor_str(result);
1746 }
1747 ZVAL_CHAR(result, and);
1748 return SUCCESS;
1749 }
1750 longer = op1;
1751 shorter = op2;
1752 } else {
1753 longer = op2;
1754 shorter = op1;
1755 }
1756
1757 str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1758 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1759 ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] & Z_STRVAL_P(longer)[i];
1760 }
1761 ZSTR_VAL(str)[i] = 0;
1762 if (result==op1) {
1763 zval_ptr_dtor_str(result);
1764 }
1765 ZVAL_NEW_STR(result, str);
1766 return SUCCESS;
1767 }
1768
1769 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1770 bool failed;
1772 op1_lval = zendi_try_get_long(op1, &failed);
1773 if (UNEXPECTED(failed)) {
1774 zend_binop_error("&", op1, op2);
1775 if (result != op1) {
1777 }
1778 return FAILURE;
1779 }
1780 } else {
1781 op1_lval = Z_LVAL_P(op1);
1782 }
1783 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1784 bool failed;
1786 op2_lval = zendi_try_get_long(op2, &failed);
1787 if (UNEXPECTED(failed)) {
1788 zend_binop_error("&", op1, op2);
1789 if (result != op1) {
1791 }
1792 return FAILURE;
1793 }
1794 } else {
1795 op2_lval = Z_LVAL_P(op2);
1796 }
1797
1798 if (op1 == result) {
1800 }
1801 ZVAL_LONG(result, op1_lval & op2_lval);
1802 return SUCCESS;
1803}
1804/* }}} */
1805
1807{
1808 zend_long op1_lval, op2_lval;
1809
1812 return SUCCESS;
1813 }
1814
1815 ZVAL_DEREF(op1);
1816 ZVAL_DEREF(op2);
1817
1818 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1819 zval *longer, *shorter;
1820 zend_string *str;
1821 size_t i;
1822
1823 if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1824 if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1826 if (result==op1) {
1827 zval_ptr_dtor_str(result);
1828 }
1829 ZVAL_CHAR(result, xor);
1830 return SUCCESS;
1831 }
1832 longer = op1;
1833 shorter = op2;
1834 } else {
1835 longer = op2;
1836 shorter = op1;
1837 }
1838
1839 str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1840 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1841 ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] ^ Z_STRVAL_P(longer)[i];
1842 }
1843 ZSTR_VAL(str)[i] = 0;
1844 if (result==op1) {
1845 zval_ptr_dtor_str(result);
1846 }
1847 ZVAL_NEW_STR(result, str);
1848 return SUCCESS;
1849 }
1850
1851 if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1852 bool failed;
1854 op1_lval = zendi_try_get_long(op1, &failed);
1855 if (UNEXPECTED(failed)) {
1856 zend_binop_error("^", op1, op2);
1857 if (result != op1) {
1859 }
1860 return FAILURE;
1861 }
1862 } else {
1863 op1_lval = Z_LVAL_P(op1);
1864 }
1865 if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1866 bool failed;
1868 op2_lval = zendi_try_get_long(op2, &failed);
1869 if (UNEXPECTED(failed)) {
1870 zend_binop_error("^", op1, op2);
1871 if (result != op1) {
1873 }
1874 return FAILURE;
1875 }
1876 } else {
1877 op2_lval = Z_LVAL_P(op2);
1878 }
1879
1880 if (op1 == result) {
1882 }
1883 ZVAL_LONG(result, op1_lval ^ op2_lval);
1884 return SUCCESS;
1885}
1886/* }}} */
1887
1889{
1890 zend_long op1_lval, op2_lval;
1891
1892 convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SL, "<<");
1893
1894 /* prevent wrapping quirkiness on some processors where << 64 + x == << x */
1895 if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1896 if (EXPECTED(op2_lval > 0)) {
1897 if (op1 == result) {
1899 }
1900 ZVAL_LONG(result, 0);
1901 return SUCCESS;
1902 } else {
1903 if (EG(current_execute_data) && !CG(in_compilation)) {
1904 zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1905 } else {
1906 zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1907 }
1908 if (op1 != result) {
1910 }
1911 return FAILURE;
1912 }
1913 }
1914
1915 if (op1 == result) {
1917 }
1918
1919 /* Perform shift on unsigned numbers to get well-defined wrap behavior. */
1920 ZVAL_LONG(result, (zend_long) ((zend_ulong) op1_lval << op2_lval));
1921 return SUCCESS;
1922}
1923/* }}} */
1924
1926{
1927 zend_long op1_lval, op2_lval;
1928
1929 convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SR, ">>");
1930
1931 /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
1932 if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1933 if (EXPECTED(op2_lval > 0)) {
1934 if (op1 == result) {
1936 }
1937 ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
1938 return SUCCESS;
1939 } else {
1940 if (EG(current_execute_data) && !CG(in_compilation)) {
1941 zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1942 } else {
1943 zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1944 }
1945 if (op1 != result) {
1947 }
1948 return FAILURE;
1949 }
1950 }
1951
1952 if (op1 == result) {
1954 }
1955
1956 ZVAL_LONG(result, op1_lval >> op2_lval);
1957 return SUCCESS;
1958}
1959/* }}} */
1960
1962{
1963 zval *orig_op1 = op1;
1964 zend_string *op1_string, *op2_string;
1965 bool free_op1_string = false;
1966 bool free_op2_string = false;
1967
1968 do {
1969 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
1970 op1_string = Z_STR_P(op1);
1971 } else {
1972 if (Z_ISREF_P(op1)) {
1973 op1 = Z_REFVAL_P(op1);
1974 if (Z_TYPE_P(op1) == IS_STRING) {
1975 op1_string = Z_STR_P(op1);
1976 break;
1977 }
1978 }
1980 op1_string = zval_get_string_func(op1);
1981 if (UNEXPECTED(EG(exception))) {
1982 zend_string_release(op1_string);
1983 if (orig_op1 != result) {
1985 }
1986 return FAILURE;
1987 }
1988 free_op1_string = true;
1989 if (result == op1) {
1990 if (UNEXPECTED(op1 == op2)) {
1991 op2_string = op1_string;
1992 goto has_op2_string;
1993 }
1994 }
1995 }
1996 } while (0);
1997 do {
1998 if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1999 op2_string = Z_STR_P(op2);
2000 } else {
2001 if (Z_ISREF_P(op2)) {
2002 op2 = Z_REFVAL_P(op2);
2003 if (Z_TYPE_P(op2) == IS_STRING) {
2004 op2_string = Z_STR_P(op2);
2005 break;
2006 }
2007 }
2008 /* hold an additional reference because a userland function could free this */
2009 if (!free_op1_string) {
2010 op1_string = zend_string_copy(op1_string);
2011 free_op1_string = true;
2012 }
2014 op2_string = zval_get_string_func(op2);
2015 if (UNEXPECTED(EG(exception))) {
2016 zend_string_release(op1_string);
2017 zend_string_release(op2_string);
2018 if (orig_op1 != result) {
2020 }
2021 return FAILURE;
2022 }
2023 free_op2_string = true;
2024 }
2025 } while (0);
2026
2027has_op2_string:;
2028 if (UNEXPECTED(ZSTR_LEN(op1_string) == 0)) {
2029 if (EXPECTED(result != op2 || Z_TYPE_P(result) != IS_STRING)) {
2030 if (result == orig_op1) {
2031 i_zval_ptr_dtor(result);
2032 }
2033 if (free_op2_string) {
2034 /* transfer ownership of op2_string */
2035 ZVAL_STR(result, op2_string);
2036 free_op2_string = false;
2037 } else {
2038 ZVAL_STR_COPY(result, op2_string);
2039 }
2040 }
2041 } else if (UNEXPECTED(ZSTR_LEN(op2_string) == 0)) {
2042 if (EXPECTED(result != op1 || Z_TYPE_P(result) != IS_STRING)) {
2043 if (result == orig_op1) {
2044 i_zval_ptr_dtor(result);
2045 }
2046 if (free_op1_string) {
2047 /* transfer ownership of op1_string */
2048 ZVAL_STR(result, op1_string);
2049 free_op1_string = false;
2050 } else {
2051 ZVAL_STR_COPY(result, op1_string);
2052 }
2053 }
2054 } else {
2055 size_t op1_len = ZSTR_LEN(op1_string);
2056 size_t op2_len = ZSTR_LEN(op2_string);
2057 size_t result_len = op1_len + op2_len;
2058 zend_string *result_str;
2059 uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_string, op2_string);
2060
2061 if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) {
2062 if (free_op1_string) zend_string_release(op1_string);
2063 if (free_op2_string) zend_string_release(op2_string);
2064 zend_throw_error(NULL, "String size overflow");
2065 if (orig_op1 != result) {
2067 }
2068 return FAILURE;
2069 }
2070
2071 if (result == op1) {
2072 /* Destroy the old result first to drop the refcount, such that $x .= ...; may happen in-place. */
2073 if (free_op1_string) {
2074 /* op1_string will be used as the result, so we should not free it */
2075 i_zval_ptr_dtor(result);
2076 /* Set it to NULL in case that the extension will throw an out-of-memory error.
2077 * Otherwise the shutdown sequence will try to free this again. */
2079 free_op1_string = false;
2080 }
2081 /* special case, perform operations on result */
2082 result_str = zend_string_extend(op1_string, result_len, 0);
2083 /* account for the case where result_str == op1_string == op2_string and the realloc is done */
2084 if (op1_string == op2_string) {
2085 if (free_op2_string) {
2086 zend_string_release(op2_string);
2087 free_op2_string = false;
2088 }
2089 op2_string = result_str;
2090 }
2091 } else {
2092 result_str = zend_string_alloc(result_len, 0);
2093 memcpy(ZSTR_VAL(result_str), ZSTR_VAL(op1_string), op1_len);
2094 if (result == orig_op1) {
2095 i_zval_ptr_dtor(result);
2096 }
2097 }
2098 GC_ADD_FLAGS(result_str, flags);
2099
2100 ZVAL_NEW_STR(result, result_str);
2101 memcpy(ZSTR_VAL(result_str) + op1_len, ZSTR_VAL(op2_string), op2_len);
2102 ZSTR_VAL(result_str)[result_len] = '\0';
2103 }
2104
2105 if (free_op1_string) zend_string_release(op1_string);
2106 if (free_op2_string) zend_string_release(op2_string);
2107
2108 return SUCCESS;
2109}
2110/* }}} */
2111
2112ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, bool case_insensitive) /* {{{ */
2113{
2114 zend_string *tmp_str1, *tmp_str2;
2115 zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
2116 zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
2117 int ret;
2118
2119 if (case_insensitive) {
2120 ret = zend_binary_strcasecmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
2121 } else {
2122 ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
2123 }
2124
2125 zend_tmp_string_release(tmp_str1);
2126 zend_tmp_string_release(tmp_str2);
2127 return ret;
2128}
2129/* }}} */
2130
2132{
2133 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
2135 if (Z_STR_P(op1) == Z_STR_P(op2)) {
2136 return 0;
2137 } else {
2139 }
2140 } else {
2141 zend_string *tmp_str1, *tmp_str2;
2142 zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
2143 zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
2144 int ret = zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
2145
2146 zend_tmp_string_release(tmp_str1);
2147 zend_tmp_string_release(tmp_str2);
2148 return ret;
2149 }
2150}
2151/* }}} */
2152
2154{
2155 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
2157 if (Z_STR_P(op1) == Z_STR_P(op2)) {
2158 return 0;
2159 } else {
2161 }
2162 } else {
2163 zend_string *tmp_str1, *tmp_str2;
2164 zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
2165 zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
2166 int ret = zend_binary_strcasecmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2));
2167
2168 zend_tmp_string_release(tmp_str1);
2169 zend_tmp_string_release(tmp_str2);
2170 return ret;
2171 }
2172}
2173/* }}} */
2174
2176{
2177 zend_string *tmp_str1, *tmp_str2;
2178 zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
2179 zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
2180 int ret = strcoll(ZSTR_VAL(str1), ZSTR_VAL(str2));
2181
2182 zend_tmp_string_release(tmp_str1);
2183 zend_tmp_string_release(tmp_str2);
2184 return ret;
2185}
2186/* }}} */
2187
2189{
2190 double d1, d2;
2191
2192 d1 = zval_get_double(op1);
2193 d2 = zval_get_double(op2);
2194
2195 return ZEND_THREEWAY_COMPARE(d1, d2);
2196}
2197/* }}} */
2198
2204/* }}} */
2205
2206static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
2207{
2208 zend_long str_lval;
2209 double str_dval;
2210 uint8_t type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
2211
2212 if (type == IS_LONG) {
2213 return lval > str_lval ? 1 : lval < str_lval ? -1 : 0;
2214 }
2215
2216 if (type == IS_DOUBLE) {
2217 return ZEND_THREEWAY_COMPARE((double) lval, str_dval);
2218 }
2219
2220 zend_string *lval_as_str = zend_long_to_str(lval);
2221 int cmp_result = zend_binary_strcmp(
2222 ZSTR_VAL(lval_as_str), ZSTR_LEN(lval_as_str), ZSTR_VAL(str), ZSTR_LEN(str));
2223 zend_string_release(lval_as_str);
2224 return ZEND_NORMALIZE_BOOL(cmp_result);
2225}
2226/* }}} */
2227
2228static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2229{
2230 zend_long str_lval;
2231 double str_dval;
2232 uint8_t type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
2233
2234 if (type == IS_LONG) {
2235 return ZEND_THREEWAY_COMPARE(dval, (double) str_lval);
2236 }
2237
2238 if (type == IS_DOUBLE) {
2239 return ZEND_THREEWAY_COMPARE(dval, str_dval);
2240 }
2241
2242 zend_string *dval_as_str = zend_double_to_str(dval);
2243 int cmp_result = zend_binary_strcmp(
2244 ZSTR_VAL(dval_as_str), ZSTR_LEN(dval_as_str), ZSTR_VAL(str), ZSTR_LEN(str));
2245 zend_string_release(dval_as_str);
2246 return ZEND_NORMALIZE_BOOL(cmp_result);
2247}
2248/* }}} */
2249
2251{
2252 int converted = 0;
2253 zval op1_copy, op2_copy;
2254
2255 while (1) {
2256 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
2257 case TYPE_PAIR(IS_LONG, IS_LONG):
2258 return Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0);
2259
2261 return ZEND_THREEWAY_COMPARE(Z_DVAL_P(op1), (double)Z_LVAL_P(op2));
2262
2264 return ZEND_THREEWAY_COMPARE((double)Z_LVAL_P(op1), Z_DVAL_P(op2));
2265
2268
2270 return zend_compare_arrays(op1, op2);
2271
2272 case TYPE_PAIR(IS_NULL, IS_NULL):
2273 case TYPE_PAIR(IS_NULL, IS_FALSE):
2274 case TYPE_PAIR(IS_FALSE, IS_NULL):
2276 case TYPE_PAIR(IS_TRUE, IS_TRUE):
2277 return 0;
2278
2279 case TYPE_PAIR(IS_NULL, IS_TRUE):
2280 return -1;
2281
2282 case TYPE_PAIR(IS_TRUE, IS_NULL):
2283 return 1;
2284
2286 if (Z_STR_P(op1) == Z_STR_P(op2)) {
2287 return 0;
2288 }
2290
2292 return Z_STRLEN_P(op2) == 0 ? 0 : -1;
2293
2295 return Z_STRLEN_P(op1) == 0 ? 0 : 1;
2296
2298 return compare_long_to_string(Z_LVAL_P(op1), Z_STR_P(op2));
2299
2301 return -compare_long_to_string(Z_LVAL_P(op2), Z_STR_P(op1));
2302
2304 if (zend_isnan(Z_DVAL_P(op1))) {
2305 return 1;
2306 }
2307
2308 return compare_double_to_string(Z_DVAL_P(op1), Z_STR_P(op2));
2309
2311 if (zend_isnan(Z_DVAL_P(op2))) {
2312 return 1;
2313 }
2314
2315 return -compare_double_to_string(Z_DVAL_P(op2), Z_STR_P(op1));
2316
2318 return 1;
2319
2321 return -1;
2322
2323 default:
2324 if (Z_ISREF_P(op1)) {
2325 op1 = Z_REFVAL_P(op1);
2326 continue;
2327 } else if (Z_ISREF_P(op2)) {
2328 op2 = Z_REFVAL_P(op2);
2329 continue;
2330 }
2331
2332 if (Z_TYPE_P(op1) == IS_OBJECT
2333 && Z_TYPE_P(op2) == IS_OBJECT
2334 && Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
2335 return 0;
2336 } else if (Z_TYPE_P(op1) == IS_OBJECT) {
2337 return Z_OBJ_HANDLER_P(op1, compare)(op1, op2);
2338 } else if (Z_TYPE_P(op2) == IS_OBJECT) {
2339 return Z_OBJ_HANDLER_P(op2, compare)(op1, op2);
2340 }
2341
2342 if (!converted) {
2343 if (Z_TYPE_P(op1) < IS_TRUE) {
2344 return zval_is_true(op2) ? -1 : 0;
2345 } else if (Z_TYPE_P(op1) == IS_TRUE) {
2346 return zval_is_true(op2) ? 0 : 1;
2347 } else if (Z_TYPE_P(op2) < IS_TRUE) {
2348 return zval_is_true(op1) ? 1 : 0;
2349 } else if (Z_TYPE_P(op2) == IS_TRUE) {
2350 return zval_is_true(op1) ? 0 : -1;
2351 } else {
2352 op1 = _zendi_convert_scalar_to_number_silent(op1, &op1_copy);
2353 op2 = _zendi_convert_scalar_to_number_silent(op2, &op2_copy);
2354 if (EG(exception)) {
2355 return 1; /* to stop comparison of arrays */
2356 }
2357 converted = 1;
2358 }
2359 } else if (Z_TYPE_P(op1)==IS_ARRAY) {
2360 return 1;
2361 } else if (Z_TYPE_P(op2)==IS_ARRAY) {
2362 return -1;
2363 } else {
2365 zend_throw_error(NULL, "Unsupported operand types");
2366 return 1;
2367 }
2368 }
2369 }
2370}
2371/* }}} */
2372
2373/* return int to be compatible with compare_func_t */
2374static int hash_zval_identical_function(zval *z1, zval *z2) /* {{{ */
2375{
2376 /* is_identical_function() returns 1 in case of identity and 0 in case
2377 * of a difference;
2378 * whereas this comparison function is expected to return 0 on identity,
2379 * and non zero otherwise.
2380 */
2381 ZVAL_DEREF(z1);
2382 ZVAL_DEREF(z2);
2383 return fast_is_not_identical_function(z1, z2);
2384}
2385/* }}} */
2386
2388{
2389 if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
2390 return 0;
2391 }
2392 switch (Z_TYPE_P(op1)) {
2393 case IS_NULL:
2394 case IS_FALSE:
2395 case IS_TRUE:
2396 return 1;
2397 case IS_LONG:
2398 return (Z_LVAL_P(op1) == Z_LVAL_P(op2));
2399 case IS_RESOURCE:
2400 return (Z_RES_P(op1) == Z_RES_P(op2));
2401 case IS_DOUBLE:
2402 return (Z_DVAL_P(op1) == Z_DVAL_P(op2));
2403 case IS_STRING:
2404 return zend_string_equals(Z_STR_P(op1), Z_STR_P(op2));
2405 case IS_ARRAY:
2406 return (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
2407 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1) == 0);
2408 case IS_OBJECT:
2409 return (Z_OBJ_P(op1) == Z_OBJ_P(op2));
2410 default:
2411 return 0;
2412 }
2413}
2414/* }}} */
2415
2421/* }}} */
2422
2428/* }}} */
2429
2435/* }}} */
2436
2442/* }}} */
2443
2449/* }}} */
2450
2456/* }}} */
2457
2459{
2460 uint32_t i;
2461 ZEND_ASSERT(interface_ce->ce_flags & ZEND_ACC_INTERFACE);
2462
2463 if (class_ce->num_interfaces) {
2465 for (i = 0; i < class_ce->num_interfaces; i++) {
2466 if (class_ce->interfaces[i] == interface_ce) {
2467 return 1;
2468 }
2469 }
2470 }
2471 return 0;
2472}
2473/* }}} */
2474
2476{
2477 ZEND_ASSERT(instance_ce != ce && "Should have been checked already");
2478 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2479 uint32_t i;
2480
2481 if (instance_ce->num_interfaces) {
2483 for (i = 0; i < instance_ce->num_interfaces; i++) {
2484 if (instance_ce->interfaces[i] == ce) {
2485 return 1;
2486 }
2487 }
2488 }
2489 return 0;
2490 } else {
2491 while (1) {
2492 instance_ce = instance_ce->parent;
2493 if (instance_ce == ce) {
2494 return 1;
2495 }
2496 if (instance_ce == NULL) {
2497 return 0;
2498 }
2499 }
2500 }
2501}
2502/* }}} */
2503
2504#define LOWER_CASE 1
2505#define UPPER_CASE 2
2506#define NUMERIC 3
2507
2509{
2510 const char *p = ZSTR_VAL(str);
2511 const char *e = ZSTR_VAL(str) + ZSTR_LEN(str);
2512 while (p < e) {
2513 char c = *p++;
2514 if (UNEXPECTED( c < '0' || c > 'z' || (c < 'a' && c > 'Z') || (c < 'A' && c > '9') ) ) {
2515 return false;
2516 }
2517 }
2518 return true;
2519}
2520
2521static bool ZEND_FASTCALL increment_string(zval *str) /* {{{ */
2522{
2523 int carry=0;
2524 size_t pos=Z_STRLEN_P(str)-1;
2525 char *s;
2526 zend_string *t;
2527 int last=0; /* Shut up the compiler warning */
2528 int ch;
2529
2530 if (UNEXPECTED(Z_STRLEN_P(str) == 0)) {
2531 zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated");
2532 if (EG(exception)) {
2533 return false;
2534 }
2535 /* A userland error handler can change the type from string to something else */
2536 zval_ptr_dtor(str);
2537 ZVAL_CHAR(str, '1');
2538 return true;
2539 }
2540
2542 zend_string *zstr = Z_STR_P(str);
2543 zend_string_addref(zstr);
2544 zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated");
2545 if (EG(exception)) {
2546 zend_string_release(zstr);
2547 return false;
2548 }
2549 zval_ptr_dtor(str);
2550 ZVAL_STR(str, zstr);
2551 }
2552
2553 if (!Z_REFCOUNTED_P(str)) {
2554 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2556 } else if (Z_REFCOUNT_P(str) > 1) {
2557 /* Only release string after allocation succeeded. */
2558 zend_string *orig_str = Z_STR_P(str);
2559 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2560 GC_DELREF(orig_str);
2561 } else {
2562 zend_string_forget_hash_val(Z_STR_P(str));
2563 }
2564 s = Z_STRVAL_P(str);
2565
2566 do {
2567 ch = s[pos];
2568 if (ch >= 'a' && ch <= 'z') {
2569 if (ch == 'z') {
2570 s[pos] = 'a';
2571 carry=1;
2572 } else {
2573 s[pos]++;
2574 carry=0;
2575 }
2577 } else if (ch >= 'A' && ch <= 'Z') {
2578 if (ch == 'Z') {
2579 s[pos] = 'A';
2580 carry=1;
2581 } else {
2582 s[pos]++;
2583 carry=0;
2584 }
2586 } else if (ch >= '0' && ch <= '9') {
2587 if (ch == '9') {
2588 s[pos] = '0';
2589 carry=1;
2590 } else {
2591 s[pos]++;
2592 carry=0;
2593 }
2594 last = NUMERIC;
2595 } else {
2596 carry=0;
2597 break;
2598 }
2599 if (carry == 0) {
2600 break;
2601 }
2602 } while (pos-- > 0);
2603
2604 if (carry) {
2605 t = zend_string_alloc(Z_STRLEN_P(str)+1, 0);
2606 memcpy(ZSTR_VAL(t) + 1, Z_STRVAL_P(str), Z_STRLEN_P(str));
2607 ZSTR_VAL(t)[Z_STRLEN_P(str) + 1] = '\0';
2608 switch (last) {
2609 case NUMERIC:
2610 ZSTR_VAL(t)[0] = '1';
2611 break;
2612 case UPPER_CASE:
2613 ZSTR_VAL(t)[0] = 'A';
2614 break;
2615 case LOWER_CASE:
2616 ZSTR_VAL(t)[0] = 'a';
2617 break;
2618 }
2619 zend_string_free(Z_STR_P(str));
2620 ZVAL_NEW_STR(str, t);
2621 }
2622 return true;
2623}
2624/* }}} */
2625
2627{
2628try_again:
2629 switch (Z_TYPE_P(op1)) {
2630 case IS_LONG:
2631 fast_long_increment_function(op1);
2632 break;
2633 case IS_DOUBLE:
2634 Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2635 break;
2636 case IS_NULL:
2637 ZVAL_LONG(op1, 1);
2638 break;
2639 case IS_STRING: {
2640 zend_long lval;
2641 double dval;
2642
2643 switch (is_numeric_str_function(Z_STR_P(op1), &lval, &dval)) {
2644 case IS_LONG:
2645 zval_ptr_dtor_str(op1);
2646 if (lval == ZEND_LONG_MAX) {
2647 /* switch to double */
2648 double d = (double)lval;
2649 ZVAL_DOUBLE(op1, d+1);
2650 } else {
2651 ZVAL_LONG(op1, lval+1);
2652 }
2653 break;
2654 case IS_DOUBLE:
2655 zval_ptr_dtor_str(op1);
2656 ZVAL_DOUBLE(op1, dval+1);
2657 break;
2658 default:
2659 /* Perl style string increment */
2660 increment_string(op1);
2661 if (EG(exception)) {
2662 return FAILURE;
2663 }
2664 break;
2665 }
2666 }
2667 break;
2668 case IS_FALSE:
2669 case IS_TRUE: {
2670 /* Error handler can undef/change type of op1, save it and reset it in case those cases */
2671 zval copy;
2673 zend_error(E_WARNING, "Increment on type bool has no effect, this will change in the next major version of PHP");
2676 if (EG(exception)) {
2677 return FAILURE;
2678 }
2679 break;
2680 }
2681 case IS_REFERENCE:
2682 op1 = Z_REFVAL_P(op1);
2683 goto try_again;
2684 case IS_OBJECT: {
2685 if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2686 zval op2;
2687 ZVAL_LONG(&op2, 1);
2688 if (Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, &op2) == SUCCESS) {
2689 return SUCCESS;
2690 }
2691 }
2692 zval tmp;
2693 if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp, _IS_NUMBER) == SUCCESS) {
2694 ZEND_ASSERT(Z_TYPE(tmp) == IS_LONG || Z_TYPE(tmp) == IS_DOUBLE);
2696 ZVAL_COPY_VALUE(op1, &tmp);
2697 goto try_again;
2698 }
2700 }
2701 case IS_RESOURCE:
2702 case IS_ARRAY:
2703 zend_type_error("Cannot increment %s", zend_zval_value_name(op1));
2704 return FAILURE;
2706 }
2707 return SUCCESS;
2708}
2709/* }}} */
2710
2712{
2713 zend_long lval;
2714 double dval;
2715
2716try_again:
2717 switch (Z_TYPE_P(op1)) {
2718 case IS_LONG:
2719 fast_long_decrement_function(op1);
2720 break;
2721 case IS_DOUBLE:
2722 Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2723 break;
2724 case IS_STRING: /* Like perl we only support string increment */
2725 if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
2726 zend_error(E_DEPRECATED, "Decrement on empty string is deprecated as non-numeric");
2727 if (EG(exception)) {
2728 return FAILURE;
2729 }
2730 /* A userland error handler can change the type from string to something else */
2732 ZVAL_LONG(op1, -1);
2733 break;
2734 }
2735 switch (is_numeric_str_function(Z_STR_P(op1), &lval, &dval)) {
2736 case IS_LONG:
2737 zval_ptr_dtor_str(op1);
2738 if (lval == ZEND_LONG_MIN) {
2739 double d = (double)lval;
2740 ZVAL_DOUBLE(op1, d-1);
2741 } else {
2742 ZVAL_LONG(op1, lval-1);
2743 }
2744 break;
2745 case IS_DOUBLE:
2746 zval_ptr_dtor_str(op1);
2747 ZVAL_DOUBLE(op1, dval - 1);
2748 break;
2749 default: {
2750 /* Error handler can unset the variable */
2751 zend_string *zstr = Z_STR_P(op1);
2752 zend_string_addref(zstr);
2753 zend_error(E_DEPRECATED, "Decrement on non-numeric string has no effect and is deprecated");
2754 if (EG(exception)) {
2755 zend_string_release(zstr);
2756 return FAILURE;
2757 }
2759 ZVAL_STR(op1, zstr);
2760 }
2761 }
2762 break;
2763 case IS_NULL: {
2764 /* Error handler can undef/change type of op1, save it and reset it in case those cases */
2765 zval copy;
2767 zend_error(E_WARNING, "Decrement on type null has no effect, this will change in the next major version of PHP");
2770 if (EG(exception)) {
2771 return FAILURE;
2772 }
2773 break;
2774 }
2775 case IS_FALSE:
2776 case IS_TRUE: {
2777 /* Error handler can undef/change type of op1, save it and reset it in case those cases */
2778 zval copy;
2780 zend_error(E_WARNING, "Decrement on type bool has no effect, this will change in the next major version of PHP");
2783 if (EG(exception)) {
2784 return FAILURE;
2785 }
2786 break;
2787 }
2788 case IS_REFERENCE:
2789 op1 = Z_REFVAL_P(op1);
2790 goto try_again;
2791 case IS_OBJECT: {
2792 if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2793 zval op2;
2794 ZVAL_LONG(&op2, 1);
2795 if (Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, &op2) == SUCCESS) {
2796 return SUCCESS;
2797 }
2798 }
2799 zval tmp;
2800 if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp, _IS_NUMBER) == SUCCESS) {
2801 ZEND_ASSERT(Z_TYPE(tmp) == IS_LONG || Z_TYPE(tmp) == IS_DOUBLE);
2803 ZVAL_COPY_VALUE(op1, &tmp);
2804 goto try_again;
2805 }
2807 }
2808 case IS_RESOURCE:
2809 case IS_ARRAY:
2810 zend_type_error("Cannot decrement %s", zend_zval_value_name(op1));
2811 return FAILURE;
2813 }
2814
2815 return SUCCESS;
2816}
2817/* }}} */
2818
2819ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op) /* {{{ */
2820{
2821 return i_zend_is_true(op);
2822}
2823/* }}} */
2824
2826{
2827 zend_object *zobj = Z_OBJ_P(op);
2828 zval tmp;
2829 if (zobj->handlers->cast_object(zobj, &tmp, _IS_BOOL) == SUCCESS) {
2830 return Z_TYPE(tmp) == IS_TRUE;
2831 }
2832 zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(zobj->ce->name));
2833 return false;
2834}
2835/* }}} */
2836
2838{
2839#ifdef ZEND_USE_TOLOWER_L
2840# if defined(ZEND_WIN32) && defined(_MSC_VER)
2841 current_locale = _get_current_locale();
2842# else
2843 current_locale = uselocale(0);
2844# endif
2845#endif
2846#if defined(ZEND_WIN32) && defined(_MSC_VER)
2847 if (MB_CUR_MAX > 1) {
2848 unsigned int cp = ___lc_codepage_func();
2849 CG(variable_width_locale) = 1;
2850 // TODO: EUC-* are also ASCII compatible ???
2851 CG(ascii_compatible_locale) =
2852 cp == 65001; /* UTF-8 */
2853 } else {
2854 CG(variable_width_locale) = 0;
2855 CG(ascii_compatible_locale) = 1;
2856 }
2857#elif defined(MB_CUR_MAX)
2858 /* Check if current locale uses variable width encoding */
2859 if (MB_CUR_MAX > 1) {
2860#ifdef HAVE_NL_LANGINFO
2861 const char *charmap = nl_langinfo(CODESET);
2862#else
2863 char buf[16];
2864 const char *charmap = NULL;
2865 const char *locale = setlocale(LC_CTYPE, NULL);
2866
2867 if (locale) {
2868 const char *dot = strchr(locale, '.');
2869 const char *modifier;
2870
2871 if (dot) {
2872 dot++;
2873 modifier = strchr(dot, '@');
2874 if (!modifier) {
2875 charmap = dot;
2876 } else if (modifier - dot < sizeof(buf)) {
2877 memcpy(buf, dot, modifier - dot);
2878 buf[modifier - dot] = '\0';
2879 charmap = buf;
2880 }
2881 }
2882 }
2883#endif
2884 CG(variable_width_locale) = 1;
2885 CG(ascii_compatible_locale) = 0;
2886
2887 if (charmap) {
2888 size_t len = strlen(charmap);
2889 static const char *ascii_compatible_charmaps[] = {
2890 "utf-8",
2891 "utf8",
2892 // TODO: EUC-* are also ASCII compatible ???
2893 NULL
2894 };
2895 const char **p;
2896 /* Check if current locale is ASCII compatible */
2897 for (p = ascii_compatible_charmaps; *p; p++) {
2898 if (zend_binary_strcasecmp(charmap, len, *p, strlen(*p)) == 0) {
2899 CG(ascii_compatible_locale) = 1;
2900 break;
2901 }
2902 }
2903 }
2904
2905 } else {
2906 CG(variable_width_locale) = 0;
2907 CG(ascii_compatible_locale) = 1;
2908 }
2909#else
2910 /* We can't determine current charset. Assume the worst case */
2911 CG(variable_width_locale) = 1;
2912 CG(ascii_compatible_locale) = 0;
2913#endif
2914}
2915/* }}} */
2916
2918{
2919 /* Use the C.UTF-8 locale so that readline can process UTF-8 input, while not interfering
2920 * with single-byte locale-dependent functions used by PHP. */
2921 if (!setlocale(LC_CTYPE, "C.UTF-8")) {
2922 setlocale(LC_CTYPE, "C");
2923 }
2924}
2925
2926static zend_always_inline void zend_str_tolower_impl(char *dest, const char *str, size_t length) /* {{{ */ {
2927 unsigned char *p = (unsigned char*)str;
2928 unsigned char *q = (unsigned char*)dest;
2929 unsigned char *end = p + length;
2930#ifdef HAVE_BLOCKCONV
2931 if (length >= BLOCKCONV_STRIDE) {
2932 BLOCKCONV_INIT_RANGE('A', 'Z');
2933 BLOCKCONV_INIT_DELTA('a' - 'A');
2934 do {
2935 BLOCKCONV_LOAD(p);
2936 BLOCKCONV_STORE(q);
2937 p += BLOCKCONV_STRIDE;
2938 q += BLOCKCONV_STRIDE;
2939 } while (p + BLOCKCONV_STRIDE <= end);
2940 }
2941#endif
2942 while (p < end) {
2943 *q++ = zend_tolower_ascii(*p++);
2944 }
2945}
2946/* }}} */
2947
2948static zend_always_inline void zend_str_toupper_impl(char *dest, const char *str, size_t length) /* {{{ */ {
2949 unsigned char *p = (unsigned char*)str;
2950 unsigned char *q = (unsigned char*)dest;
2951 unsigned char *end = p + length;
2952#ifdef HAVE_BLOCKCONV
2953 if (length >= BLOCKCONV_STRIDE) {
2954 BLOCKCONV_INIT_RANGE('a', 'z');
2955 BLOCKCONV_INIT_DELTA('A' - 'a');
2956 do {
2957 BLOCKCONV_LOAD(p);
2958 BLOCKCONV_STORE(q);
2959 p += BLOCKCONV_STRIDE;
2960 q += BLOCKCONV_STRIDE;
2961 } while (p + BLOCKCONV_STRIDE <= end);
2962 }
2963#endif
2964 while (p < end) {
2965 *q++ = zend_toupper_ascii(*p++);
2966 }
2967}
2968/* }}} */
2969
2970ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length) /* {{{ */
2971{
2972 zend_str_tolower_impl(dest, source, length);
2973 dest[length] = '\0';
2974 return dest;
2975}
2976/* }}} */
2977
2978ZEND_API char* ZEND_FASTCALL zend_str_toupper_copy(char *dest, const char *source, size_t length) /* {{{ */
2979{
2980 zend_str_toupper_impl(dest, source, length);
2981 dest[length] = '\0';
2982 return dest;
2983}
2984/* }}} */
2985
2986ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length) /* {{{ */
2987{
2988 return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2989}
2990/* }}} */
2991
2992ZEND_API char* ZEND_FASTCALL zend_str_toupper_dup(const char *source, size_t length) /* {{{ */
2993{
2994 return zend_str_toupper_copy((char *)emalloc(length+1), source, length);
2995}
2996/* }}} */
2997
2998ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length) /* {{{ */
2999{
3000 zend_str_tolower_impl(str, (const char*)str, length);
3001}
3002/* }}} */
3003
3004ZEND_API void ZEND_FASTCALL zend_str_toupper(char *str, size_t length) /* {{{ */
3005{
3006 zend_str_toupper_impl(str, (const char*)str, length);
3007}
3008/* }}} */
3009
3010
3011ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length) /* {{{ */
3012{
3013 const unsigned char *p = (const unsigned char*)source;
3014 const unsigned char *end = p + length;
3015
3016 while (p < end) {
3017 if (*p != zend_tolower_ascii(*p)) {
3018 char *res = (char*)emalloc(length + 1);
3019 unsigned char *r;
3020
3021 if (p != (const unsigned char*)source) {
3022 memcpy(res, source, p - (const unsigned char*)source);
3023 }
3024 r = (unsigned char*)p + (res - source);
3025 zend_str_tolower_impl((char *)r, (const char*)p, end - p);
3026 res[length] = '\0';
3027 return res;
3028 }
3029 p++;
3030 }
3031 return NULL;
3032}
3033/* }}} */
3034
3035ZEND_API char* ZEND_FASTCALL zend_str_toupper_dup_ex(const char *source, size_t length) /* {{{ */
3036{
3037 const unsigned char *p = (const unsigned char*)source;
3038 const unsigned char *end = p + length;
3039
3040 while (p < end) {
3041 if (*p != zend_toupper_ascii(*p)) {
3042 char *res = (char*)emalloc(length + 1);
3043 unsigned char *r;
3044
3045 if (p != (const unsigned char*)source) {
3046 memcpy(res, source, p - (const unsigned char*)source);
3047 }
3048 r = (unsigned char*)p + (res - source);
3049 zend_str_toupper_impl((char *)r, (const char*)p, end - p);
3050 res[length] = '\0';
3051 return res;
3052 }
3053 p++;
3054 }
3055 return NULL;
3056}
3057/* }}} */
3058
3060{
3061 size_t length = ZSTR_LEN(str);
3062 unsigned char *p = (unsigned char *) ZSTR_VAL(str);
3063 unsigned char *end = p + length;
3064
3065#ifdef HAVE_BLOCKCONV
3066 BLOCKCONV_INIT_RANGE('A', 'Z');
3067 while (p + BLOCKCONV_STRIDE <= end) {
3068 BLOCKCONV_LOAD(p);
3069 if (BLOCKCONV_FOUND()) {
3070 zend_string *res = zend_string_alloc(length, persistent);
3071 memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str));
3072 unsigned char *q = (unsigned char*) ZSTR_VAL(res) + (p - (unsigned char*) ZSTR_VAL(str));
3073
3074 /* Lowercase the chunk we already compared. */
3075 BLOCKCONV_INIT_DELTA('a' - 'A');
3076 BLOCKCONV_STORE(q);
3077
3078 /* Lowercase the rest of the string. */
3079 p += BLOCKCONV_STRIDE;
3080 q += BLOCKCONV_STRIDE;
3081 zend_str_tolower_impl((char *) q, (const char *) p, end - p);
3082 ZSTR_VAL(res)[length] = '\0';
3083 return res;
3084 }
3085 p += BLOCKCONV_STRIDE;
3086 }
3087#endif
3088
3089 while (p < end) {
3090 if (*p != zend_tolower_ascii(*p)) {
3091 zend_string *res = zend_string_alloc(length, persistent);
3092 memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*) ZSTR_VAL(str));
3093
3094 unsigned char *q = (unsigned char*) ZSTR_VAL(res) + (p - (unsigned char*) ZSTR_VAL(str));
3095 while (p < end) {
3096 *q++ = zend_tolower_ascii(*p++);
3097 }
3098 ZSTR_VAL(res)[length] = '\0';
3099 return res;
3100 }
3101 p++;
3102 }
3103
3104 return zend_string_copy(str);
3105}
3106/* }}} */
3107
3109{
3110 size_t length = ZSTR_LEN(str);
3111 unsigned char *p = (unsigned char *) ZSTR_VAL(str);
3112 unsigned char *end = p + length;
3113
3114#ifdef HAVE_BLOCKCONV
3115 BLOCKCONV_INIT_RANGE('a', 'z');
3116 while (p + BLOCKCONV_STRIDE <= end) {
3117 BLOCKCONV_LOAD(p);
3118 if (BLOCKCONV_FOUND()) {
3119 zend_string *res = zend_string_alloc(length, persistent);
3120 memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str));
3121 unsigned char *q = (unsigned char *) ZSTR_VAL(res) + (p - (unsigned char *) ZSTR_VAL(str));
3122
3123 /* Uppercase the chunk we already compared. */
3124 BLOCKCONV_INIT_DELTA('A' - 'a');
3125 BLOCKCONV_STORE(q);
3126
3127 /* Uppercase the rest of the string. */
3128 p += BLOCKCONV_STRIDE;
3129 q += BLOCKCONV_STRIDE;
3130 zend_str_toupper_impl((char *) q, (const char *) p, end - p);
3131 ZSTR_VAL(res)[length] = '\0';
3132 return res;
3133 }
3134 p += BLOCKCONV_STRIDE;
3135 }
3136#endif
3137
3138 while (p < end) {
3139 if (*p != zend_toupper_ascii(*p)) {
3140 zend_string *res = zend_string_alloc(length, persistent);
3141 memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*) ZSTR_VAL(str));
3142
3143 unsigned char *q = (unsigned char *) ZSTR_VAL(res) + (p - (unsigned char *) ZSTR_VAL(str));
3144 while (p < end) {
3145 *q++ = zend_toupper_ascii(*p++);
3146 }
3147 ZSTR_VAL(res)[length] = '\0';
3148 return res;
3149 }
3150 p++;
3151 }
3152
3153 return zend_string_copy(str);
3154}
3155/* }}} */
3156
3157ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
3158{
3159 int retval;
3160
3161 if (s1 == s2) {
3162 return 0;
3163 }
3164 retval = memcmp(s1, s2, MIN(len1, len2));
3165 if (!retval) {
3166 return ZEND_THREEWAY_COMPARE(len1, len2);
3167 } else {
3168 return retval;
3169 }
3170}
3171/* }}} */
3172
3173ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
3174{
3175 int retval;
3176
3177 if (s1 == s2) {
3178 return 0;
3179 }
3180 retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
3181 if (!retval) {
3182 return ZEND_THREEWAY_COMPARE(MIN(length, len1), MIN(length, len2));
3183 } else {
3184 return retval;
3185 }
3186}
3187/* }}} */
3188
3189ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
3190{
3191 size_t len;
3192 int c1, c2;
3193
3194 if (s1 == s2) {
3195 return 0;
3196 }
3197
3198 len = MIN(len1, len2);
3199 while (len--) {
3200 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
3201 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
3202 if (c1 != c2) {
3203 return c1 - c2;
3204 }
3205 }
3206
3207 return ZEND_THREEWAY_COMPARE(len1, len2);
3208}
3209/* }}} */
3210
3211ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
3212{
3213 size_t len;
3214 int c1, c2;
3215
3216 if (s1 == s2) {
3217 return 0;
3218 }
3219 len = MIN(length, MIN(len1, len2));
3220 while (len--) {
3221 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
3222 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
3223 if (c1 != c2) {
3224 return c1 - c2;
3225 }
3226 }
3227
3228 return ZEND_THREEWAY_COMPARE(MIN(length, len1), MIN(length, len2));
3229}
3230/* }}} */
3231
3232ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
3233{
3234 size_t len;
3235 int c1, c2;
3236
3237 if (s1 == s2) {
3238 return 0;
3239 }
3240
3241 len = MIN(len1, len2);
3242 while (len--) {
3243 c1 = zend_tolower((int)*(unsigned char *)s1++);
3244 c2 = zend_tolower((int)*(unsigned char *)s2++);
3245 if (c1 != c2) {
3246 return c1 - c2;
3247 }
3248 }
3249
3250 return ZEND_THREEWAY_COMPARE(len1, len2);
3251}
3252/* }}} */
3253
3254ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
3255{
3256 size_t len;
3257 int c1, c2;
3258
3259 if (s1 == s2) {
3260 return 0;
3261 }
3262 len = MIN(length, MIN(len1, len2));
3263 while (len--) {
3264 c1 = zend_tolower((int)*(unsigned char *)s1++);
3265 c2 = zend_tolower((int)*(unsigned char *)s2++);
3266 if (c1 != c2) {
3267 return c1 - c2;
3268 }
3269 }
3270
3271 return ZEND_THREEWAY_COMPARE(MIN(length, len1), MIN(length, len2));
3272}
3273/* }}} */
3274
3276{
3278}
3279/* }}} */
3280
3282{
3284}
3285/* }}} */
3286
3288{
3289 uint8_t ret1, ret2;
3290 int oflow1, oflow2;
3291 zend_long lval1 = 0, lval2 = 0;
3292 double dval1 = 0.0, dval2 = 0.0;
3293
3294 if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, false, &oflow1, NULL)) &&
3295 (ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, false, &oflow2, NULL))) {
3296#if ZEND_ULONG_MAX == 0xFFFFFFFF
3297 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
3298 ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
3299 || (oflow1 == -1 && dval1 < -9007199254740991.))) {
3300#else
3301 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
3302#endif
3303 /* both values are integers overflown to the same side, and the
3304 * double comparison may have resulted in crucial accuracy lost */
3305 goto string_cmp;
3306 }
3307 if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) {
3308 if (ret1 != IS_DOUBLE) {
3309 if (oflow2) {
3310 /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
3311 return 0;
3312 }
3313 dval1 = (double) lval1;
3314 } else if (ret2 != IS_DOUBLE) {
3315 if (oflow1) {
3316 return 0;
3317 }
3318 dval2 = (double) lval2;
3319 } else if (dval1 == dval2 && !zend_finite(dval1)) {
3320 /* Both values overflowed and have the same sign,
3321 * so a numeric comparison would be inaccurate */
3322 goto string_cmp;
3323 }
3324 return dval1 == dval2;
3325 } else { /* they both have to be long's */
3326 return lval1 == lval2;
3327 }
3328 } else {
3329string_cmp:
3330 return zend_string_equal_content(s1, s2);
3331 }
3332}
3333/* }}} */
3334
3336{
3337 uint8_t ret1, ret2;
3338 int oflow1, oflow2;
3339 zend_long lval1 = 0, lval2 = 0;
3340 double dval1 = 0.0, dval2 = 0.0;
3341
3342 if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, false, &oflow1, NULL)) &&
3343 (ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, false, &oflow2, NULL))) {
3344#if ZEND_ULONG_MAX == 0xFFFFFFFF
3345 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
3346 ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
3347 || (oflow1 == -1 && dval1 < -9007199254740991.))) {
3348#else
3349 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
3350#endif
3351 /* both values are integers overflowed to the same side, and the
3352 * double comparison may have resulted in crucial accuracy lost */
3353 goto string_cmp;
3354 }
3355 if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) {
3356 if (ret1 != IS_DOUBLE) {
3357 if (oflow2) {
3358 /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
3359 return -1 * oflow2;
3360 }
3361 dval1 = (double) lval1;
3362 } else if (ret2 != IS_DOUBLE) {
3363 if (oflow1) {
3364 return oflow1;
3365 }
3366 dval2 = (double) lval2;
3367 } else if (dval1 == dval2 && !zend_finite(dval1)) {
3368 /* Both values overflowed and have the same sign,
3369 * so a numeric comparison would be inaccurate */
3370 goto string_cmp;
3371 }
3372 dval1 = dval1 - dval2;
3373 return ZEND_NORMALIZE_BOOL(dval1);
3374 } else { /* they both have to be long's */
3375 return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0);
3376 }
3377 } else {
3378 int strcmp_ret;
3379string_cmp:
3380 strcmp_ret = zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len);
3381 return ZEND_NORMALIZE_BOOL(strcmp_ret);
3382 }
3383}
3384/* }}} */
3385
3386static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
3387{
3388 return zend_compare(z1, z2);
3389}
3390/* }}} */
3391
3393{
3394 return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0);
3395}
3396/* }}} */
3397
3399{
3401}
3402/* }}} */
3403
3405{
3406 if (Z_OBJ_P(o1) == Z_OBJ_P(o2)) {
3407 return 0;
3408 }
3409
3410 if (Z_OBJ_HT_P(o1)->compare == NULL) {
3411 return 1;
3412 } else {
3413 return Z_OBJ_HT_P(o1)->compare(o1, o2);
3414 }
3415}
3416/* }}} */
3417
3419{
3420 if ((zend_ulong)num <= 9) {
3421 return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
3422 } else {
3423 char buf[MAX_LENGTH_OF_LONG + 1];
3424 char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
3425 zend_string *str = zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
3427 return str;
3428 }
3429}
3430/* }}} */
3431
3433{
3434 if (num <= 9) {
3435 return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
3436 } else {
3437 char buf[MAX_LENGTH_OF_LONG + 1];
3438 char *res = zend_print_ulong_to_buf(buf + sizeof(buf) - 1, num);
3439 zend_string *str = zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
3441 return str;
3442 }
3443}
3444
3445/* buf points to the END of the buffer */
3446static zend_always_inline char *zend_print_u64_to_buf(char *buf, uint64_t num64) {
3447#if SIZEOF_ZEND_LONG == 8
3448 return zend_print_ulong_to_buf(buf, num64);
3449#else
3450 *buf = '\0';
3451 while (num64 > ZEND_ULONG_MAX) {
3452 *--buf = (char) (num64 % 10) + '0';
3453 num64 /= 10;
3454 }
3455
3456 zend_ulong num = (zend_ulong) num64;
3457 do {
3458 *--buf = (char) (num % 10) + '0';
3459 num /= 10;
3460 } while (num > 0);
3461 return buf;
3462#endif
3463}
3464
3465/* buf points to the END of the buffer */
3466static zend_always_inline char *zend_print_i64_to_buf(char *buf, int64_t num) {
3467 if (num < 0) {
3468 char *result = zend_print_u64_to_buf(buf, ~((uint64_t) num) + 1);
3469 *--result = '-';
3470 return result;
3471 } else {
3472 return zend_print_u64_to_buf(buf, num);
3473 }
3474}
3475
3477{
3478 if (num <= 9) {
3479 return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
3480 } else {
3481 char buf[20 + 1];
3482 char *res = zend_print_u64_to_buf(buf + sizeof(buf) - 1, num);
3483 zend_string *str = zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
3485 return str;
3486 }
3487}
3488
3490{
3491 if ((uint64_t)num <= 9) {
3492 return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
3493 } else {
3494 char buf[20 + 1];
3495 char *res = zend_print_i64_to_buf(buf + sizeof(buf) - 1, num);
3496 zend_string *str = zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
3498 return str;
3499 }
3500}
3501
3503{
3505 /* Model snprintf precision behavior. */
3506 int precision = (int) EG(precision);
3507 zend_gcvt(num, precision ? precision : 1, '.', 'E', buf);
3508 zend_string *str = zend_string_init(buf, strlen(buf), 0);
3510 return str;
3511}
3512
3513ZEND_API uint8_t ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval) /* {{{ */
3514{
3515 return is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), lval, dval, false);
3516}
3517/* }}} */
3518
3519ZEND_API uint8_t ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t length, zend_long *lval,
3520 double *dval, bool allow_errors, int *oflow_info, bool *trailing_data) /* {{{ */
3521{
3522 const char *ptr;
3523 int digits = 0, dp_or_e = 0;
3524 double local_dval = 0.0;
3525 uint8_t type;
3526 zend_ulong tmp_lval = 0;
3527 int neg = 0;
3528
3529 if (!length) {
3530 return 0;
3531 }
3532
3533 if (oflow_info != NULL) {
3534 *oflow_info = 0;
3535 }
3536 if (trailing_data != NULL) {
3537 *trailing_data = false;
3538 }
3539
3540 /* Skip any whitespace
3541 * This is much faster than the isspace() function */
3542 while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
3543 str++;
3544 length--;
3545 }
3546 ptr = str;
3547
3548 if (*ptr == '-') {
3549 neg = 1;
3550 ptr++;
3551 } else if (*ptr == '+') {
3552 ptr++;
3553 }
3554
3555 if (ZEND_IS_DIGIT(*ptr)) {
3556 /* Skip any leading 0s */
3557 while (*ptr == '0') {
3558 ptr++;
3559 }
3560
3561 /* Count the number of digits. If a decimal point/exponent is found,
3562 * it's a double. Otherwise, if there's a dval or no need to check for
3563 * a full match, stop when there are too many digits for a long */
3564 for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors)); digits++, ptr++) {
3565check_digits:
3566 if (ZEND_IS_DIGIT(*ptr)) {
3567 tmp_lval = tmp_lval * 10 + (*ptr) - '0';
3568 continue;
3569 } else if (*ptr == '.' && dp_or_e < 1) {
3570 goto process_double;
3571 } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
3572 const char *e = ptr + 1;
3573
3574 if (*e == '-' || *e == '+') {
3575 ptr = e++;
3576 }
3577 if (ZEND_IS_DIGIT(*e)) {
3578 goto process_double;
3579 }
3580 }
3581
3582 break;
3583 }
3584
3585 if (digits >= MAX_LENGTH_OF_LONG) {
3586 if (oflow_info != NULL) {
3587 *oflow_info = *str == '-' ? -1 : 1;
3588 }
3589 dp_or_e = -1;
3590 goto process_double;
3591 }
3592 } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
3593process_double:
3594 type = IS_DOUBLE;
3595
3596 /* If there's a dval, do the conversion; else continue checking
3597 * the digits if we need to check for a full match */
3598 if (dval) {
3599 local_dval = zend_strtod(str, &ptr);
3600 } else if (!allow_errors && dp_or_e != -1) {
3601 dp_or_e = (*ptr++ == '.') ? 1 : 2;
3602 goto check_digits;
3603 }
3604 } else {
3605 return 0;
3606 }
3607
3608 if (ptr != str + length) {
3609 const char *endptr = ptr;
3610 while (*endptr == ' ' || *endptr == '\t' || *endptr == '\n' || *endptr == '\r' || *endptr == '\v' || *endptr == '\f') {
3611 endptr++;
3612 length--;
3613 }
3614 if (ptr != str + length) {
3615 if (!allow_errors) {
3616 return 0;
3617 }
3618 if (trailing_data != NULL) {
3619 *trailing_data = true;
3620 }
3621 }
3622 }
3623
3624 if (type == IS_LONG) {
3625 if (digits == MAX_LENGTH_OF_LONG - 1) {
3626 int cmp = strcmp(&ptr[-digits], long_min_digits);
3627
3628 if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
3629 if (dval) {
3630 *dval = zend_strtod(str, NULL);
3631 }
3632 if (oflow_info != NULL) {
3633 *oflow_info = *str == '-' ? -1 : 1;
3634 }
3635
3636 return IS_DOUBLE;
3637 }
3638 }
3639
3640 if (lval) {
3641 if (neg) {
3642 tmp_lval = -tmp_lval;
3643 }
3644 *lval = (zend_long) tmp_lval;
3645 }
3646
3647 return IS_LONG;
3648 } else {
3649 if (dval) {
3650 *dval = local_dval;
3651 }
3652
3653 return IS_DOUBLE;
3654 }
3655}
3656/* }}} */
3657
3658/*
3659 * String matching - Sunday algorithm
3660 * http://www.iti.fh-flensburg.de/lang/algorithmen/pattern/sundayen.htm
3661 */
3662static zend_always_inline void zend_memnstr_ex_pre(unsigned int td[], const char *needle, size_t needle_len, int reverse) /* {{{ */ {
3663 int i;
3664
3665 for (i = 0; i < 256; i++) {
3666 td[i] = needle_len + 1;
3667 }
3668
3669 if (reverse) {
3670 for (i = needle_len - 1; i >= 0; i--) {
3671 td[(unsigned char)needle[i]] = i + 1;
3672 }
3673 } else {
3674 size_t i;
3675
3676 for (i = 0; i < needle_len; i++) {
3677 td[(unsigned char)needle[i]] = (int)needle_len - i;
3678 }
3679 }
3680}
3681/* }}} */
3682
3683ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
3684{
3685 unsigned int td[256];
3686 size_t i;
3687 const char *p;
3688
3689 if (needle_len == 0 || (end - haystack) < needle_len) {
3690 return NULL;
3691 }
3692
3693 zend_memnstr_ex_pre(td, needle, needle_len, 0);
3694
3695 p = haystack;
3696 end -= needle_len;
3697
3698 while (p <= end) {
3699 for (i = 0; i < needle_len; i++) {
3700 if (needle[i] != p[i]) {
3701 break;
3702 }
3703 }
3704 if (i == needle_len) {
3705 return p;
3706 }
3707 if (UNEXPECTED(p == end)) {
3708 return NULL;
3709 }
3710 p += td[(unsigned char)(p[needle_len])];
3711 }
3712
3713 return NULL;
3714}
3715/* }}} */
3716
3717ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
3718{
3719 unsigned int td[256];
3720 size_t i;
3721 const char *p;
3722
3723 if (needle_len == 0 || (end - haystack) < needle_len) {
3724 return NULL;
3725 }
3726
3727 zend_memnstr_ex_pre(td, needle, needle_len, 1);
3728
3729 p = end;
3730 p -= needle_len;
3731
3732 while (p >= haystack) {
3733 for (i = 0; i < needle_len; i++) {
3734 if (needle[i] != p[i]) {
3735 break;
3736 }
3737 }
3738
3739 if (i == needle_len) {
3740 return (const char *)p;
3741 }
3742
3743 if (UNEXPECTED(p == haystack)) {
3744 return NULL;
3745 }
3746
3747 p -= td[(unsigned char)(p[-1])];
3748 }
3749
3750 return NULL;
3751}
3752/* }}} */
3753
3754#if SIZEOF_ZEND_LONG == 4
3756{
3757 double two_pow_32 = pow(2., 32.),
3758 dmod;
3759
3760 dmod = fmod(d, two_pow_32);
3761 if (dmod < 0) {
3762 /* we're going to make this number positive; call ceil()
3763 * to simulate rounding towards 0 of the negative number */
3764 dmod = ceil(dmod) + two_pow_32;
3765 }
3766 return (zend_long)(zend_ulong)dmod;
3767}
3768#else
3770{
3771 double two_pow_64 = pow(2., 64.),
3772 dmod;
3773
3774 dmod = fmod(d, two_pow_64);
3775 if (dmod < 0) {
3776 /* no need to call ceil; original double must have had no
3777 * fractional part, hence dmod does not have one either */
3778 dmod += two_pow_64;
3779 }
3780 return (zend_long)(zend_ulong)dmod;
3781}
3782/* }}} */
3783#endif
size_t len
Definition apprentice.c:174
bool exception
Definition assert.c:30
nl_langinfo(int $item)
const LC_CTYPE
setlocale(int $category, $locales,... $rest)
strcoll(string $string1, string $string2)
copy(string $from, string $to, $context=null)
fmod(float $num1, float $num2)
pow(mixed $num, mixed $exponent)
ceil(int|float $num)
strchr(string $haystack, string $needle, bool $before_needle=false)
const CODESET
char s[4]
Definition cdf.c:77
zend_ffi_type * type
Definition ffi.c:3812
zend_long ch
Definition ffi.c:4580
zend_string * res
Definition ffi.c:4692
void * ptr
Definition ffi.c:3814
memcpy(ptr1, ptr2, size)
HashTable * ht
Definition ffi.c:4838
ffi persistent
Definition ffi.c:3633
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
unsigned const char * end
Definition php_ffi.h:51
unsigned const char * pos
Definition php_ffi.h:52
zend_stack handlers
Definition php_output.h:139
const char * endptr
Definition session.c:1021
p
Definition session.c:1105
uint32_t num_interfaces
Definition zend.h:205
uint32_t ce_flags
Definition zend.h:156
zend_class_entry ** interfaces
Definition zend.h:212
zend_class_entry * parent
Definition zend.h:152
HashTable * properties
Definition zend_types.h:562
char val[1]
Definition zend_types.h:377
ZEND_API ZEND_COLD void zend_error_unchecked(int type, const char *format,...)
Definition zend.c:1670
ZEND_API zend_string * zend_strpprintf(size_t max_len, const char *format,...)
Definition zend.c:353
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
Definition zend.c:1703
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API zend_class_entry * zend_standard_class_def
Definition zend.c:83
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API const char * zend_zval_type_name(const zval *arg)
Definition zend_API.c:167
ZEND_API void object_init(zval *arg)
Definition zend_API.c:1922
#define ZVAL_CHAR(z, c)
Definition zend_API.h:978
#define array_init(arg)
Definition zend_API.h:537
#define ZVAL_EMPTY_STRING(z)
Definition zend_API.h:961
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
ZEND_API zend_class_entry * zend_ce_closure
zend_string_release_ex(func->internal_function.function_name, 0)
#define ZEND_ACC_INTERFACE
#define ZEND_ACC_RESOLVED_INTERFACES
#define ZEND_API
#define E_ERROR
Definition zend_errors.h:23
#define E_WARNING
Definition zend_errors.h:24
#define E_RECOVERABLE_ERROR
Definition zend_errors.h:36
#define E_DEPRECATED
Definition zend_errors.h:37
ZEND_API zend_class_entry * zend_ce_arithmetic_error
ZEND_API zend_class_entry * zend_ce_division_by_zero_error
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
#define CG(v)
#define EG(v)
ZEND_API HashTable *ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, bool always_duplicate)
Definition zend_hash.c:3387
ZEND_API HashTable *ZEND_FASTCALL zend_symtable_to_proptable(HashTable *ht)
Definition zend_hash.c:3334
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData)
Definition zend_hash.c:1214
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered)
Definition zend_hash.c:3197
ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, bool overwrite)
Definition zend_hash.c:2547
ZEND_API zval *ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:1007
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
#define zend_new_array(size)
Definition zend_hash.h:338
int32_t zend_long
Definition zend_long.h:42
#define MAX_LENGTH_OF_LONG
Definition zend_long.h:109
#define ZEND_LONG_MIN
Definition zend_long.h:46
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_ULONG_MAX
Definition zend_long.h:47
#define ZEND_STRTOL(s0, s1, base)
Definition zend_long.h:85
#define ZEND_LONG_FMT
Definition zend_long.h:87
#define SIZEOF_ZEND_LONG
Definition zend_long.h:50
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval)
ZEND_API HashTable * zend_get_properties_for(zval *obj, zend_prop_purpose purpose)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API HashTable * zend_std_build_object_properties_array(zend_object *zobj)
#define zend_release_properties(ht)
@ ZEND_PROP_PURPOSE_ARRAY_CAST
#define ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(object)
ZEND_API zend_object *ZEND_FASTCALL zend_objects_new(zend_class_entry *ce)
#define OBJ_RELEASE(obj)
ZEND_API const unsigned char zend_tolower_map[256]
#define UPPER_CASE
#define LOWER_CASE
#define convert_object_to_type(op, dst, ctype)
#define zend_tolower(c)
#define TYPES_NOT_HANDLED
ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2)
#define NUMERIC
ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2)
#define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode)
ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1)
ZEND_API zend_result ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
ZEND_API bool ZEND_FASTCALL zend_is_identical(const zval *op1, const zval *op2)
ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2)
ZEND_API const unsigned char zend_toupper_map[256]
#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, opcode, sigil)
ZEND_API zend_result ZEND_FASTCALL boolean_not_function(zval *result, zval *op1)
ZEND_API zend_result ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2)
ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, bool case_insensitive)
ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2)
ZEND_API zend_string *ZEND_FASTCALL zend_long_to_str(zend_long num)
ZEND_API const char *ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end)
ZEND_API char *ZEND_FASTCALL zend_str_toupper_dup_ex(const char *source, size_t length)
ZEND_API bool ZEND_FASTCALL zend_object_is_true(const zval *op)
ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len)
ZEND_API zend_result ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2)
#define ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode)
ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length)
ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op)
ZEND_API zend_result ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, zval *op2)
#define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode)
ZEND_API void ZEND_COLD zend_incompatible_double_to_long_error(double d)
ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op)
ZEND_API void ZEND_FASTCALL zend_str_toupper(char *str, size_t length)
ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2)
ZEND_API void ZEND_COLD zend_incompatible_string_to_long_error(const zend_string *s)
ZEND_API bool zend_string_only_has_ascii_alphanumeric(const zend_string *str)
ZEND_API zend_result ZEND_FASTCALL bitwise_not_function(zval *result, zval *op1)
ZEND_API zend_result ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2)
#define TYPE_PAIR(t1, t2)
ZEND_API zend_result ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2)
ZEND_API void ZEND_FASTCALL convert_to_array(zval *op)
ZEND_API zend_result ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length)
ZEND_API zend_result ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2)
ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2)
ZEND_API zend_string *ZEND_FASTCALL zval_try_get_string_func(zval *op)
ZEND_API bool ZEND_FASTCALL _try_convert_to_string(zval *op)
ZEND_API bool ZEND_FASTCALL instanceof_function_slow(const zend_class_entry *instance_ce, const zend_class_entry *ce)
ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2)
ZEND_API zend_string *ZEND_FASTCALL zend_u64_to_str(uint64_t num)
ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len)
ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3)
ZEND_API zend_result ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length)
ZEND_API zend_string *ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, bool persistent)
ZEND_API zend_string *ZEND_FASTCALL zend_i64_to_str(int64_t num)
ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_strict)
ZEND_API zend_result ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2)
ZEND_API const char *ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end)
ZEND_API uint8_t ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, bool allow_errors, int *oflow_info, bool *trailing_data)
ZEND_API void ZEND_FASTCALL convert_to_double(zval *op)
ZEND_API bool ZEND_FASTCALL zendi_smart_streq(zend_string *s1, zend_string *s2)
ZEND_API zend_result ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
#define ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode)
ZEND_API void ZEND_FASTCALL convert_to_object(zval *op)
ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length)
ZEND_API zend_result ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2)
ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2)
ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length)
ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2)
ZEND_API uint8_t ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval)
ZEND_API char *ZEND_FASTCALL zend_str_toupper_copy(char *dest, const char *source, size_t length)
ZEND_API void zend_reset_lc_ctype_locale(void)
ZEND_API zend_result ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2)
ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2)
ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2)
ZEND_API zend_long ZEND_FASTCALL zval_try_get_long(const zval *op, bool *failed)
ZEND_API zend_result ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2)
ZEND_API void zend_update_current_locale(void)
ZEND_API zend_result ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2)
ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length)
ZEND_API double ZEND_FASTCALL zval_get_double_func(const zval *op)
ZEND_API zend_string *ZEND_FASTCALL zval_get_string_func(zval *op)
ZEND_API void ZEND_FASTCALL convert_to_null(zval *op)
ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op)
ZEND_API zend_result ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2)
ZEND_API bool ZEND_FASTCALL zend_class_implements_interface(const zend_class_entry *class_ce, const zend_class_entry *interface_ce)
ZEND_API zend_string *ZEND_FASTCALL zend_ulong_to_str(zend_ulong num)
ZEND_API zend_result ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_string *ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, bool persistent)
ZEND_API void ZEND_FASTCALL convert_to_long(zval *op)
ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2)
ZEND_API zend_string *ZEND_FASTCALL zend_double_to_str(double num)
#define DIV_BY_ZERO
ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length)
ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2)
ZEND_API char *ZEND_FASTCALL zend_str_toupper_dup(const char *source, size_t length)
#define zend_toupper_ascii(c)
#define zval_is_true(op)
#define zend_tolower_ascii(c)
#define ZEND_IS_DIGIT(c)
int last
#define ZEND_NORMALIZE_BOOL(n)
#define zend_finite(a)
#define zend_never_inline
#define MIN(a, b)
#define ZEND_FALLTHROUGH
#define EXPECTED(condition)
#define ZEND_THREEWAY_COMPARE(a, b)
#define zend_always_inline
#define ZEND_FASTCALL
#define ZEND_ASSERT(c)
#define ZEND_UNREACHABLE()
#define zend_isnan(a)
#define ZEND_COLD
#define EMPTY_SWITCH_DEFAULT_CASE()
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(s1, s2)
Definition zend_string.h:94
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_MAX_LEN
#define ZSTR_KNOWN(idx)
#define ZSTR_EMPTY_ALLOC()
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define ZSTR_CHAR(c)
#define d1
#define dval(x)
ZEND_API double zend_strtod(const char *s00, const char **se)
ZEND_API char * zend_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf)
#define ZEND_DOUBLE_MAX_LENGTH
Definition zend_strtod.h:48
#define Z_OBJ_HANDLER_P(zv_p, hf)
Definition zend_types.h:996
int(* compare_func_t)(const void *, const void *)
Definition zend_types.h:104
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_STR(z, s)
#define ZVAL_FALSE(z)
#define Z_ISREF_P(zval_p)
Definition zend_types.h:954
#define ZVAL_UNDEF(z)
#define Z_DVAL(zval)
Definition zend_types.h:968
#define Z_REFVAL_P(zval_p)
#define IS_FALSE
Definition zend_types.h:602
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define IS_UNDEF
Definition zend_types.h:600
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_TRUE(z)
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
#define Z_REFCOUNTED_P(zval_p)
Definition zend_types.h:921
#define ZVAL_STR_COPY(z, s)
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_RESOURCE
Definition zend_types.h:609
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define Z_OBJ_HT_P(zval_p)
Definition zend_types.h:993
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_TYPE_INFO_P(zval_p)
Definition zend_types.h:669
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define IS_STR_VALID_UTF8
Definition zend_types.h:820
#define Z_STR(zval)
Definition zend_types.h:971
#define GC_DELREF(p)
Definition zend_types.h:710
#define GC_FLAGS(p)
Definition zend_types.h:756
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define IS_STRING_EX
Definition zend_types.h:807
#define IS_NULL
Definition zend_types.h:601
#define Z_OBJCE_P(zval_p)
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_ARR(z, a)
#define IS_REFERENCE
Definition zend_types.h:610
#define Z_RES_HANDLE_P(zval_p)
#define ZVAL_NEW_STR(z, s)
#define _IS_BOOL
Definition zend_types.h:629
#define Z_TYPE_INFO(zval)
Definition zend_types.h:668
#define Z_OBJPROP_P(zval_p)
#define ZVAL_DOUBLE(z, d)
#define Z_REFCOUNT_P(pz)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define IS_ARRAY_IMMUTABLE
Definition zend_types.h:823
unsigned char zend_uchar
Definition zend_types.h:57
#define _IS_NUMBER
Definition zend_types.h:630
#define Z_RES_P(zval_p)
#define SEPARATE_ARRAY(zv)
#define GC_IS_RECURSIVE(p)
Definition zend_types.h:865
#define Z_TYPE(zval)
Definition zend_types.h:659
#define ZVAL_INTERNED_STR(z, s)
#define Z_DVAL_P(zval_p)
Definition zend_types.h:969
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_COPY_VALUE(z, v)
#define ZVAL_BOOL(z, b)
#define Z_LVAL(zval)
Definition zend_types.h:965
#define GC_ADD_FLAGS(p, flags)
Definition zend_types.h:759
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
ZEND_API void zval_add_ref(zval *p)
zval retval
double d2
zend_string * name
bool result
op2
op1
zval * ret
zend_object * zobj
#define ZEND_SL
#define ZEND_BOOL_NOT
#define ZEND_BOOL_XOR
#define ZEND_POW
#define ZEND_SUB
#define ZEND_BW_XOR
#define ZEND_DIV
#define ZEND_CONCAT
#define ZEND_BW_OR
#define ZEND_MUL
#define ZEND_BW_NOT
#define ZEND_BW_AND
#define ZEND_SR
#define ZEND_MOD
#define ZEND_ADD