Coverage Report

Created: 2025-07-23 06:33

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