PageRenderTime 63ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/Zend/zend_operators.c

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