PageRenderTime 64ms CodeModel.GetById 7ms 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

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Zeev Suraski <zeev@php.net> |
  17. | Dmitry Stogov <dmitry@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #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 (EXPECTE

Large files files are truncated, but you can click here to view the full file