PageRenderTime 64ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/Zend/zend_compile.c

http://github.com/php/php-src
C | 9277 lines | 8026 code | 924 blank | 327 comment | 1618 complexity | a142d13b4798cf62d9d1e736f262e637 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. | Nikita Popov <nikic@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #include <zend_language_parser.h>
  21. #include "zend.h"
  22. #include "zend_compile.h"
  23. #include "zend_constants.h"
  24. #include "zend_llist.h"
  25. #include "zend_API.h"
  26. #include "zend_exceptions.h"
  27. #include "zend_interfaces.h"
  28. #include "zend_virtual_cwd.h"
  29. #include "zend_multibyte.h"
  30. #include "zend_language_scanner.h"
  31. #include "zend_inheritance.h"
  32. #include "zend_vm.h"
  33. #define SET_NODE(target, src) do { \
  34. target ## _type = (src)->op_type; \
  35. if ((src)->op_type == IS_CONST) { \
  36. target.constant = zend_add_literal(&(src)->u.constant); \
  37. } else { \
  38. target = (src)->u.op; \
  39. } \
  40. } while (0)
  41. #define GET_NODE(target, src) do { \
  42. (target)->op_type = src ## _type; \
  43. if ((target)->op_type == IS_CONST) { \
  44. ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
  45. } else { \
  46. (target)->u.op = src; \
  47. } \
  48. } while (0)
  49. #define FC(member) (CG(file_context).member)
  50. typedef struct _zend_loop_var {
  51. zend_uchar opcode;
  52. zend_uchar var_type;
  53. uint32_t var_num;
  54. uint32_t try_catch_offset;
  55. } zend_loop_var;
  56. static inline uint32_t zend_alloc_cache_slots(unsigned count) {
  57. if (count == 0) {
  58. return (uint32_t) -1;
  59. }
  60. zend_op_array *op_array = CG(active_op_array);
  61. uint32_t ret = op_array->cache_size;
  62. op_array->cache_size += count * sizeof(void*);
  63. return ret;
  64. }
  65. static inline uint32_t zend_alloc_cache_slot(void) {
  66. return zend_alloc_cache_slots(1);
  67. }
  68. ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
  69. ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, const char *filename);
  70. #ifndef ZTS
  71. ZEND_API zend_compiler_globals compiler_globals;
  72. ZEND_API zend_executor_globals executor_globals;
  73. #endif
  74. static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2);
  75. static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast);
  76. static void init_op(zend_op *op)
  77. {
  78. MAKE_NOP(op);
  79. op->extended_value = 0;
  80. op->lineno = CG(zend_lineno);
  81. }
  82. static zend_always_inline uint32_t get_next_op_number(void)
  83. {
  84. return CG(active_op_array)->last;
  85. }
  86. static zend_op *get_next_op(void)
  87. {
  88. zend_op_array *op_array = CG(active_op_array);
  89. uint32_t next_op_num = op_array->last++;
  90. zend_op *next_op;
  91. if (UNEXPECTED(next_op_num >= CG(context).opcodes_size)) {
  92. CG(context).opcodes_size *= 4;
  93. op_array->opcodes = erealloc(op_array->opcodes, CG(context).opcodes_size * sizeof(zend_op));
  94. }
  95. next_op = &(op_array->opcodes[next_op_num]);
  96. init_op(next_op);
  97. return next_op;
  98. }
  99. static zend_brk_cont_element *get_next_brk_cont_element(void)
  100. {
  101. CG(context).last_brk_cont++;
  102. CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
  103. return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
  104. }
  105. static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
  106. {
  107. zend_property_info *property_info = Z_PTR_P(zv);
  108. zend_string_release(property_info->name);
  109. zend_type_release(property_info->type, /* persistent */ 1);
  110. free(property_info);
  111. }
  112. /* }}} */
  113. static zend_string *zend_build_runtime_definition_key(zend_string *name, uint32_t start_lineno) /* {{{ */
  114. {
  115. zend_string *filename = CG(active_op_array)->filename;
  116. zend_string *result = zend_strpprintf(0, "%c%s%s:%" PRIu32 "$%" PRIx32,
  117. '\0', ZSTR_VAL(name), ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
  118. return zend_new_interned_string(result);
  119. }
  120. /* }}} */
  121. static zend_bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
  122. {
  123. const char *ns_separator = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  124. if (ns_separator != NULL) {
  125. *result = ns_separator + 1;
  126. *result_len = ZSTR_VAL(name) + ZSTR_LEN(name) - *result;
  127. return 1;
  128. }
  129. return 0;
  130. }
  131. /* }}} */
  132. struct reserved_class_name {
  133. const char *name;
  134. size_t len;
  135. };
  136. static const struct reserved_class_name reserved_class_names[] = {
  137. {ZEND_STRL("bool")},
  138. {ZEND_STRL("false")},
  139. {ZEND_STRL("float")},
  140. {ZEND_STRL("int")},
  141. {ZEND_STRL("null")},
  142. {ZEND_STRL("parent")},
  143. {ZEND_STRL("self")},
  144. {ZEND_STRL("static")},
  145. {ZEND_STRL("string")},
  146. {ZEND_STRL("true")},
  147. {ZEND_STRL("void")},
  148. {ZEND_STRL("iterable")},
  149. {ZEND_STRL("object")},
  150. {NULL, 0}
  151. };
  152. static zend_bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
  153. {
  154. const struct reserved_class_name *reserved = reserved_class_names;
  155. const char *uqname = ZSTR_VAL(name);
  156. size_t uqname_len = ZSTR_LEN(name);
  157. zend_get_unqualified_name(name, &uqname, &uqname_len);
  158. for (; reserved->name; ++reserved) {
  159. if (uqname_len == reserved->len
  160. && zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0
  161. ) {
  162. return 1;
  163. }
  164. }
  165. return 0;
  166. }
  167. /* }}} */
  168. void zend_assert_valid_class_name(const zend_string *name) /* {{{ */
  169. {
  170. if (zend_is_reserved_class_name(name)) {
  171. zend_error_noreturn(E_COMPILE_ERROR,
  172. "Cannot use '%s' as class name as it is reserved", ZSTR_VAL(name));
  173. }
  174. }
  175. /* }}} */
  176. typedef struct _builtin_type_info {
  177. const char* name;
  178. const size_t name_len;
  179. const zend_uchar type;
  180. } builtin_type_info;
  181. static const builtin_type_info builtin_types[] = {
  182. {ZEND_STRL("null"), IS_NULL},
  183. {ZEND_STRL("false"), IS_FALSE},
  184. {ZEND_STRL("int"), IS_LONG},
  185. {ZEND_STRL("float"), IS_DOUBLE},
  186. {ZEND_STRL("string"), IS_STRING},
  187. {ZEND_STRL("bool"), _IS_BOOL},
  188. {ZEND_STRL("void"), IS_VOID},
  189. {ZEND_STRL("iterable"), IS_ITERABLE},
  190. {ZEND_STRL("object"), IS_OBJECT},
  191. {NULL, 0, IS_UNDEF}
  192. };
  193. typedef struct {
  194. const char *name;
  195. size_t name_len;
  196. const char *correct_name;
  197. } confusable_type_info;
  198. static const confusable_type_info confusable_types[] = {
  199. {ZEND_STRL("boolean"), "bool"},
  200. {ZEND_STRL("integer"), "int"},
  201. {ZEND_STRL("double"), "float"},
  202. {ZEND_STRL("resource"), NULL},
  203. {NULL, 0, NULL},
  204. };
  205. static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend_string *name) /* {{{ */
  206. {
  207. const builtin_type_info *info = &builtin_types[0];
  208. for (; info->name; ++info) {
  209. if (ZSTR_LEN(name) == info->name_len
  210. && zend_binary_strcasecmp(ZSTR_VAL(name), ZSTR_LEN(name), info->name, info->name_len) == 0
  211. ) {
  212. return info->type;
  213. }
  214. }
  215. return 0;
  216. }
  217. /* }}} */
  218. static zend_always_inline zend_bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */
  219. {
  220. const confusable_type_info *info = confusable_types;
  221. /* Intentionally using case-sensitive comparison here, because "integer" is likely intended
  222. * as a scalar type, while "Integer" is likely a class type. */
  223. for (; info->name; ++info) {
  224. if (ZSTR_LEN(name) == info->name_len
  225. && memcmp(ZSTR_VAL(name), info->name, info->name_len) == 0
  226. ) {
  227. *correct_name = info->correct_name;
  228. return 1;
  229. }
  230. }
  231. return 0;
  232. }
  233. /* }}} */
  234. static zend_bool zend_is_not_imported(zend_string *name) {
  235. /* Assuming "name" is unqualified here. */
  236. return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL;
  237. }
  238. void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
  239. {
  240. *prev_context = CG(context);
  241. CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
  242. CG(context).vars_size = 0;
  243. CG(context).literals_size = 0;
  244. CG(context).fast_call_var = -1;
  245. CG(context).try_catch_offset = -1;
  246. CG(context).current_brk_cont = -1;
  247. CG(context).last_brk_cont = 0;
  248. CG(context).brk_cont_array = NULL;
  249. CG(context).labels = NULL;
  250. }
  251. /* }}} */
  252. void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
  253. {
  254. if (CG(context).brk_cont_array) {
  255. efree(CG(context).brk_cont_array);
  256. CG(context).brk_cont_array = NULL;
  257. }
  258. if (CG(context).labels) {
  259. zend_hash_destroy(CG(context).labels);
  260. FREE_HASHTABLE(CG(context).labels);
  261. CG(context).labels = NULL;
  262. }
  263. CG(context) = *prev_context;
  264. }
  265. /* }}} */
  266. static void zend_reset_import_tables(void) /* {{{ */
  267. {
  268. if (FC(imports)) {
  269. zend_hash_destroy(FC(imports));
  270. efree(FC(imports));
  271. FC(imports) = NULL;
  272. }
  273. if (FC(imports_function)) {
  274. zend_hash_destroy(FC(imports_function));
  275. efree(FC(imports_function));
  276. FC(imports_function) = NULL;
  277. }
  278. if (FC(imports_const)) {
  279. zend_hash_destroy(FC(imports_const));
  280. efree(FC(imports_const));
  281. FC(imports_const) = NULL;
  282. }
  283. }
  284. /* }}} */
  285. static void zend_end_namespace(void) /* {{{ */ {
  286. FC(in_namespace) = 0;
  287. zend_reset_import_tables();
  288. if (FC(current_namespace)) {
  289. zend_string_release_ex(FC(current_namespace), 0);
  290. FC(current_namespace) = NULL;
  291. }
  292. }
  293. /* }}} */
  294. void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
  295. {
  296. *prev_context = CG(file_context);
  297. FC(imports) = NULL;
  298. FC(imports_function) = NULL;
  299. FC(imports_const) = NULL;
  300. FC(current_namespace) = NULL;
  301. FC(in_namespace) = 0;
  302. FC(has_bracketed_namespaces) = 0;
  303. FC(declarables).ticks = 0;
  304. zend_hash_init(&FC(seen_symbols), 8, NULL, NULL, 0);
  305. }
  306. /* }}} */
  307. void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
  308. {
  309. zend_end_namespace();
  310. zend_hash_destroy(&FC(seen_symbols));
  311. CG(file_context) = *prev_context;
  312. }
  313. /* }}} */
  314. void zend_init_compiler_data_structures(void) /* {{{ */
  315. {
  316. zend_stack_init(&CG(loop_var_stack), sizeof(zend_loop_var));
  317. zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
  318. CG(active_class_entry) = NULL;
  319. CG(in_compilation) = 0;
  320. CG(skip_shebang) = 0;
  321. CG(encoding_declared) = 0;
  322. CG(memoized_exprs) = NULL;
  323. CG(memoize_mode) = 0;
  324. }
  325. /* }}} */
  326. static void zend_register_seen_symbol(zend_string *name, uint32_t kind) {
  327. zval *zv = zend_hash_find(&FC(seen_symbols), name);
  328. if (zv) {
  329. Z_LVAL_P(zv) |= kind;
  330. } else {
  331. zval tmp;
  332. ZVAL_LONG(&tmp, kind);
  333. zend_hash_add_new(&FC(seen_symbols), name, &tmp);
  334. }
  335. }
  336. static zend_bool zend_have_seen_symbol(zend_string *name, uint32_t kind) {
  337. zval *zv = zend_hash_find(&FC(seen_symbols), name);
  338. return zv && (Z_LVAL_P(zv) & kind) != 0;
  339. }
  340. ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
  341. {
  342. zend_file_handle_dtor(fh);
  343. }
  344. /* }}} */
  345. void init_compiler(void) /* {{{ */
  346. {
  347. CG(arena) = zend_arena_create(64 * 1024);
  348. CG(active_op_array) = NULL;
  349. memset(&CG(context), 0, sizeof(CG(context)));
  350. zend_init_compiler_data_structures();
  351. zend_init_rsrc_list();
  352. zend_hash_init(&CG(filenames_table), 8, NULL, ZVAL_PTR_DTOR, 0);
  353. zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
  354. CG(unclean_shutdown) = 0;
  355. CG(delayed_variance_obligations) = NULL;
  356. CG(delayed_autoloads) = NULL;
  357. }
  358. /* }}} */
  359. void shutdown_compiler(void) /* {{{ */
  360. {
  361. zend_stack_destroy(&CG(loop_var_stack));
  362. zend_stack_destroy(&CG(delayed_oplines_stack));
  363. zend_hash_destroy(&CG(filenames_table));
  364. zend_arena_destroy(CG(arena));
  365. if (CG(delayed_variance_obligations)) {
  366. zend_hash_destroy(CG(delayed_variance_obligations));
  367. FREE_HASHTABLE(CG(delayed_variance_obligations));
  368. CG(delayed_variance_obligations) = NULL;
  369. }
  370. if (CG(delayed_autoloads)) {
  371. zend_hash_destroy(CG(delayed_autoloads));
  372. FREE_HASHTABLE(CG(delayed_autoloads));
  373. CG(delayed_autoloads) = NULL;
  374. }
  375. }
  376. /* }}} */
  377. ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename) /* {{{ */
  378. {
  379. zval *p, rv;
  380. if ((p = zend_hash_find(&CG(filenames_table), new_compiled_filename))) {
  381. ZEND_ASSERT(Z_TYPE_P(p) == IS_STRING);
  382. CG(compiled_filename) = Z_STR_P(p);
  383. return Z_STR_P(p);
  384. }
  385. new_compiled_filename = zend_new_interned_string(zend_string_copy(new_compiled_filename));
  386. ZVAL_STR(&rv, new_compiled_filename);
  387. zend_hash_add_new(&CG(filenames_table), new_compiled_filename, &rv);
  388. CG(compiled_filename) = new_compiled_filename;
  389. return new_compiled_filename;
  390. }
  391. /* }}} */
  392. ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename) /* {{{ */
  393. {
  394. CG(compiled_filename) = original_compiled_filename;
  395. }
  396. /* }}} */
  397. ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */
  398. {
  399. return CG(compiled_filename);
  400. }
  401. /* }}} */
  402. ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
  403. {
  404. return CG(zend_lineno);
  405. }
  406. /* }}} */
  407. ZEND_API zend_bool zend_is_compiling(void) /* {{{ */
  408. {
  409. return CG(in_compilation);
  410. }
  411. /* }}} */
  412. static zend_always_inline uint32_t get_temporary_variable(void) /* {{{ */
  413. {
  414. return (uint32_t)CG(active_op_array)->T++;
  415. }
  416. /* }}} */
  417. static int lookup_cv(zend_string *name) /* {{{ */{
  418. zend_op_array *op_array = CG(active_op_array);
  419. int i = 0;
  420. zend_ulong hash_value = zend_string_hash_val(name);
  421. while (i < op_array->last_var) {
  422. if (ZSTR_H(op_array->vars[i]) == hash_value
  423. && zend_string_equals(op_array->vars[i], name)) {
  424. return EX_NUM_TO_VAR(i);
  425. }
  426. i++;
  427. }
  428. i = op_array->last_var;
  429. op_array->last_var++;
  430. if (op_array->last_var > CG(context).vars_size) {
  431. CG(context).vars_size += 16; /* FIXME */
  432. op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*));
  433. }
  434. op_array->vars[i] = zend_string_copy(name);
  435. return EX_NUM_TO_VAR(i);
  436. }
  437. /* }}} */
  438. static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */
  439. {
  440. ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
  441. Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
  442. if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
  443. Z_TYPE_FLAGS_P(zv) = 0;
  444. }
  445. return Z_STR_P(zv);
  446. }
  447. /* Common part of zend_add_literal and zend_append_individual_literal */
  448. static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
  449. {
  450. zval *lit = CT_CONSTANT_EX(op_array, literal_position);
  451. if (Z_TYPE_P(zv) == IS_STRING) {
  452. zval_make_interned_string(zv);
  453. }
  454. ZVAL_COPY_VALUE(lit, zv);
  455. Z_EXTRA_P(lit) = 0;
  456. }
  457. /* }}} */
  458. /* Is used while compiling a function, using the context to keep track
  459. of an approximate size to avoid to relocate to often.
  460. Literals are truncated to actual size in the second compiler pass (pass_two()). */
  461. static int zend_add_literal(zval *zv) /* {{{ */
  462. {
  463. zend_op_array *op_array = CG(active_op_array);
  464. int i = op_array->last_literal;
  465. op_array->last_literal++;
  466. if (i >= CG(context).literals_size) {
  467. while (i >= CG(context).literals_size) {
  468. CG(context).literals_size += 16; /* FIXME */
  469. }
  470. op_array->literals = (zval*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zval));
  471. }
  472. zend_insert_literal(op_array, zv, i);
  473. return i;
  474. }
  475. /* }}} */
  476. static inline int zend_add_literal_string(zend_string **str) /* {{{ */
  477. {
  478. int ret;
  479. zval zv;
  480. ZVAL_STR(&zv, *str);
  481. ret = zend_add_literal(&zv);
  482. *str = Z_STR(zv);
  483. return ret;
  484. }
  485. /* }}} */
  486. static int zend_add_func_name_literal(zend_string *name) /* {{{ */
  487. {
  488. /* Original name */
  489. int ret = zend_add_literal_string(&name);
  490. /* Lowercased name */
  491. zend_string *lc_name = zend_string_tolower(name);
  492. zend_add_literal_string(&lc_name);
  493. return ret;
  494. }
  495. /* }}} */
  496. static int zend_add_ns_func_name_literal(zend_string *name) /* {{{ */
  497. {
  498. const char *unqualified_name;
  499. size_t unqualified_name_len;
  500. /* Original name */
  501. int ret = zend_add_literal_string(&name);
  502. /* Lowercased name */
  503. zend_string *lc_name = zend_string_tolower(name);
  504. zend_add_literal_string(&lc_name);
  505. /* Lowercased unqualfied name */
  506. if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
  507. lc_name = zend_string_alloc(unqualified_name_len, 0);
  508. zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len);
  509. zend_add_literal_string(&lc_name);
  510. }
  511. return ret;
  512. }
  513. /* }}} */
  514. static int zend_add_class_name_literal(zend_string *name) /* {{{ */
  515. {
  516. /* Original name */
  517. int ret = zend_add_literal_string(&name);
  518. /* Lowercased name */
  519. zend_string *lc_name = zend_string_tolower(name);
  520. zend_add_literal_string(&lc_name);
  521. return ret;
  522. }
  523. /* }}} */
  524. static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) /* {{{ */
  525. {
  526. zend_string *tmp_name;
  527. int ret = zend_add_literal_string(&name);
  528. size_t ns_len = 0, after_ns_len = ZSTR_LEN(name);
  529. const char *after_ns = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  530. if (after_ns) {
  531. after_ns += 1;
  532. ns_len = after_ns - ZSTR_VAL(name) - 1;
  533. after_ns_len = ZSTR_LEN(name) - ns_len - 1;
  534. /* lowercased namespace name & original constant name */
  535. tmp_name = zend_string_init(ZSTR_VAL(name), ZSTR_LEN(name), 0);
  536. zend_str_tolower(ZSTR_VAL(tmp_name), ns_len);
  537. zend_add_literal_string(&tmp_name);
  538. if (!unqualified) {
  539. return ret;
  540. }
  541. } else {
  542. after_ns = ZSTR_VAL(name);
  543. }
  544. /* original unqualified constant name */
  545. tmp_name = zend_string_init(after_ns, after_ns_len, 0);
  546. zend_add_literal_string(&tmp_name);
  547. return ret;
  548. }
  549. /* }}} */
  550. #define LITERAL_STR(op, str) do { \
  551. zval _c; \
  552. ZVAL_STR(&_c, str); \
  553. op.constant = zend_add_literal(&_c); \
  554. } while (0)
  555. void zend_stop_lexing(void)
  556. {
  557. if (LANG_SCNG(on_event)) {
  558. LANG_SCNG(on_event)(ON_STOP, END, 0, LANG_SCNG(on_event_context));
  559. }
  560. LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
  561. }
  562. static inline void zend_begin_loop(
  563. zend_uchar free_opcode, const znode *loop_var, zend_bool is_switch) /* {{{ */
  564. {
  565. zend_brk_cont_element *brk_cont_element;
  566. int parent = CG(context).current_brk_cont;
  567. zend_loop_var info = {0};
  568. CG(context).current_brk_cont = CG(context).last_brk_cont;
  569. brk_cont_element = get_next_brk_cont_element();
  570. brk_cont_element->parent = parent;
  571. brk_cont_element->is_switch = is_switch;
  572. if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
  573. uint32_t start = get_next_op_number();
  574. info.opcode = free_opcode;
  575. info.var_type = loop_var->op_type;
  576. info.var_num = loop_var->u.op.var;
  577. brk_cont_element->start = start;
  578. } else {
  579. info.opcode = ZEND_NOP;
  580. /* The start field is used to free temporary variables in case of exceptions.
  581. * We won't try to free something of we don't have loop variable. */
  582. brk_cont_element->start = -1;
  583. }
  584. zend_stack_push(&CG(loop_var_stack), &info);
  585. }
  586. /* }}} */
  587. static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
  588. {
  589. uint32_t end = get_next_op_number();
  590. zend_brk_cont_element *brk_cont_element
  591. = &CG(context).brk_cont_array[CG(context).current_brk_cont];
  592. brk_cont_element->cont = cont_addr;
  593. brk_cont_element->brk = end;
  594. CG(context).current_brk_cont = brk_cont_element->parent;
  595. zend_stack_del_top(&CG(loop_var_stack));
  596. }
  597. /* }}} */
  598. void zend_do_free(znode *op1) /* {{{ */
  599. {
  600. if (op1->op_type == IS_TMP_VAR) {
  601. zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
  602. while (opline->opcode == ZEND_END_SILENCE ||
  603. opline->opcode == ZEND_OP_DATA) {
  604. opline--;
  605. }
  606. if (opline->result_type == IS_TMP_VAR && opline->result.var == op1->u.op.var) {
  607. switch (opline->opcode) {
  608. case ZEND_BOOL:
  609. case ZEND_BOOL_NOT:
  610. /* boolean resuls don't have to be freed */
  611. return;
  612. case ZEND_POST_INC_STATIC_PROP:
  613. case ZEND_POST_DEC_STATIC_PROP:
  614. case ZEND_POST_INC_OBJ:
  615. case ZEND_POST_DEC_OBJ:
  616. case ZEND_POST_INC:
  617. case ZEND_POST_DEC:
  618. /* convert $i++ to ++$i */
  619. opline->opcode -= 2;
  620. opline->result_type = IS_UNUSED;
  621. return;
  622. case ZEND_ASSIGN:
  623. case ZEND_ASSIGN_DIM:
  624. case ZEND_ASSIGN_OBJ:
  625. case ZEND_ASSIGN_STATIC_PROP:
  626. case ZEND_ASSIGN_OP:
  627. case ZEND_ASSIGN_DIM_OP:
  628. case ZEND_ASSIGN_OBJ_OP:
  629. case ZEND_ASSIGN_STATIC_PROP_OP:
  630. case ZEND_PRE_INC_STATIC_PROP:
  631. case ZEND_PRE_DEC_STATIC_PROP:
  632. case ZEND_PRE_INC_OBJ:
  633. case ZEND_PRE_DEC_OBJ:
  634. case ZEND_PRE_INC:
  635. case ZEND_PRE_DEC:
  636. opline->result_type = IS_UNUSED;
  637. return;
  638. }
  639. }
  640. zend_emit_op(NULL, ZEND_FREE, op1, NULL);
  641. } else if (op1->op_type == IS_VAR) {
  642. zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
  643. while (opline->opcode == ZEND_END_SILENCE ||
  644. opline->opcode == ZEND_EXT_FCALL_END ||
  645. opline->opcode == ZEND_OP_DATA) {
  646. opline--;
  647. }
  648. if (opline->result_type == IS_VAR
  649. && opline->result.var == op1->u.op.var) {
  650. if (opline->opcode == ZEND_FETCH_THIS) {
  651. opline->opcode = ZEND_NOP;
  652. opline->result_type = IS_UNUSED;
  653. } else {
  654. opline->result_type = IS_UNUSED;
  655. }
  656. } else {
  657. while (opline >= CG(active_op_array)->opcodes) {
  658. if ((opline->opcode == ZEND_FETCH_LIST_R ||
  659. opline->opcode == ZEND_FETCH_LIST_W) &&
  660. opline->op1_type == IS_VAR &&
  661. opline->op1.var == op1->u.op.var) {
  662. zend_emit_op(NULL, ZEND_FREE, op1, NULL);
  663. return;
  664. }
  665. if (opline->result_type == IS_VAR
  666. && opline->result.var == op1->u.op.var) {
  667. if (opline->opcode == ZEND_NEW) {
  668. zend_emit_op(NULL, ZEND_FREE, op1, NULL);
  669. }
  670. break;
  671. }
  672. opline--;
  673. }
  674. }
  675. } else if (op1->op_type == IS_CONST) {
  676. /* Destroy value without using GC: When opcache moves arrays into SHM it will
  677. * free the zend_array structure, so references to it from outside the op array
  678. * become invalid. GC would cause such a reference in the root buffer. */
  679. zval_ptr_dtor_nogc(&op1->u.constant);
  680. }
  681. }
  682. /* }}} */
  683. uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
  684. {
  685. uint32_t new_flags = flags | new_flag;
  686. if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  687. zend_throw_exception(zend_ce_compile_error,
  688. "Multiple abstract modifiers are not allowed", 0);
  689. return 0;
  690. }
  691. if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
  692. zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
  693. return 0;
  694. }
  695. if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
  696. zend_throw_exception(zend_ce_compile_error,
  697. "Cannot use the final modifier on an abstract class", 0);
  698. return 0;
  699. }
  700. return new_flags;
  701. }
  702. /* }}} */
  703. uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
  704. {
  705. uint32_t new_flags = flags | new_flag;
  706. if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
  707. zend_throw_exception(zend_ce_compile_error,
  708. "Multiple access type modifiers are not allowed", 0);
  709. return 0;
  710. }
  711. if ((flags & ZEND_ACC_ABSTRACT) && (new_flag & ZEND_ACC_ABSTRACT)) {
  712. zend_throw_exception(zend_ce_compile_error, "Multiple abstract modifiers are not allowed", 0);
  713. return 0;
  714. }
  715. if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
  716. zend_throw_exception(zend_ce_compile_error, "Multiple static modifiers are not allowed", 0);
  717. return 0;
  718. }
  719. if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
  720. zend_throw_exception(zend_ce_compile_error, "Multiple final modifiers are not allowed", 0);
  721. return 0;
  722. }
  723. if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
  724. zend_throw_exception(zend_ce_compile_error,
  725. "Cannot use the final modifier on an abstract class member", 0);
  726. return 0;
  727. }
  728. return new_flags;
  729. }
  730. /* }}} */
  731. ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) {
  732. return zend_string_concat3(
  733. ZSTR_VAL(class_name), ZSTR_LEN(class_name),
  734. "::", sizeof("::") - 1,
  735. ZSTR_VAL(member_name), ZSTR_LEN(member_name));
  736. }
  737. zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
  738. return zend_string_concat3(name1, name1_len, "\\", 1, name2, name2_len);
  739. }
  740. zend_string *zend_prefix_with_ns(zend_string *name) {
  741. if (FC(current_namespace)) {
  742. zend_string *ns = FC(current_namespace);
  743. return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
  744. } else {
  745. return zend_string_copy(name);
  746. }
  747. }
  748. zend_string *zend_resolve_non_class_name(
  749. zend_string *name, uint32_t type, zend_bool *is_fully_qualified,
  750. zend_bool case_sensitive, HashTable *current_import_sub
  751. ) {
  752. char *compound;
  753. *is_fully_qualified = 0;
  754. if (ZSTR_VAL(name)[0] == '\\') {
  755. /* Remove \ prefix (only relevant if this is a string rather than a label) */
  756. *is_fully_qualified = 1;
  757. return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
  758. }
  759. if (type == ZEND_NAME_FQ) {
  760. *is_fully_qualified = 1;
  761. return zend_string_copy(name);
  762. }
  763. if (type == ZEND_NAME_RELATIVE) {
  764. *is_fully_qualified = 1;
  765. return zend_prefix_with_ns(name);
  766. }
  767. if (current_import_sub) {
  768. /* If an unqualified name is a function/const alias, replace it. */
  769. zend_string *import_name;
  770. if (case_sensitive) {
  771. import_name = zend_hash_find_ptr(current_import_sub, name);
  772. } else {
  773. import_name = zend_hash_find_ptr_lc(current_import_sub, name);
  774. }
  775. if (import_name) {
  776. *is_fully_qualified = 1;
  777. return zend_string_copy(import_name);
  778. }
  779. }
  780. compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  781. if (compound) {
  782. *is_fully_qualified = 1;
  783. }
  784. if (compound && FC(imports)) {
  785. /* If the first part of a qualified name is an alias, substitute it. */
  786. size_t len = compound - ZSTR_VAL(name);
  787. zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
  788. if (import_name) {
  789. return zend_concat_names(
  790. ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
  791. }
  792. }
  793. return zend_prefix_with_ns(name);
  794. }
  795. /* }}} */
  796. zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */
  797. {
  798. return zend_resolve_non_class_name(
  799. name, type, is_fully_qualified, 0, FC(imports_function));
  800. }
  801. /* }}} */
  802. zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */ {
  803. return zend_resolve_non_class_name(
  804. name, type, is_fully_qualified, 1, FC(imports_const));
  805. }
  806. /* }}} */
  807. zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
  808. {
  809. char *compound;
  810. if (type == ZEND_NAME_RELATIVE) {
  811. return zend_prefix_with_ns(name);
  812. }
  813. if (type == ZEND_NAME_FQ || ZSTR_VAL(name)[0] == '\\') {
  814. /* Remove \ prefix (only relevant if this is a string rather than a label) */
  815. if (ZSTR_VAL(name)[0] == '\\') {
  816. name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
  817. } else {
  818. zend_string_addref(name);
  819. }
  820. /* Ensure that \self, \parent and \static are not used */
  821. if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
  822. zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", ZSTR_VAL(name));
  823. }
  824. return name;
  825. }
  826. if (FC(imports)) {
  827. compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  828. if (compound) {
  829. /* If the first part of a qualified name is an alias, substitute it. */
  830. size_t len = compound - ZSTR_VAL(name);
  831. zend_string *import_name =
  832. zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
  833. if (import_name) {
  834. return zend_concat_names(
  835. ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
  836. }
  837. } else {
  838. /* If an unqualified name is an alias, replace it. */
  839. zend_string *import_name
  840. = zend_hash_find_ptr_lc(FC(imports), name);
  841. if (import_name) {
  842. return zend_string_copy(import_name);
  843. }
  844. }
  845. }
  846. /* If not fully qualified and not an alias, prepend the current namespace */
  847. return zend_prefix_with_ns(name);
  848. }
  849. /* }}} */
  850. zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
  851. {
  852. zval *class_name = zend_ast_get_zval(ast);
  853. if (Z_TYPE_P(class_name) != IS_STRING) {
  854. zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
  855. }
  856. return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
  857. }
  858. /* }}} */
  859. static void label_ptr_dtor(zval *zv) /* {{{ */
  860. {
  861. efree_size(Z_PTR_P(zv), sizeof(zend_label));
  862. }
  863. /* }}} */
  864. static void str_dtor(zval *zv) /* {{{ */ {
  865. zend_string_release_ex(Z_STR_P(zv), 0);
  866. }
  867. /* }}} */
  868. static zend_bool zend_is_call(zend_ast *ast);
  869. static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
  870. {
  871. zend_op_array *op_array = CG(active_op_array);
  872. uint32_t try_catch_offset = op_array->last_try_catch++;
  873. zend_try_catch_element *elem;
  874. op_array->try_catch_array = safe_erealloc(
  875. op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
  876. elem = &op_array->try_catch_array[try_catch_offset];
  877. elem->try_op = try_op;
  878. elem->catch_op = 0;
  879. elem->finally_op = 0;
  880. elem->finally_end = 0;
  881. return try_catch_offset;
  882. }
  883. /* }}} */
  884. ZEND_API void function_add_ref(zend_function *function) /* {{{ */
  885. {
  886. if (function->type == ZEND_USER_FUNCTION) {
  887. zend_op_array *op_array = &function->op_array;
  888. if (op_array->refcount) {
  889. (*op_array->refcount)++;
  890. }
  891. if (op_array->static_variables
  892. && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
  893. GC_ADDREF(op_array->static_variables);
  894. }
  895. if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
  896. ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_PRELOADED);
  897. ZEND_MAP_PTR_NEW(op_array->run_time_cache);
  898. ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
  899. } else {
  900. ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
  901. ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
  902. ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
  903. }
  904. }
  905. if (function->common.function_name) {
  906. zend_string_addref(function->common.function_name);
  907. }
  908. }
  909. /* }}} */
  910. static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, zend_bool compile_time) /* {{{ */
  911. {
  912. zval *zv = zend_hash_find_ex(compile_time ? CG(function_table) : EG(function_table), lcname, 1);
  913. int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
  914. zend_function *old_function;
  915. ZEND_ASSERT(zv != NULL);
  916. old_function = (zend_function*)Z_PTR_P(zv);
  917. if (old_function->type == ZEND_USER_FUNCTION
  918. && old_function->op_array.last > 0) {
  919. zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
  920. op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name),
  921. ZSTR_VAL(old_function->op_array.filename),
  922. old_function->op_array.opcodes[0].lineno);
  923. } else {
  924. zend_error_noreturn(error_level, "Cannot redeclare %s()",
  925. op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name));
  926. }
  927. }
  928. ZEND_API int do_bind_function(zval *lcname) /* {{{ */
  929. {
  930. zend_function *function;
  931. zval *rtd_key, *zv;
  932. rtd_key = lcname + 1;
  933. zv = zend_hash_find_ex(EG(function_table), Z_STR_P(rtd_key), 1);
  934. if (UNEXPECTED(!zv)) {
  935. do_bind_function_error(Z_STR_P(lcname), NULL, 0);
  936. return FAILURE;
  937. }
  938. function = (zend_function*)Z_PTR_P(zv);
  939. zv = zend_hash_set_bucket_key(EG(function_table), (Bucket*)zv, Z_STR_P(lcname));
  940. if (UNEXPECTED(!zv)) {
  941. do_bind_function_error(Z_STR_P(lcname), &function->op_array, 0);
  942. return FAILURE;
  943. }
  944. return SUCCESS;
  945. }
  946. /* }}} */
  947. ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
  948. {
  949. zend_class_entry *ce;
  950. zval *rtd_key, *zv;
  951. rtd_key = lcname + 1;
  952. zv = zend_hash_find_ex(EG(class_table), Z_STR_P(rtd_key), 1);
  953. if (UNEXPECTED(!zv)) {
  954. ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname));
  955. if (ce) {
  956. zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
  957. return FAILURE;
  958. } else {
  959. do {
  960. ZEND_ASSERT(EG(current_execute_data)->func->op_array.fn_flags & ZEND_ACC_PRELOADED);
  961. if (zend_preload_autoload
  962. && zend_preload_autoload(EG(current_execute_data)->func->op_array.filename) == SUCCESS) {
  963. zv = zend_hash_find_ex(EG(class_table), Z_STR_P(rtd_key), 1);
  964. if (EXPECTED(zv != NULL)) {
  965. break;
  966. }
  967. }
  968. zend_error_noreturn(E_ERROR, "Class %s wasn't preloaded", Z_STRVAL_P(lcname));
  969. return FAILURE;
  970. } while (0);
  971. }
  972. }
  973. /* Register the derived class */
  974. ce = (zend_class_entry*)Z_PTR_P(zv);
  975. zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
  976. if (UNEXPECTED(!zv)) {
  977. zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
  978. return FAILURE;
  979. }
  980. if (zend_do_link_class(ce, lc_parent_name) == FAILURE) {
  981. /* Reload bucket pointer, the hash table may have been reallocated */
  982. zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
  983. zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key));
  984. return FAILURE;
  985. }
  986. return SUCCESS;
  987. }
  988. /* }}} */
  989. static zend_string *add_type_string(zend_string *type, zend_string *new_type) {
  990. zend_string *result;
  991. if (type == NULL) {
  992. return zend_string_copy(new_type);
  993. }
  994. result = zend_string_concat3(
  995. ZSTR_VAL(type), ZSTR_LEN(type), "|", 1, ZSTR_VAL(new_type), ZSTR_LEN(new_type));
  996. zend_string_release(type);
  997. return result;
  998. }
  999. static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scope) {
  1000. if (scope) {
  1001. if (zend_string_equals_literal_ci(name, "self")) {
  1002. name = scope->name;
  1003. } else if (zend_string_equals_literal_ci(name, "parent") && scope->parent) {
  1004. name = scope->parent->name;
  1005. }
  1006. }
  1007. return name;
  1008. }
  1009. zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) {
  1010. zend_string *str = NULL;
  1011. if (ZEND_TYPE_HAS_LIST(type)) {
  1012. zend_type *list_type;
  1013. ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
  1014. if (ZEND_TYPE_HAS_CE(*list_type)) {
  1015. str = add_type_string(str, ZEND_TYPE_CE(*list_type)->name);
  1016. } else {
  1017. str = add_type_string(str, resolve_class_name(ZEND_TYPE_NAME(*list_type), scope));
  1018. }
  1019. } ZEND_TYPE_LIST_FOREACH_END();
  1020. } else if (ZEND_TYPE_HAS_NAME(type)) {
  1021. str = zend_string_copy(resolve_class_name(ZEND_TYPE_NAME(type), scope));
  1022. } else if (ZEND_TYPE_HAS_CE(type)) {
  1023. str = zend_string_copy(ZEND_TYPE_CE(type)->name);
  1024. }
  1025. uint32_t type_mask = ZEND_TYPE_FULL_MASK(type);
  1026. if (type_mask & MAY_BE_STATIC) {
  1027. zend_string *name = ZSTR_KNOWN(ZEND_STR_STATIC);
  1028. if (scope) {
  1029. zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
  1030. if (called_scope) {
  1031. name = called_scope->name;
  1032. }
  1033. }
  1034. str = add_type_string(str, name);
  1035. }
  1036. if (type_mask & MAY_BE_CALLABLE) {
  1037. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_CALLABLE));
  1038. }
  1039. if (type_mask & MAY_BE_ITERABLE) {
  1040. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ITERABLE));
  1041. }
  1042. if (type_mask & MAY_BE_OBJECT) {
  1043. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_OBJECT));
  1044. }
  1045. if (type_mask & MAY_BE_ARRAY) {
  1046. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_ARRAY));
  1047. }
  1048. if (type_mask & MAY_BE_STRING) {
  1049. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_STRING));
  1050. }
  1051. if (type_mask & MAY_BE_LONG) {
  1052. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_INT));
  1053. }
  1054. if (type_mask & MAY_BE_DOUBLE) {
  1055. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FLOAT));
  1056. }
  1057. if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
  1058. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_BOOL));
  1059. } else if (type_mask & MAY_BE_FALSE) {
  1060. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_FALSE));
  1061. }
  1062. if (type_mask & MAY_BE_VOID) {
  1063. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_VOID));
  1064. }
  1065. if (type_mask & MAY_BE_NULL) {
  1066. zend_bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
  1067. if (!is_union) {
  1068. zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str));
  1069. zend_string_release(str);
  1070. return nullable_str;
  1071. }
  1072. str = add_type_string(str, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE));
  1073. }
  1074. return str;
  1075. }
  1076. ZEND_API zend_string *zend_type_to_string(zend_type type) {
  1077. return zend_type_to_string_resolved(type, NULL);
  1078. }
  1079. static zend_bool is_generator_compatible_class_type(zend_string *name) {
  1080. return zend_string_equals_literal_ci(name, "Traversable")
  1081. || zend_string_equals_literal_ci(name, "Iterator")
  1082. || zend_string_equals_literal_ci(name, "Generator");
  1083. }
  1084. static void zend_mark_function_as_generator() /* {{{ */
  1085. {
  1086. if (!CG(active_op_array)->function_name) {
  1087. zend_error_noreturn(E_COMPILE_ERROR,
  1088. "The \"yield\" expression can only be used inside a function");
  1089. }
  1090. if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  1091. zend_type return_type = CG(active_op_array)->arg_info[-1].type;
  1092. zend_bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & MAY_BE_ITERABLE) != 0;
  1093. if (!valid_type) {
  1094. zend_type *single_type;
  1095. ZEND_TYPE_FOREACH(return_type, single_type) {
  1096. if (ZEND_TYPE_HAS_NAME(*single_type)
  1097. && is_generator_compatible_class_type(ZEND_TYPE_NAME(*single_type))) {
  1098. valid_type = 1;
  1099. break;
  1100. }
  1101. } ZEND_TYPE_FOREACH_END();
  1102. }
  1103. if (!valid_type) {
  1104. zend_string *str = zend_type_to_string(return_type);
  1105. zend_error_noreturn(E_COMPILE_ERROR,
  1106. "Generators may only declare a return type containing " \
  1107. "Generator, Iterator, Traversable, or iterable, %s is not permitted",
  1108. ZSTR_VAL(str));
  1109. }
  1110. }
  1111. CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
  1112. }
  1113. /* }}} */
  1114. ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array) /* {{{ */
  1115. {
  1116. if (op_array->fn_flags & ZEND_ACC_EARLY_BINDING) {
  1117. uint32_t first_early_binding_opline = (uint32_t)-1;
  1118. uint32_t *prev_opline_num = &first_early_binding_opline;
  1119. zend_op *opline = op_array->opcodes;
  1120. zend_op *end = opline + op_array->last;
  1121. while (opline < end) {
  1122. if (opline->opcode == ZEND_DECLARE_CLASS_DELAYED) {
  1123. *prev_opline_num = opline - op_array->opcodes;
  1124. prev_opline_num = &opline->result.opline_num;
  1125. }
  1126. ++opline;
  1127. }
  1128. *prev_opline_num = -1;
  1129. return first_early_binding_opline;
  1130. }
  1131. return (uint32_t)-1;
  1132. }
  1133. /* }}} */
  1134. ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array, uint32_t first_early_binding_opline) /* {{{ */
  1135. {
  1136. if (first_early_binding_opline != (uint32_t)-1) {
  1137. zend_bool orig_in_compilation = CG(in_compilation);
  1138. uint32_t opline_num = first_early_binding_opline;
  1139. void **run_time_cache;
  1140. if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
  1141. void *ptr;
  1142. ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE);
  1143. ptr = emalloc(op_array->cache_size + sizeof(void*));
  1144. ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
  1145. ptr = (char*)ptr + sizeof(void*);
  1146. ZEND_MAP_PTR_SET(op_array->run_time_cache, ptr);
  1147. memset(ptr, 0, op_array->cache_size);
  1148. }
  1149. run_time_cache = RUN_TIME_CACHE(op_array);
  1150. CG(in_compilation) = 1;
  1151. while (opline_num != (uint32_t)-1) {
  1152. const zend_op *opline = &op_array->opcodes[opline_num];
  1153. zval *lcname = RT_CONSTANT(opline, opline->op1);
  1154. zval *zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
  1155. if (zv) {
  1156. zend_class_entry *ce = Z_CE_P(zv);
  1157. zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
  1158. zend_class_entry *parent_ce = zend_hash_find_ex_ptr(EG(class_table), lc_parent_name, 1);
  1159. if (parent_ce) {
  1160. if (zend_try_early_bind(ce, parent_ce, Z_STR_P(lcname), zv)) {
  1161. /* Store in run-time cache */
  1162. ((void**)((char*)run_time_cache + opline->extended_value))[0] = ce;
  1163. }
  1164. }
  1165. }
  1166. opline_num = op_array->opcodes[opline_num].result.opline_num;
  1167. }
  1168. CG(in_compilation) = orig_in_compilation;
  1169. }
  1170. }
  1171. /* }}} */
  1172. ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal) /* {{{ */
  1173. {
  1174. size_t prop_name_length = 1 + src1_length + 1 + src2_length;
  1175. zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
  1176. ZSTR_VAL(prop_name)[0] = '\0';
  1177. memcpy(ZSTR_VAL(prop_name) + 1, src1, src1_length+1);
  1178. memcpy(ZSTR_VAL(prop_name) + 1 + src1_length + 1, src2, src2_length+1);
  1179. return prop_name;
  1180. }
  1181. /* }}} */
  1182. static zend_always_inline size_t zend_strnlen(const char* s, size_t maxlen) /* {{{ */
  1183. {
  1184. size_t len = 0;
  1185. while (*s++ && maxlen--) len++;
  1186. return len;
  1187. }
  1188. /* }}} */
  1189. ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len) /* {{{ */
  1190. {
  1191. size_t class_name_len;
  1192. size_t anonclass_src_len;
  1193. *class_name = NULL;
  1194. if (!ZSTR_LEN(name) || ZSTR_VAL(name)[0] != '\0') {
  1195. *prop_name = ZSTR_VAL(name);
  1196. if (prop_len) {
  1197. *prop_len = ZSTR_LEN(name);
  1198. }
  1199. return SUCCESS;
  1200. }
  1201. if (ZSTR_LEN(name) < 3 || ZSTR_VAL(name)[1] == '\0') {
  1202. zend_error(E_NOTICE, "Illegal member variable name");
  1203. *prop_name = ZSTR_VAL(name);
  1204. if (prop_len) {
  1205. *prop_len = ZSTR_LEN(name);
  1206. }
  1207. return FAILURE;
  1208. }
  1209. class_name_len = zend_strnlen(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 2);
  1210. if (class_name_len >= ZSTR_LEN(name) - 2 || ZSTR_VAL(name)[class_name_len + 1] != '\0') {
  1211. zend_error(E_NOTICE, "Corrupt member variable name");
  1212. *prop_name = ZSTR_VAL(name);
  1213. if (prop_len) {
  1214. *prop_len = ZSTR_LEN(name);
  1215. }
  1216. return FAILURE;
  1217. }
  1218. *class_name = ZSTR_VAL(name) + 1;
  1219. anonclass_src_len = zend_strnlen(*class_name + class_name_len + 1, ZSTR_LEN(name) - class_name_len - 2);
  1220. if (class_name_len + anonclass_src_len + 2 != ZSTR_LEN(name)) {
  1221. class_name_len += anonclass_src_len + 1;
  1222. }
  1223. *prop_name = ZSTR_VAL(name) + class_name_len + 2;
  1224. if (prop_len) {
  1225. *prop_len = ZSTR_LEN(name) - class_name_len - 2;
  1226. }
  1227. return SUCCESS;
  1228. }
  1229. /* }}} */
  1230. static zend_bool can_ct_eval_const(zend_constant *c) {
  1231. if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
  1232. return 0;
  1233. }
  1234. if ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)
  1235. && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION)
  1236. && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE)
  1237. && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) {
  1238. return 1;
  1239. }
  1240. if (Z_TYPE(c->value) < IS_OBJECT
  1241. && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
  1242. return 1;
  1243. }
  1244. return 0;
  1245. }
  1246. static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */
  1247. {
  1248. zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name);
  1249. if (c && can_ct_eval_const(c)) {
  1250. ZVAL_COPY_OR_DUP(zv, &c->value);
  1251. return 1;
  1252. }
  1253. {
  1254. /* Substitute true, false and null (including unqualified usage in namespaces) */
  1255. const char *lookup_name = ZSTR_VAL(name);
  1256. size_t lookup_len = ZSTR_LEN(name);
  1257. if (!is_fully_qualified) {
  1258. zend_get_unqualified_name(name, &lookup_name, &lookup_len);
  1259. }
  1260. if ((c = zend_get_special_const(lookup_name, lookup_len))) {
  1261. ZVAL_COPY_VALUE(zv, &c->value);
  1262. return 1;
  1263. }
  1264. return 0;
  1265. }
  1266. }
  1267. /* }}} */
  1268. static inline zend_bool zend_is_scope_known() /* {{{ */
  1269. {
  1270. if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
  1271. /* Closures can be rebound to a different scope */
  1272. return 0;
  1273. }
  1274. if (!CG(active_class_entry)) {
  1275. /* The scope is known if we're in a free function (no scope), but not if we're in
  1276. * a file/eval (which inherits including/eval'ing scope). */
  1277. return CG(active_op_array)->function_name != NULL;
  1278. }
  1279. /* For traits self etc refers to the using class, not the trait itself */
  1280. return (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == 0;
  1281. }
  1282. /* }}} */
  1283. static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
  1284. {
  1285. if (!CG(active_class_entry)) {
  1286. return 0;
  1287. }
  1288. if (fetch_type == ZEND_FETCH_CLASS_SELF && zend_is_scope_known()) {
  1289. return 1;
  1290. }
  1291. return fetch_type == ZEND_FETCH_CLASS_DEFAULT
  1292. && zend_string_equals_ci(class_name, CG(active_class_entry)->name);
  1293. }
  1294. /* }}} */
  1295. uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
  1296. {
  1297. if (zend_string_equals_literal_ci(name, "self")) {
  1298. return ZEND_FETCH_CLASS_SELF;
  1299. } else if (zend_string_equals_literal_ci(name, "parent")) {
  1300. return ZEND_FETCH_CLASS_PARENT;
  1301. } else if (zend_string_equals_literal_ci(name, "static")) {
  1302. return ZEND_FETCH_CLASS_STATIC;
  1303. } else {
  1304. return ZEND_FETCH_CLASS_DEFAULT;
  1305. }
  1306. }
  1307. /* }}} */
  1308. static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
  1309. {
  1310. /* Fully qualified names are always default refs */
  1311. if (name_ast->attr == ZEND_NAME_FQ) {
  1312. return ZEND_FETCH_CLASS_DEFAULT;
  1313. }
  1314. return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
  1315. }
  1316. /* }}} */
  1317. static zend_string *zend_resolve_const_class_name_reference(zend_ast *ast, const char *type)
  1318. {
  1319. zend_string *class_name = zend_ast_get_str(ast);
  1320. if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type_ast(ast)) {
  1321. zend_error_noreturn(E_COMPILE_ERROR,
  1322. "Cannot use '%s' as %s, as it is reserved",
  1323. ZSTR_VAL(class_name), type);
  1324. }
  1325. return zend_resolve_class_name(class_name, ast->attr);
  1326. }
  1327. static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
  1328. {
  1329. if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && zend_is_scope_known()) {
  1330. zend_class_entry *ce = CG(active_class_entry);
  1331. if (!ce) {
  1332. zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
  1333. fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
  1334. fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
  1335. } else if (fetch_type == ZEND_FETCH_CLASS_PARENT && !ce->parent_name) {
  1336. zend_error_noreturn(E_COMPILE_ERROR,
  1337. "Cannot use \"parent\" when current class scope has no parent");
  1338. }
  1339. }
  1340. }
  1341. /* }}} */
  1342. static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
  1343. {
  1344. uint32_t fetch_type;
  1345. zval *class_name;
  1346. if (class_ast->kind != ZEND_AST_ZVAL) {
  1347. return 0;
  1348. }
  1349. class_name = zend_ast_get_zval(class_ast);
  1350. if (Z_TYPE_P(class_name) != IS_STRING) {
  1351. zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
  1352. }
  1353. fetch_type = zend_get_class_fetch_type(Z_STR_P(class_name));
  1354. zend_ensure_valid_class_fetch_type(fetch_type);
  1355. switch (fetch_type) {
  1356. case ZEND_FETCH_CLASS_SELF:
  1357. if (CG(active_class_entry) && zend_is_scope_known()) {
  1358. ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
  1359. return 1;
  1360. }
  1361. return 0;
  1362. case ZEND_FETCH_CLASS_PARENT:
  1363. if (CG(active_class_entry) && CG(active_class_entry)->parent_name
  1364. && zend_is_scope_known()) {
  1365. ZVAL_STR_COPY(zv, CG(active_class_entry)->parent_name);
  1366. return 1;
  1367. }
  1368. return 0;
  1369. case ZEND_FETCH_CLASS_STATIC:
  1370. return 0;
  1371. case ZEND_FETCH_CLASS_DEFAULT:
  1372. ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
  1373. return 1;
  1374. EMPTY_SWITCH_DEFAULT_CASE()
  1375. }
  1376. }
  1377. /* }}} */
  1378. /* We don't use zend_verify_const_access because we need to deal with unlinked classes. */
  1379. static zend_bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope)
  1380. {
  1381. if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
  1382. return 1;
  1383. } else if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PRIVATE) {
  1384. return c->ce == scope;
  1385. } else {
  1386. zend_class_entry *ce = c->ce;
  1387. while (1) {
  1388. if (ce == scope) {
  1389. return 1;
  1390. }
  1391. if (!ce->parent) {
  1392. break;
  1393. }
  1394. if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
  1395. ce = ce->parent;
  1396. } else {
  1397. ce = zend_hash_find_ptr_lc(CG(class_table), ce->parent_name);
  1398. if (!ce) {
  1399. break;
  1400. }
  1401. }
  1402. }
  1403. /* Reverse case cannot be true during compilation */
  1404. return 0;
  1405. }
  1406. }
  1407. static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
  1408. {
  1409. uint32_t fetch_type = zend_get_class_fetch_type(class_name);
  1410. zend_class_constant *cc;
  1411. zval *c;
  1412. if (class_name_refers_to_active_ce(class_name, fetch_type)) {
  1413. cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
  1414. } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
  1415. zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name);
  1416. if (ce) {
  1417. cc = zend_hash_find_ptr(&ce->constants_table, name);
  1418. } else {
  1419. return 0;
  1420. }
  1421. } else {
  1422. return 0;
  1423. }
  1424. if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
  1425. return 0;
  1426. }
  1427. if (!cc || !zend_verify_ct_const_access(cc, CG(active_class_entry))) {
  1428. return 0;
  1429. }
  1430. c = &cc->value;
  1431. /* Substitute case-sensitive (or lowercase) persistent class constants */
  1432. if (Z_TYPE_P(c) < IS_OBJECT) {
  1433. ZVAL_COPY_OR_DUP(zv, c);
  1434. return 1;
  1435. }
  1436. return 0;
  1437. }
  1438. /* }}} */
  1439. static void zend_add_to_list(void *result, void *item) /* {{{ */
  1440. {
  1441. void** list = *(void**)result;
  1442. size_t n = 0;
  1443. if (list) {
  1444. while (list[n]) {
  1445. n++;
  1446. }
  1447. }
  1448. list = erealloc(list, sizeof(void*) * (n+2));
  1449. list[n] = item;
  1450. list[n+1] = NULL;
  1451. *(void**)result = list;
  1452. }
  1453. /* }}} */
  1454. void zend_do_extended_stmt(void) /* {{{ */
  1455. {
  1456. zend_op *opline;
  1457. if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT)) {
  1458. return;
  1459. }
  1460. opline = get_next_op();
  1461. opline->opcode = ZEND_EXT_STMT;
  1462. }
  1463. /* }}} */
  1464. void zend_do_extended_fcall_begin(void) /* {{{ */
  1465. {
  1466. zend_op *opline;
  1467. if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
  1468. return;
  1469. }
  1470. opline = get_next_op();
  1471. opline->opcode = ZEND_EXT_FCALL_BEGIN;
  1472. }
  1473. /* }}} */
  1474. void zend_do_extended_fcall_end(void) /* {{{ */
  1475. {
  1476. zend_op *opline;
  1477. if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_FCALL)) {
  1478. return;
  1479. }
  1480. opline = get_next_op();
  1481. opline->opcode = ZEND_EXT_FCALL_END;
  1482. }
  1483. /* }}} */
  1484. zend_bool zend_is_auto_global_str(char *name, size_t len) /* {{{ */ {
  1485. zend_auto_global *auto_global;
  1486. if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
  1487. if (auto_global->armed) {
  1488. auto_global->armed = auto_global->auto_global_callback(auto_global->name);
  1489. }
  1490. return 1;
  1491. }
  1492. return 0;
  1493. }
  1494. /* }}} */
  1495. zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
  1496. {
  1497. zend_auto_global *auto_global;
  1498. if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
  1499. if (auto_global->armed) {
  1500. auto_global->armed = auto_global->auto_global_callback(auto_global->name);
  1501. }
  1502. return 1;
  1503. }
  1504. return 0;
  1505. }
  1506. /* }}} */
  1507. int zend_register_auto_global(zend_string *name, zend_bool jit, z

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