Coverage Report

Created: 2025-06-13 06:43

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