zend_execute.c 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2016 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@zend.com> |
  16. | Zeev Suraski <zeev@zend.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. #define ZEND_INTENSIVE_DEBUGGING 0
  21. #include <stdio.h>
  22. #include <signal.h>
  23. #include "zend.h"
  24. #include "zend_compile.h"
  25. #include "zend_execute.h"
  26. #include "zend_API.h"
  27. #include "zend_ptr_stack.h"
  28. #include "zend_constants.h"
  29. #include "zend_extensions.h"
  30. #include "zend_ini.h"
  31. #include "zend_exceptions.h"
  32. #include "zend_interfaces.h"
  33. #include "zend_closures.h"
  34. #include "zend_generators.h"
  35. #include "zend_vm.h"
  36. #include "zend_dtrace.h"
  37. /* Virtual current working directory support */
  38. #include "zend_virtual_cwd.h"
  39. #define _CONST_CODE 0
  40. #define _TMP_CODE 1
  41. #define _VAR_CODE 2
  42. #define _UNUSED_CODE 3
  43. #define _CV_CODE 4
  44. typedef int (*incdec_t)(zval *);
  45. #define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
  46. #define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
  47. #define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
  48. #define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC)
  49. /* Prototypes */
  50. static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
  51. static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
  52. static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
  53. #define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
  54. #define EX_T(offset) (*EX_TMP_VAR(execute_data, offset))
  55. #define EX_CV(var) (*EX_CV_NUM(execute_data, var))
  56. #define TEMP_VAR_STACK_LIMIT 2000
  57. static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC)
  58. {
  59. if (!Z_DELREF_P(z)) {
  60. Z_SET_REFCOUNT_P(z, 1);
  61. Z_UNSET_ISREF_P(z);
  62. should_free->var = z;
  63. /* should_free->is_var = 1; */
  64. } else {
  65. should_free->var = 0;
  66. if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) {
  67. Z_UNSET_ISREF_P(z);
  68. }
  69. }
  70. }
  71. static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
  72. {
  73. if (!Z_DELREF_P(z)) {
  74. ZEND_ASSERT(z != &EG(uninitialized_zval));
  75. GC_REMOVE_ZVAL_FROM_BUFFER(z);
  76. zval_dtor(z);
  77. efree(z);
  78. }
  79. }
  80. #undef zval_ptr_dtor
  81. #define zval_ptr_dtor(pzv) i_zval_ptr_dtor(*(pzv) ZEND_FILE_LINE_CC TSRMLS_CC)
  82. #define zval_ptr_dtor_nogc(pzv) i_zval_ptr_dtor_nogc(*(pzv) ZEND_FILE_LINE_CC TSRMLS_CC)
  83. #define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
  84. #define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
  85. #define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC)
  86. #define PZVAL_LOCK(z) Z_ADDREF_P((z))
  87. #define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
  88. #define EXTRACT_ZVAL_PTR(t) do { \
  89. temp_variable *__t = (t); \
  90. __t->var.ptr = *__t->var.ptr_ptr; \
  91. __t->var.ptr_ptr = &__t->var.ptr; \
  92. if (!PZVAL_IS_REF(__t->var.ptr) && \
  93. Z_REFCOUNT_P(__t->var.ptr) > 2) { \
  94. SEPARATE_ZVAL(__t->var.ptr_ptr); \
  95. } \
  96. } while (0)
  97. #define AI_SET_PTR(t, val) do { \
  98. temp_variable *__t = (t); \
  99. __t->var.ptr = (val); \
  100. __t->var.ptr_ptr = &__t->var.ptr; \
  101. } while (0)
  102. #define FREE_OP(should_free) \
  103. if (should_free.var) { \
  104. if ((zend_uintptr_t)should_free.var & 1L) { \
  105. zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
  106. } else { \
  107. zval_ptr_dtor_nogc(&should_free.var); \
  108. } \
  109. }
  110. #define FREE_OP_IF_VAR(should_free) \
  111. if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
  112. zval_ptr_dtor_nogc(&should_free.var); \
  113. }
  114. #define FREE_OP_VAR_PTR(should_free) \
  115. if (should_free.var) { \
  116. zval_ptr_dtor_nogc(&should_free.var); \
  117. }
  118. #define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
  119. #define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
  120. #define MAKE_REAL_ZVAL_PTR(val) \
  121. do { \
  122. zval *_tmp; \
  123. ALLOC_ZVAL(_tmp); \
  124. INIT_PZVAL_COPY(_tmp, (val)); \
  125. (val) = _tmp; \
  126. } while (0)
  127. /* End of zend_execute_locks.h */
  128. #define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
  129. #define CTOR_CALL_BIT 0x1
  130. #define CTOR_USED_BIT 0x2
  131. #define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
  132. #define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
  133. #define ENCODE_CTOR(ce, used) \
  134. ((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
  135. #define DECODE_CTOR(ce) \
  136. ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
  137. #undef EX
  138. #define EX(element) execute_data->element
  139. ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data, zend_uint var)
  140. {
  141. return EX_CV(var);
  142. }
  143. static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
  144. {
  145. return should_free->var = &EX_T(var).tmp_var;
  146. }
  147. static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
  148. {
  149. zval *ptr = EX_T(var).var.ptr;
  150. return should_free->var = ptr;
  151. }
  152. static zend_never_inline zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
  153. {
  154. zend_compiled_variable *cv = &CV_DEF_OF(var);
  155. if (!EG(active_symbol_table) ||
  156. zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
  157. switch (type) {
  158. case BP_VAR_R:
  159. case BP_VAR_UNSET:
  160. zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  161. /* break missing intentionally */
  162. case BP_VAR_IS:
  163. return &EG(uninitialized_zval_ptr);
  164. break;
  165. case BP_VAR_RW:
  166. zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  167. /* break missing intentionally */
  168. case BP_VAR_W:
  169. Z_ADDREF(EG(uninitialized_zval));
  170. if (!EG(active_symbol_table)) {
  171. *ptr = (zval**)EX_CV_NUM(EG(current_execute_data), EG(active_op_array)->last_var + var);
  172. **ptr = &EG(uninitialized_zval);
  173. } else {
  174. zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
  175. }
  176. break;
  177. }
  178. }
  179. return *ptr;
  180. }
  181. static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_R(zval ***ptr, zend_uint var TSRMLS_DC)
  182. {
  183. zend_compiled_variable *cv = &CV_DEF_OF(var);
  184. if (!EG(active_symbol_table) ||
  185. zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
  186. zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  187. return &EG(uninitialized_zval_ptr);
  188. }
  189. return *ptr;
  190. }
  191. static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_UNSET(zval ***ptr, zend_uint var TSRMLS_DC)
  192. {
  193. zend_compiled_variable *cv = &CV_DEF_OF(var);
  194. if (!EG(active_symbol_table) ||
  195. zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
  196. zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  197. return &EG(uninitialized_zval_ptr);
  198. }
  199. return *ptr;
  200. }
  201. static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_IS(zval ***ptr, zend_uint var TSRMLS_DC)
  202. {
  203. zend_compiled_variable *cv = &CV_DEF_OF(var);
  204. if (!EG(active_symbol_table) ||
  205. zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
  206. return &EG(uninitialized_zval_ptr);
  207. }
  208. return *ptr;
  209. }
  210. static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_RW(zval ***ptr, zend_uint var TSRMLS_DC)
  211. {
  212. zend_compiled_variable *cv = &CV_DEF_OF(var);
  213. if (!EG(active_symbol_table)) {
  214. Z_ADDREF(EG(uninitialized_zval));
  215. *ptr = (zval**)EX_CV_NUM(EG(current_execute_data), EG(active_op_array)->last_var + var);
  216. **ptr = &EG(uninitialized_zval);
  217. zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  218. } else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
  219. Z_ADDREF(EG(uninitialized_zval));
  220. zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
  221. zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
  222. }
  223. return *ptr;
  224. }
  225. static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_W(zval ***ptr, zend_uint var TSRMLS_DC)
  226. {
  227. zend_compiled_variable *cv = &CV_DEF_OF(var);
  228. if (!EG(active_symbol_table)) {
  229. Z_ADDREF(EG(uninitialized_zval));
  230. *ptr = (zval**)EX_CV_NUM(EG(current_execute_data), EG(active_op_array)->last_var + var);
  231. **ptr = &EG(uninitialized_zval);
  232. } else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
  233. Z_ADDREF(EG(uninitialized_zval));
  234. zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
  235. }
  236. return *ptr;
  237. }
  238. static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_DC)
  239. {
  240. zval ***ptr = EX_CV_NUM(EG(current_execute_data), var);
  241. if (UNEXPECTED(*ptr == NULL)) {
  242. return *_get_zval_cv_lookup(ptr, var, type TSRMLS_CC);
  243. }
  244. return **ptr;
  245. }
  246. static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  247. {
  248. zval ***ptr = EX_CV_NUM(execute_data, var);
  249. if (UNEXPECTED(*ptr == NULL)) {
  250. return *_get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
  251. }
  252. return **ptr;
  253. }
  254. static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  255. {
  256. zval ***ptr = EX_CV_NUM(execute_data, var);
  257. if (UNEXPECTED(*ptr == NULL)) {
  258. return *_get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC);
  259. }
  260. return **ptr;
  261. }
  262. static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  263. {
  264. zval ***ptr = EX_CV_NUM(execute_data, var);
  265. if (UNEXPECTED(*ptr == NULL)) {
  266. return *_get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC);
  267. }
  268. return **ptr;
  269. }
  270. static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  271. {
  272. zval ***ptr = EX_CV_NUM(execute_data, var);
  273. if (UNEXPECTED(*ptr == NULL)) {
  274. return *_get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC);
  275. }
  276. return **ptr;
  277. }
  278. static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  279. {
  280. zval ***ptr = EX_CV_NUM(execute_data, var);
  281. if (UNEXPECTED(*ptr == NULL)) {
  282. return *_get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC);
  283. }
  284. return **ptr;
  285. }
  286. static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
  287. {
  288. /* should_free->is_var = 0; */
  289. switch (op_type) {
  290. case IS_CONST:
  291. should_free->var = 0;
  292. return node->zv;
  293. break;
  294. case IS_TMP_VAR:
  295. should_free->var = TMP_FREE(&EX_T(node->var).tmp_var);
  296. return &EX_T(node->var).tmp_var;
  297. break;
  298. case IS_VAR:
  299. return _get_zval_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
  300. break;
  301. case IS_UNUSED:
  302. should_free->var = 0;
  303. return NULL;
  304. break;
  305. case IS_CV:
  306. should_free->var = 0;
  307. return _get_zval_ptr_cv(node->var, type TSRMLS_CC);
  308. break;
  309. EMPTY_SWITCH_DEFAULT_CASE()
  310. }
  311. return NULL;
  312. }
  313. static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
  314. {
  315. zval** ptr_ptr = EX_T(var).var.ptr_ptr;
  316. if (EXPECTED(ptr_ptr != NULL)) {
  317. PZVAL_UNLOCK(*ptr_ptr, should_free);
  318. } else {
  319. /* string offset */
  320. PZVAL_UNLOCK(EX_T(var).str_offset.str, should_free);
  321. }
  322. return ptr_ptr;
  323. }
  324. static zend_always_inline zval **_get_zval_ptr_ptr_var_fast(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC)
  325. {
  326. zval** ptr_ptr = EX_T(var).var.ptr_ptr;
  327. if (EXPECTED(ptr_ptr != NULL)) {
  328. should_free->var = *ptr_ptr;
  329. } else {
  330. /* string offset */
  331. should_free->var = EX_T(var).str_offset.str;
  332. }
  333. return ptr_ptr;
  334. }
  335. static zend_always_inline zval **_get_zval_ptr_ptr_cv(zend_uint var, int type TSRMLS_DC)
  336. {
  337. zval ***ptr = EX_CV_NUM(EG(current_execute_data), var);
  338. if (UNEXPECTED(*ptr == NULL)) {
  339. return _get_zval_cv_lookup(ptr, var, type TSRMLS_CC);
  340. }
  341. return *ptr;
  342. }
  343. static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  344. {
  345. zval ***ptr = EX_CV_NUM(execute_data, var);
  346. if (UNEXPECTED(*ptr == NULL)) {
  347. return _get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
  348. }
  349. return *ptr;
  350. }
  351. static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  352. {
  353. zval ***ptr = EX_CV_NUM(execute_data, var);
  354. if (UNEXPECTED(*ptr == NULL)) {
  355. return _get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC);
  356. }
  357. return *ptr;
  358. }
  359. static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  360. {
  361. zval ***ptr = EX_CV_NUM(execute_data, var);
  362. if (UNEXPECTED(*ptr == NULL)) {
  363. return _get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC);
  364. }
  365. return *ptr;
  366. }
  367. static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  368. {
  369. zval ***ptr = EX_CV_NUM(execute_data, var);
  370. if (UNEXPECTED(*ptr == NULL)) {
  371. return _get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC);
  372. }
  373. return *ptr;
  374. }
  375. static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
  376. {
  377. zval ***ptr = EX_CV_NUM(execute_data, var);
  378. if (UNEXPECTED(*ptr == NULL)) {
  379. return _get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC);
  380. }
  381. return *ptr;
  382. }
  383. static inline zval **_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
  384. {
  385. if (op_type == IS_CV) {
  386. should_free->var = 0;
  387. return _get_zval_ptr_ptr_cv(node->var, type TSRMLS_CC);
  388. } else if (op_type == IS_VAR) {
  389. return _get_zval_ptr_ptr_var(node->var, execute_data, should_free TSRMLS_CC);
  390. } else {
  391. should_free->var = 0;
  392. return NULL;
  393. }
  394. }
  395. static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
  396. {
  397. if (EXPECTED(EG(This) != NULL)) {
  398. return EG(This);
  399. } else {
  400. zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  401. return NULL;
  402. }
  403. }
  404. static inline zval **_get_obj_zval_ptr_ptr(int op_type, const znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
  405. {
  406. if (op_type == IS_UNUSED) {
  407. if (EXPECTED(EG(This) != NULL)) {
  408. /* this should actually never be modified, _ptr_ptr is modified only when
  409. the object is empty */
  410. should_free->var = 0;
  411. return &EG(This);
  412. } else {
  413. zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  414. }
  415. }
  416. return get_zval_ptr_ptr(op_type, op, execute_data, should_free, type);
  417. }
  418. static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
  419. {
  420. if (EXPECTED(EG(This) != NULL)) {
  421. return &EG(This);
  422. } else {
  423. zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  424. return NULL;
  425. }
  426. }
  427. static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC)
  428. {
  429. if (op_type == IS_UNUSED) {
  430. if (EXPECTED(EG(This) != NULL)) {
  431. should_free->var = 0;
  432. return EG(This);
  433. } else {
  434. zend_error_noreturn(E_ERROR, "Using $this when not in object context");
  435. }
  436. }
  437. return get_zval_ptr(op_type, op, execute_data, should_free, type);
  438. }
  439. static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC)
  440. {
  441. zval *variable_ptr = *variable_ptr_ptr;
  442. zval *value_ptr = *value_ptr_ptr;
  443. if (variable_ptr != value_ptr) {
  444. if (!PZVAL_IS_REF(value_ptr)) {
  445. /* break it away */
  446. Z_DELREF_P(value_ptr);
  447. if (Z_REFCOUNT_P(value_ptr)>0) {
  448. ALLOC_ZVAL(*value_ptr_ptr);
  449. ZVAL_COPY_VALUE(*value_ptr_ptr, value_ptr);
  450. value_ptr = *value_ptr_ptr;
  451. zendi_zval_copy_ctor(*value_ptr);
  452. }
  453. Z_SET_REFCOUNT_P(value_ptr, 1);
  454. Z_SET_ISREF_P(value_ptr);
  455. }
  456. *variable_ptr_ptr = value_ptr;
  457. Z_ADDREF_P(value_ptr);
  458. zval_ptr_dtor(&variable_ptr);
  459. } else if (!Z_ISREF_P(variable_ptr)) {
  460. if (variable_ptr_ptr == value_ptr_ptr) {
  461. SEPARATE_ZVAL(variable_ptr_ptr);
  462. } else if (variable_ptr==&EG(uninitialized_zval)
  463. || Z_REFCOUNT_P(variable_ptr)>2) {
  464. /* we need to separate */
  465. Z_SET_REFCOUNT_P(variable_ptr, Z_REFCOUNT_P(variable_ptr) - 2);
  466. ALLOC_ZVAL(*variable_ptr_ptr);
  467. ZVAL_COPY_VALUE(*variable_ptr_ptr, variable_ptr);
  468. zval_copy_ctor(*variable_ptr_ptr);
  469. *value_ptr_ptr = *variable_ptr_ptr;
  470. Z_SET_REFCOUNT_PP(variable_ptr_ptr, 2);
  471. }
  472. Z_SET_ISREF_PP(variable_ptr_ptr);
  473. }
  474. }
  475. /* this should modify object only if it's empty */
  476. static inline void make_real_object(zval **object_ptr TSRMLS_DC)
  477. {
  478. if (Z_TYPE_PP(object_ptr) == IS_NULL
  479. || (Z_TYPE_PP(object_ptr) == IS_BOOL && Z_LVAL_PP(object_ptr) == 0)
  480. || (Z_TYPE_PP(object_ptr) == IS_STRING && Z_STRLEN_PP(object_ptr) == 0)
  481. ) {
  482. SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
  483. zval_dtor(*object_ptr);
  484. object_init(*object_ptr);
  485. zend_error(E_WARNING, "Creating default object from empty value");
  486. }
  487. }
  488. ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC)
  489. {
  490. *pce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
  491. *class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name;
  492. if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
  493. return "implement interface ";
  494. } else {
  495. return "be an instance of ";
  496. }
  497. }
  498. ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
  499. {
  500. zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
  501. const char *fname = zf->common.function_name;
  502. char *fsep;
  503. const char *fclass;
  504. if (zf->common.scope) {
  505. fsep = "::";
  506. fclass = zf->common.scope->name;
  507. } else {
  508. fsep = "";
  509. fclass = "";
  510. }
  511. if (ptr && ptr->op_array) {
  512. zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->op_array->filename, ptr->opline->lineno);
  513. } else {
  514. zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
  515. }
  516. return 0;
  517. }
  518. static int is_null_constant(zval *default_value TSRMLS_DC)
  519. {
  520. if (IS_CONSTANT_TYPE(Z_TYPE_P(default_value))) {
  521. zval constant = *default_value;
  522. zval *constant_ptr = &constant;
  523. zval_update_constant(&constant_ptr, 0 TSRMLS_CC);
  524. if (Z_TYPE(constant) == IS_NULL) {
  525. return 1;
  526. }
  527. zval_dtor(&constant);
  528. }
  529. return 0;
  530. }
  531. static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type, zval *default_value TSRMLS_DC)
  532. {
  533. zend_arg_info *cur_arg_info;
  534. char *need_msg;
  535. zend_class_entry *ce;
  536. if (!zf->common.arg_info) {
  537. return 1;
  538. }
  539. if (arg_num <= zf->common.num_args) {
  540. cur_arg_info = &zf->common.arg_info[arg_num-1];
  541. } else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
  542. cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
  543. } else {
  544. return 1;
  545. }
  546. if (cur_arg_info->class_name) {
  547. const char *class_name;
  548. if (!arg) {
  549. need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
  550. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
  551. }
  552. if (Z_TYPE_P(arg) == IS_OBJECT) {
  553. need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
  554. if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
  555. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
  556. }
  557. } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value TSRMLS_CC)))) {
  558. need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
  559. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
  560. }
  561. } else if (cur_arg_info->type_hint) {
  562. switch(cur_arg_info->type_hint) {
  563. case IS_ARRAY:
  564. if (!arg) {
  565. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
  566. }
  567. if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value TSRMLS_CC))))) {
  568. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
  569. }
  570. break;
  571. case IS_CALLABLE:
  572. if (!arg) {
  573. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
  574. }
  575. if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value TSRMLS_CC))))) {
  576. return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
  577. }
  578. break;
  579. default:
  580. zend_error(E_ERROR, "Unknown typehint");
  581. }
  582. }
  583. return 1;
  584. }
  585. static inline void zend_assign_to_object(zval **retval, zval **object_ptr, zval *property_name, int value_type, znode_op *value_op, const zend_execute_data *execute_data, int opcode, const zend_literal *key TSRMLS_DC)
  586. {
  587. zval *object = *object_ptr;
  588. zend_free_op free_value;
  589. zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R);
  590. if (Z_TYPE_P(object) != IS_OBJECT) {
  591. if (object == &EG(error_zval)) {
  592. if (retval) {
  593. *retval = &EG(uninitialized_zval);
  594. PZVAL_LOCK(*retval);
  595. }
  596. FREE_OP(free_value);
  597. return;
  598. }
  599. if (Z_TYPE_P(object) == IS_NULL ||
  600. (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) ||
  601. (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
  602. SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
  603. object = *object_ptr;
  604. Z_ADDREF_P(object);
  605. zend_error(E_WARNING, "Creating default object from empty value");
  606. if (Z_REFCOUNT_P(object) == 1) {
  607. /* object was removed by error handler, nothing to assign to */
  608. zval_ptr_dtor(&object);
  609. if (retval) {
  610. *retval = &EG(uninitialized_zval);
  611. PZVAL_LOCK(*retval);
  612. }
  613. FREE_OP(free_value);
  614. return;
  615. }
  616. Z_DELREF_P(object);
  617. zval_dtor(object);
  618. object_init(object);
  619. } else {
  620. zend_error(E_WARNING, "Attempt to assign property of non-object");
  621. if (retval) {
  622. *retval = &EG(uninitialized_zval);
  623. PZVAL_LOCK(*retval);
  624. }
  625. FREE_OP(free_value);
  626. return;
  627. }
  628. }
  629. /* separate our value if necessary */
  630. if (value_type == IS_TMP_VAR) {
  631. zval *orig_value = value;
  632. ALLOC_ZVAL(value);
  633. ZVAL_COPY_VALUE(value, orig_value);
  634. Z_UNSET_ISREF_P(value);
  635. Z_SET_REFCOUNT_P(value, 0);
  636. } else if (value_type == IS_CONST) {
  637. zval *orig_value = value;
  638. ALLOC_ZVAL(value);
  639. ZVAL_COPY_VALUE(value, orig_value);
  640. Z_UNSET_ISREF_P(value);
  641. Z_SET_REFCOUNT_P(value, 0);
  642. zval_copy_ctor(value);
  643. }
  644. Z_ADDREF_P(value);
  645. if (opcode == ZEND_ASSIGN_OBJ) {
  646. if (!Z_OBJ_HT_P(object)->write_property) {
  647. zend_error(E_WARNING, "Attempt to assign property of non-object");
  648. if (retval) {
  649. *retval = &EG(uninitialized_zval);
  650. PZVAL_LOCK(&EG(uninitialized_zval));
  651. }
  652. if (value_type == IS_TMP_VAR) {
  653. FREE_ZVAL(value);
  654. } else if (value_type == IS_CONST) {
  655. zval_ptr_dtor(&value);
  656. }
  657. FREE_OP(free_value);
  658. return;
  659. }
  660. Z_OBJ_HT_P(object)->write_property(object, property_name, value, key TSRMLS_CC);
  661. } else {
  662. /* Note: property_name in this case is really the array index! */
  663. if (!Z_OBJ_HT_P(object)->write_dimension) {
  664. zend_error_noreturn(E_ERROR, "Cannot use object as array");
  665. }
  666. Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
  667. }
  668. if (retval && !EG(exception)) {
  669. *retval = value;
  670. PZVAL_LOCK(value);
  671. }
  672. zval_ptr_dtor(&value);
  673. FREE_OP_IF_VAR(free_value);
  674. }
  675. static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC)
  676. {
  677. zval *str = T->str_offset.str;
  678. zend_uint offset = T->str_offset.offset;
  679. if (Z_TYPE_P(str) == IS_STRING) {
  680. if ((int)offset < 0) {
  681. zend_error(E_WARNING, "Illegal string offset: %d", offset);
  682. return 0;
  683. }
  684. if (offset >= Z_STRLEN_P(str)) {
  685. Z_STRVAL_P(str) = str_erealloc(Z_STRVAL_P(str), offset+1+1);
  686. memset(Z_STRVAL_P(str) + Z_STRLEN_P(str), ' ', offset - Z_STRLEN_P(str));
  687. Z_STRVAL_P(str)[offset+1] = 0;
  688. Z_STRLEN_P(str) = offset+1;
  689. } else if (IS_INTERNED(Z_STRVAL_P(str))) {
  690. Z_STRVAL_P(str) = estrndup(Z_STRVAL_P(str), Z_STRLEN_P(str));
  691. }
  692. if (Z_TYPE_P(value) != IS_STRING) {
  693. zval tmp;
  694. ZVAL_COPY_VALUE(&tmp, value);
  695. if (value_type != IS_TMP_VAR) {
  696. zval_copy_ctor(&tmp);
  697. }
  698. convert_to_string(&tmp);
  699. Z_STRVAL_P(str)[offset] = Z_STRVAL(tmp)[0];
  700. str_efree(Z_STRVAL(tmp));
  701. } else {
  702. Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
  703. if (value_type == IS_TMP_VAR) {
  704. /* we can safely free final_value here
  705. * because separation is done only
  706. * in case value_type == IS_VAR */
  707. str_efree(Z_STRVAL_P(value));
  708. }
  709. }
  710. /*
  711. * the value of an assignment to a string offset is undefined
  712. T(result->u.var).var = &T->str_offset.str;
  713. */
  714. }
  715. return 1;
  716. }
  717. static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
  718. {
  719. zval *variable_ptr = *variable_ptr_ptr;
  720. zval garbage;
  721. if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
  722. UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
  723. Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
  724. return variable_ptr;
  725. }
  726. if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
  727. EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
  728. /* we need to split */
  729. Z_DELREF_P(variable_ptr);
  730. GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
  731. ALLOC_ZVAL(variable_ptr);
  732. INIT_PZVAL_COPY(variable_ptr, value);
  733. *variable_ptr_ptr = variable_ptr;
  734. return variable_ptr;
  735. } else {
  736. if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
  737. /* nothing to destroy */
  738. ZVAL_COPY_VALUE(variable_ptr, value);
  739. } else {
  740. ZVAL_COPY_VALUE(&garbage, variable_ptr);
  741. ZVAL_COPY_VALUE(variable_ptr, value);
  742. _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
  743. }
  744. return variable_ptr;
  745. }
  746. }
  747. static inline zval* zend_assign_const_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
  748. {
  749. zval *variable_ptr = *variable_ptr_ptr;
  750. zval garbage;
  751. if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
  752. UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
  753. Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
  754. return variable_ptr;
  755. }
  756. if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
  757. EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
  758. /* we need to split */
  759. Z_DELREF_P(variable_ptr);
  760. GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
  761. ALLOC_ZVAL(variable_ptr);
  762. INIT_PZVAL_COPY(variable_ptr, value);
  763. zval_copy_ctor(variable_ptr);
  764. *variable_ptr_ptr = variable_ptr;
  765. return variable_ptr;
  766. } else {
  767. if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
  768. /* nothing to destroy */
  769. ZVAL_COPY_VALUE(variable_ptr, value);
  770. zendi_zval_copy_ctor(*variable_ptr);
  771. } else {
  772. ZVAL_COPY_VALUE(&garbage, variable_ptr);
  773. ZVAL_COPY_VALUE(variable_ptr, value);
  774. zendi_zval_copy_ctor(*variable_ptr);
  775. _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
  776. }
  777. return variable_ptr;
  778. }
  779. }
  780. static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
  781. {
  782. zval *variable_ptr = *variable_ptr_ptr;
  783. zval garbage;
  784. if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
  785. UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
  786. Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
  787. return variable_ptr;
  788. }
  789. if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
  790. if (Z_REFCOUNT_P(variable_ptr)==1) {
  791. if (UNEXPECTED(variable_ptr == value)) {
  792. return variable_ptr;
  793. } else if (EXPECTED(!PZVAL_IS_REF(value))) {
  794. Z_ADDREF_P(value);
  795. *variable_ptr_ptr = value;
  796. ZEND_ASSERT(variable_ptr != &EG(uninitialized_zval));
  797. GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
  798. zval_dtor(variable_ptr);
  799. efree(variable_ptr);
  800. return value;
  801. } else {
  802. goto copy_value;
  803. }
  804. } else { /* we need to split */
  805. Z_DELREF_P(variable_ptr);
  806. GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
  807. if (PZVAL_IS_REF(value)) {
  808. ALLOC_ZVAL(variable_ptr);
  809. *variable_ptr_ptr = variable_ptr;
  810. INIT_PZVAL_COPY(variable_ptr, value);
  811. zval_copy_ctor(variable_ptr);
  812. return variable_ptr;
  813. } else {
  814. *variable_ptr_ptr = value;
  815. Z_ADDREF_P(value);
  816. return value;
  817. }
  818. }
  819. } else {
  820. if (EXPECTED(variable_ptr != value)) {
  821. copy_value:
  822. if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
  823. /* nothing to destroy */
  824. ZVAL_COPY_VALUE(variable_ptr, value);
  825. zendi_zval_copy_ctor(*variable_ptr);
  826. } else {
  827. ZVAL_COPY_VALUE(&garbage, variable_ptr);
  828. ZVAL_COPY_VALUE(variable_ptr, value);
  829. zendi_zval_copy_ctor(*variable_ptr);
  830. _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
  831. }
  832. }
  833. return variable_ptr;
  834. }
  835. }
  836. static void zval_deep_copy(zval **p)
  837. {
  838. zval *value;
  839. ALLOC_ZVAL(value);
  840. *value = **p;
  841. if (Z_TYPE_P(value) == IS_ARRAY) {
  842. HashTable *ht;
  843. ALLOC_HASHTABLE(ht);
  844. zend_hash_init(ht, zend_hash_num_elements(Z_ARRVAL_P(value)), NULL, ZVAL_PTR_DTOR, 0);
  845. zend_hash_copy(ht, Z_ARRVAL_P(value), (copy_ctor_func_t) zval_deep_copy, NULL, sizeof(zval *));
  846. Z_ARRVAL_P(value) = ht;
  847. } else {
  848. zval_copy_ctor(value);
  849. }
  850. INIT_PZVAL(value);
  851. *p = value;
  852. }
  853. /* Utility Functions for Extensions */
  854. static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
  855. {
  856. if (extension->statement_handler) {
  857. extension->statement_handler(op_array);
  858. }
  859. }
  860. static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
  861. {
  862. if (extension->fcall_begin_handler) {
  863. extension->fcall_begin_handler(op_array);
  864. }
  865. }
  866. static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
  867. {
  868. if (extension->fcall_end_handler) {
  869. extension->fcall_end_handler(op_array);
  870. }
  871. }
  872. static inline HashTable *zend_get_target_symbol_table(int fetch_type TSRMLS_DC)
  873. {
  874. switch (fetch_type) {
  875. case ZEND_FETCH_LOCAL:
  876. if (!EG(active_symbol_table)) {
  877. zend_rebuild_symbol_table(TSRMLS_C);
  878. }
  879. return EG(active_symbol_table);
  880. break;
  881. case ZEND_FETCH_GLOBAL:
  882. case ZEND_FETCH_GLOBAL_LOCK:
  883. return &EG(symbol_table);
  884. break;
  885. case ZEND_FETCH_STATIC:
  886. if (!EG(active_op_array)->static_variables) {
  887. ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
  888. zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
  889. }
  890. return EG(active_op_array)->static_variables;
  891. break;
  892. EMPTY_SWITCH_DEFAULT_CASE()
  893. }
  894. return NULL;
  895. }
  896. static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type TSRMLS_DC)
  897. {
  898. zval **retval;
  899. char *offset_key;
  900. int offset_key_length;
  901. ulong hval;
  902. switch (dim->type) {
  903. case IS_NULL:
  904. offset_key = "";
  905. offset_key_length = 0;
  906. hval = zend_inline_hash_func("", 1);
  907. goto fetch_string_dim;
  908. case IS_STRING:
  909. offset_key = dim->value.str.val;
  910. offset_key_length = dim->value.str.len;
  911. if (dim_type == IS_CONST) {
  912. hval = Z_HASH_P(dim);
  913. } else {
  914. ZEND_HANDLE_NUMERIC_EX(offset_key, offset_key_length+1, hval, goto num_index);
  915. hval = str_hash(offset_key, offset_key_length);
  916. }
  917. fetch_string_dim:
  918. if (zend_hash_quick_find(ht, offset_key, offset_key_length+1, hval, (void **) &retval) == FAILURE) {
  919. switch (type) {
  920. case BP_VAR_R:
  921. zend_error(E_NOTICE, "Undefined index: %s", offset_key);
  922. /* break missing intentionally */
  923. case BP_VAR_UNSET:
  924. case BP_VAR_IS:
  925. retval = &EG(uninitialized_zval_ptr);
  926. break;
  927. case BP_VAR_RW:
  928. zend_error(E_NOTICE,"Undefined index: %s", offset_key);
  929. /* break missing intentionally */
  930. case BP_VAR_W: {
  931. zval *new_zval = &EG(uninitialized_zval);
  932. Z_ADDREF_P(new_zval);
  933. zend_hash_quick_update(ht, offset_key, offset_key_length+1, hval, &new_zval, sizeof(zval *), (void **) &retval);
  934. }
  935. break;
  936. }
  937. }
  938. break;
  939. case IS_DOUBLE:
  940. hval = zend_dval_to_lval(Z_DVAL_P(dim));
  941. goto num_index;
  942. case IS_RESOURCE:
  943. zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim));
  944. /* Fall Through */
  945. case IS_BOOL:
  946. case IS_LONG:
  947. hval = Z_LVAL_P(dim);
  948. num_index:
  949. if (zend_hash_index_find(ht, hval, (void **) &retval) == FAILURE) {
  950. switch (type) {
  951. case BP_VAR_R:
  952. zend_error(E_NOTICE,"Undefined offset: %ld", hval);
  953. /* break missing intentionally */
  954. case BP_VAR_UNSET:
  955. case BP_VAR_IS:
  956. retval = &EG(uninitialized_zval_ptr);
  957. break;
  958. case BP_VAR_RW:
  959. zend_error(E_NOTICE,"Undefined offset: %ld", hval);
  960. /* break missing intentionally */
  961. case BP_VAR_W: {
  962. zval *new_zval = &EG(uninitialized_zval);
  963. Z_ADDREF_P(new_zval);
  964. zend_hash_index_update(ht, hval, &new_zval, sizeof(zval *), (void **) &retval);
  965. }
  966. break;
  967. }
  968. }
  969. break;
  970. default:
  971. zend_error(E_WARNING, "Illegal offset type");
  972. return (type == BP_VAR_W || type == BP_VAR_RW) ?
  973. &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr);
  974. }
  975. return retval;
  976. }
  977. static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_type, int type TSRMLS_DC)
  978. {
  979. zval *container = *container_ptr;
  980. zval **retval;
  981. switch (Z_TYPE_P(container)) {
  982. case IS_ARRAY:
  983. if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) {
  984. SEPARATE_ZVAL(container_ptr);
  985. container = *container_ptr;
  986. }
  987. fetch_from_array:
  988. if (dim == NULL) {
  989. zval *new_zval = &EG(uninitialized_zval);
  990. Z_ADDREF_P(new_zval);
  991. if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) {
  992. zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
  993. retval = &EG(error_zval_ptr);
  994. Z_DELREF_P(new_zval);
  995. }
  996. } else {
  997. retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
  998. }
  999. result->var.ptr_ptr = retval;
  1000. PZVAL_LOCK(*retval);
  1001. return;
  1002. break;
  1003. case IS_NULL:
  1004. if (container == &EG(error_zval)) {
  1005. result->var.ptr_ptr = &EG(error_zval_ptr);
  1006. PZVAL_LOCK(EG(error_zval_ptr));
  1007. } else if (type != BP_VAR_UNSET) {
  1008. convert_to_array:
  1009. if (!PZVAL_IS_REF(container)) {
  1010. SEPARATE_ZVAL(container_ptr);
  1011. container = *container_ptr;
  1012. }
  1013. zval_dtor(container);
  1014. array_init(container);
  1015. goto fetch_from_array;
  1016. } else {
  1017. /* for read-mode only */
  1018. result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
  1019. PZVAL_LOCK(EG(uninitialized_zval_ptr));
  1020. }
  1021. return;
  1022. break;
  1023. case IS_STRING: {
  1024. zval tmp;
  1025. if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) {
  1026. goto convert_to_array;
  1027. }
  1028. if (dim == NULL) {
  1029. zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
  1030. }
  1031. if (type != BP_VAR_UNSET) {
  1032. SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
  1033. }
  1034. if (Z_TYPE_P(dim) != IS_LONG) {
  1035. switch(Z_TYPE_P(dim)) {
  1036. /* case IS_LONG: */
  1037. case IS_STRING:
  1038. if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
  1039. break;
  1040. }
  1041. if (type != BP_VAR_UNSET) {
  1042. zend_error(E_WARNING, "Illegal string offset '%s'", dim->value.str.val);
  1043. }
  1044. break;
  1045. case IS_DOUBLE:
  1046. case IS_NULL:
  1047. case IS_BOOL:
  1048. zend_error(E_NOTICE, "String offset cast occurred");
  1049. break;
  1050. default:
  1051. zend_error(E_WARNING, "Illegal offset type");
  1052. break;
  1053. }
  1054. tmp = *dim;
  1055. zval_copy_ctor(&tmp);
  1056. convert_to_long(&tmp);
  1057. dim = &tmp;
  1058. }
  1059. container = *container_ptr;
  1060. result->str_offset.str = container;
  1061. PZVAL_LOCK(container);
  1062. result->str_offset.offset = Z_LVAL_P(dim);
  1063. result->str_offset.ptr_ptr = NULL;
  1064. return;
  1065. }
  1066. break;
  1067. case IS_OBJECT:
  1068. if (!Z_OBJ_HT_P(container)->read_dimension) {
  1069. zend_error_noreturn(E_ERROR, "Cannot use object as array");
  1070. } else {
  1071. zval *overloaded_result;
  1072. if (dim_type == IS_TMP_VAR) {
  1073. zval *orig = dim;
  1074. MAKE_REAL_ZVAL_PTR(dim);
  1075. ZVAL_NULL(orig);
  1076. }
  1077. overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
  1078. if (overloaded_result) {
  1079. if (!Z_ISREF_P(overloaded_result)) {
  1080. if (Z_REFCOUNT_P(overloaded_result) > 0) {
  1081. zval *tmp = overloaded_result;
  1082. ALLOC_ZVAL(overloaded_result);
  1083. ZVAL_COPY_VALUE(overloaded_result, tmp);
  1084. zval_copy_ctor(overloaded_result);
  1085. Z_UNSET_ISREF_P(overloaded_result);
  1086. Z_SET_REFCOUNT_P(overloaded_result, 0);
  1087. }
  1088. if (Z_TYPE_P(overloaded_result) != IS_OBJECT) {
  1089. zend_class_entry *ce = Z_OBJCE_P(container);
  1090. zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
  1091. }
  1092. }
  1093. AI_SET_PTR(result, overloaded_result);
  1094. PZVAL_LOCK(overloaded_result);
  1095. } else {
  1096. result->var.ptr_ptr = &EG(error_zval_ptr);
  1097. PZVAL_LOCK(EG(error_zval_ptr));
  1098. }
  1099. if (dim_type == IS_TMP_VAR) {
  1100. zval_ptr_dtor(&dim);
  1101. }
  1102. }
  1103. return;
  1104. break;
  1105. case IS_BOOL:
  1106. if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
  1107. goto convert_to_array;
  1108. }
  1109. /* break missing intentionally */
  1110. default:
  1111. if (type == BP_VAR_UNSET) {
  1112. zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
  1113. result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
  1114. PZVAL_LOCK(EG(uninitialized_zval_ptr));
  1115. } else {
  1116. zend_error(E_WARNING, "Cannot use a scalar value as an array");
  1117. result->var.ptr_ptr = &EG(error_zval_ptr);
  1118. PZVAL_LOCK(EG(error_zval_ptr));
  1119. }
  1120. break;
  1121. }
  1122. }
  1123. static void zend_fetch_dimension_address_read(temp_variable *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
  1124. {
  1125. zval **retval;
  1126. switch (Z_TYPE_P(container)) {
  1127. case IS_ARRAY:
  1128. retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
  1129. result->var.ptr = *retval;
  1130. PZVAL_LOCK(*retval);
  1131. return;
  1132. case IS_NULL:
  1133. result->var.ptr = &EG(uninitialized_zval);
  1134. PZVAL_LOCK(&EG(uninitialized_zval));
  1135. return;
  1136. case IS_STRING: {
  1137. zval tmp;
  1138. zval *ptr;
  1139. if (Z_TYPE_P(dim) != IS_LONG) {
  1140. switch(Z_TYPE_P(dim)) {
  1141. /* case IS_LONG: */
  1142. case IS_STRING:
  1143. if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
  1144. break;
  1145. }
  1146. if (type != BP_VAR_IS) {
  1147. zend_error(E_WARNING, "Illegal string offset '%s'", dim->value.str.val);
  1148. }
  1149. break;
  1150. case IS_DOUBLE:
  1151. case IS_NULL:
  1152. case IS_BOOL:
  1153. if (type != BP_VAR_IS) {
  1154. zend_error(E_NOTICE, "String offset cast occurred");
  1155. }
  1156. break;
  1157. default:
  1158. zend_error(E_WARNING, "Illegal offset type");
  1159. break;
  1160. }
  1161. ZVAL_COPY_VALUE(&tmp, dim);
  1162. zval_copy_ctor(&tmp);
  1163. convert_to_long(&tmp);
  1164. dim = &tmp;
  1165. }
  1166. ALLOC_ZVAL(ptr);
  1167. INIT_PZVAL(ptr);
  1168. Z_TYPE_P(ptr) = IS_STRING;
  1169. if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) {
  1170. if (type != BP_VAR_IS) {
  1171. zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
  1172. }
  1173. Z_STRVAL_P(ptr) = STR_EMPTY_ALLOC();
  1174. Z_STRLEN_P(ptr) = 0;
  1175. } else {
  1176. Z_STRVAL_P(ptr) = (char*)emalloc(2);
  1177. Z_STRVAL_P(ptr)[0] = Z_STRVAL_P(container)[Z_LVAL_P(dim)];
  1178. Z_STRVAL_P(ptr)[1] = 0;
  1179. Z_STRLEN_P(ptr) = 1;
  1180. }
  1181. result->var.ptr = ptr;
  1182. return;
  1183. }
  1184. break;
  1185. case IS_OBJECT:
  1186. if (!Z_OBJ_HT_P(container)->read_dimension) {
  1187. zend_error_noreturn(E_ERROR, "Cannot use object as array");
  1188. } else {
  1189. zval *overloaded_result;
  1190. if (dim_type == IS_TMP_VAR) {
  1191. zval *orig = dim;
  1192. MAKE_REAL_ZVAL_PTR(dim);
  1193. ZVAL_NULL(orig);
  1194. }
  1195. overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
  1196. if (result) {
  1197. if (overloaded_result) {
  1198. result->var.ptr = overloaded_result;
  1199. PZVAL_LOCK(overloaded_result);
  1200. } else {
  1201. result->var.ptr = &EG(uninitialized_zval);
  1202. PZVAL_LOCK(&EG(uninitialized_zval));
  1203. }
  1204. }
  1205. if (dim_type == IS_TMP_VAR) {
  1206. zval_ptr_dtor(&dim);
  1207. }
  1208. }
  1209. return;
  1210. default:
  1211. result->var.ptr = &EG(uninitialized_zval);
  1212. PZVAL_LOCK(&EG(uninitialized_zval));
  1213. return;
  1214. }
  1215. }
  1216. ZEND_API void zend_fetch_dimension_by_zval(zval **result, zval *container, zval *dim TSRMLS_DC) {
  1217. temp_variable tmp;
  1218. zend_fetch_dimension_address_read(&tmp, container, dim, IS_TMP_VAR, BP_VAR_R TSRMLS_CC);
  1219. *result = tmp.var.ptr;
  1220. }
  1221. static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, const zend_literal *key, int type TSRMLS_DC)
  1222. {
  1223. zval *container = *container_ptr;
  1224. if (Z_TYPE_P(container) != IS_OBJECT) {
  1225. if (container == &EG(error_zval)) {
  1226. result->var.ptr_ptr = &EG(error_zval_ptr);
  1227. PZVAL_LOCK(EG(error_zval_ptr));
  1228. return;
  1229. }
  1230. /* this should modify object only if it's empty */
  1231. if (type != BP_VAR_UNSET &&
  1232. ((Z_TYPE_P(container) == IS_NULL ||
  1233. (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) ||
  1234. (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
  1235. if (!PZVAL_IS_REF(container)) {
  1236. SEPARATE_ZVAL(container_ptr);
  1237. container = *container_ptr;
  1238. }
  1239. object_init(container);
  1240. } else {
  1241. zend_error(E_WARNING, "Attempt to modify property of non-object");
  1242. result->var.ptr_ptr = &EG(error_zval_ptr);
  1243. PZVAL_LOCK(EG(error_zval_ptr));
  1244. return;
  1245. }
  1246. }
  1247. if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
  1248. zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, key TSRMLS_CC);
  1249. if (NULL == ptr_ptr) {
  1250. zval *ptr;
  1251. if (Z_OBJ_HT_P(container)->read_property &&
  1252. (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, key TSRMLS_CC)) != NULL) {
  1253. AI_SET_PTR(result, ptr);
  1254. PZVAL_LOCK(ptr);
  1255. } else {
  1256. zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
  1257. }
  1258. } else {
  1259. result->var.ptr_ptr = ptr_ptr;
  1260. PZVAL_LOCK(*ptr_ptr);
  1261. }
  1262. } else if (Z_OBJ_HT_P(container)->read_property) {
  1263. zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, key TSRMLS_CC);
  1264. AI_SET_PTR(result, ptr);
  1265. PZVAL_LOCK(ptr);
  1266. } else {
  1267. zend_error(E_WARNING, "This object doesn't support property references");
  1268. result->var.ptr_ptr = &EG(error_zval_ptr);
  1269. PZVAL_LOCK(EG(error_zval_ptr));
  1270. }
  1271. }
  1272. static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const zend_execute_data *execute_data TSRMLS_DC)
  1273. {
  1274. int original_nest_levels = nest_levels;
  1275. zend_brk_cont_element *jmp_to;
  1276. do {
  1277. if (array_offset==-1) {
  1278. zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
  1279. }
  1280. jmp_to = &op_array->brk_cont_array[array_offset];
  1281. if (nest_levels>1) {
  1282. zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
  1283. switch (brk_opline->opcode) {
  1284. case ZEND_SWITCH_FREE:
  1285. if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
  1286. zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
  1287. }
  1288. break;
  1289. case ZEND_FREE:
  1290. if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
  1291. zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
  1292. }
  1293. break;
  1294. }
  1295. }
  1296. array_offset = jmp_to->parent;
  1297. } while (--nest_levels > 0);
  1298. return jmp_to;
  1299. }
  1300. #if ZEND_INTENSIVE_DEBUGGING
  1301. #define CHECK_SYMBOL_TABLES() \
  1302. zend_hash_apply(&EG(symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC); \
  1303. if (&EG(symbol_table)!=EG(active_symbol_table)) { \
  1304. zend_hash_apply(EG(active_symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC); \
  1305. }
  1306. static int zend_check_symbol(zval **pz TSRMLS_DC)
  1307. {
  1308. if (Z_TYPE_PP(pz) > 9) {
  1309. fprintf(stderr, "Warning! %x has invalid type!\n", *pz);
  1310. /* See http://support.microsoft.com/kb/190351 */
  1311. #ifdef PHP_WIN32
  1312. fflush(stderr);
  1313. #endif
  1314. } else if (Z_TYPE_PP(pz) == IS_ARRAY) {
  1315. zend_hash_apply(Z_ARRVAL_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
  1316. } else if (Z_TYPE_PP(pz) == IS_OBJECT) {
  1317. /* OBJ-TBI - doesn't support new object model! */
  1318. zend_hash_apply(Z_OBJPROP_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
  1319. }
  1320. return 0;
  1321. }
  1322. #else
  1323. #define CHECK_SYMBOL_TABLES()
  1324. #endif
  1325. ZEND_API opcode_handler_t *zend_opcode_handlers;
  1326. ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC)
  1327. {
  1328. if (fci != NULL) {
  1329. execute_data_ptr->function_state.function->internal_function.handler(
  1330. fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr,
  1331. fci->object_ptr, 1 TSRMLS_CC
  1332. );
  1333. } else {
  1334. zval **return_value_ptr = &EX_TMP_VAR(execute_data_ptr, execute_data_ptr->opline->result.var)->var.ptr;
  1335. execute_data_ptr->function_state.function->internal_function.handler(
  1336. execute_data_ptr->opline->extended_value + execute_data_ptr->call->num_additional_args,
  1337. *return_value_ptr, return_value_ptr,
  1338. execute_data_ptr->object, return_value_used TSRMLS_CC
  1339. );
  1340. }
  1341. }
  1342. void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{ */
  1343. {
  1344. if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
  1345. zend_hash_destroy(symbol_table);
  1346. FREE_HASHTABLE(symbol_table);
  1347. } else {
  1348. /* clean before putting into the cache, since clean
  1349. could call dtors, which could use cached hash */
  1350. zend_hash_clean(symbol_table);
  1351. *(++EG(symtable_cache_ptr)) = symbol_table;
  1352. }
  1353. }
  1354. /* }}} */
  1355. static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
  1356. {
  1357. zval ***cv = EX_CV_NUM(execute_data, 0);
  1358. zval ***end = cv + EX(op_array)->last_var;
  1359. while (cv != end) {
  1360. if (*cv) {
  1361. zval_ptr_dtor(*cv);
  1362. }
  1363. cv++;
  1364. }
  1365. }
  1366. /* }}} */
  1367. void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
  1368. {
  1369. i_free_compiled_variables(execute_data TSRMLS_CC);
  1370. }
  1371. /* }}} */
  1372. /*
  1373. * Stack Frame Layout (the whole stack frame is allocated at once)
  1374. * ==================
  1375. *
  1376. * +========================================+
  1377. * | zend_execute_data |<---+
  1378. * | EX(function_state).arguments |--+ |
  1379. * | ... | | |
  1380. * | ARGUMENT [1] | | |
  1381. * | ... | | |
  1382. * | ARGUMENT [ARGS_NUMBER] | | |
  1383. * | ARGS_NUMBER |<-+ |
  1384. * +========================================+ |
  1385. * |
  1386. * +========================================+ |
  1387. * | TMP_VAR[op_arrat->T-1] | |
  1388. * | ... | |
  1389. * EX_TMP_VAR_NUM(0) ----> | TMP_VAR[0] | |
  1390. * +----------------------------------------+ |
  1391. * EG(current_execute_data) -> | zend_execute_data | |
  1392. * | EX(prev_execute_data) |----+
  1393. * +----------------------------------------+
  1394. * EX_CV_NUM(0) ---------> | CV[0] |--+
  1395. * | ... | |
  1396. * | CV[op_array->last_var-1] | |
  1397. * +----------------------------------------+ |
  1398. * | Optional slot for CV[0] zval* |<-+
  1399. * | ... |
  1400. * | ...for CV [op_array->last_var-1] zval* |
  1401. * +----------------------------------------+
  1402. * EX(call_slots) -> | CALL_SLOT[0] |
  1403. * | ... |
  1404. * | CALL_SLOT[op_array->nested_calls-1] |
  1405. * +----------------------------------------+
  1406. * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] |
  1407. * | ... |
  1408. * zend_vm_stack_top --------> | ... |
  1409. * | ... |
  1410. * | ARGUMENTS STACK [op_array->used_stack] |
  1411. * +----------------------------------------+
  1412. */
  1413. static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
  1414. {
  1415. zend_execute_data *execute_data;
  1416. /*
  1417. * When allocating the execute_data, memory for compiled variables and
  1418. * temporary variables is also allocated before and after the actual
  1419. * zend_execute_data struct. In addition we also allocate space to store
  1420. * information about syntactically nested called functions and actual
  1421. * parameters. op_array->last_var specifies the number of compiled
  1422. * variables and op_array->T is the number of temporary variables. If there
  1423. * is no symbol table, then twice as much memory is allocated for compiled
  1424. * variables. In that case the first half contains zval**s and the second
  1425. * half the actual zval*s (which would otherwise be in the symbol table).
  1426. */
  1427. size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
  1428. size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2));
  1429. size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T;
  1430. size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
  1431. size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack;
  1432. size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size;
  1433. /*
  1434. * Normally the execute_data is allocated on the VM stack (because it does
  1435. * not actually do any allocation and thus is faster). For generators
  1436. * though this behavior would be suboptimal, because the (rather large)
  1437. * structure would have to be copied back and forth every time execution is
  1438. * suspended or resumed. That's why for generators the execution context
  1439. * is allocated using a separate VM stack, thus allowing to save and
  1440. * restore it simply by replacing a pointer. The same segment also keeps
  1441. * a copy of previous execute_data and passed parameters.
  1442. */
  1443. if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
  1444. /* Prepend the regular stack frame with a copy of prev_execute_data
  1445. * and the passed arguments
  1446. */
  1447. int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
  1448. size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1);
  1449. total_size += args_size + execute_data_size;
  1450. EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*));
  1451. EG(argument_stack)->prev = NULL;
  1452. execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size + Ts_size);
  1453. /* copy prev_execute_data */
  1454. EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size);
  1455. memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
  1456. EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
  1457. EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count);
  1458. /* copy arguments */
  1459. *EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count;
  1460. if (args_count > 0) {
  1461. zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
  1462. zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
  1463. int i;
  1464. for (i = 0; i < args_count; i++) {
  1465. arg_dst[i] = arg_src[i];
  1466. Z_ADDREF_P(arg_dst[i]);
  1467. }
  1468. }
  1469. } else {
  1470. execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC);
  1471. execute_data = (zend_execute_data*)((char*)execute_data + Ts_size);
  1472. EX(prev_execute_data) = EG(current_execute_data);
  1473. }
  1474. memset(EX_CV_NUM(execute_data, 0), 0, sizeof(zval **) * op_array->last_var);
  1475. EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + CVs_size);
  1476. EX(op_array) = op_array;
  1477. EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data);
  1478. EX(object) = NULL;
  1479. EX(current_this) = NULL;
  1480. EX(old_error_reporting) = NULL;
  1481. EX(symbol_table) = EG(active_symbol_table);
  1482. EX(call) = NULL;
  1483. EG(current_execute_data) = execute_data;
  1484. EX(nested) = nested;
  1485. EX(delayed_exception) = NULL;
  1486. if (!op_array->run_time_cache && op_array->last_cache_slot) {
  1487. op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
  1488. }
  1489. if (op_array->this_var != -1 && EG(This)) {
  1490. Z_ADDREF_P(EG(This)); /* For $this pointer */
  1491. if (!EG(active_symbol_table)) {
  1492. EX_CV(op_array->this_var) = (zval **) EX_CV_NUM(execute_data, op_array->last_var + op_array->this_var);
  1493. *EX_CV(op_array->this_var) = EG(This);
  1494. } else {
  1495. if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) EX_CV_NUM(execute_data, op_array->this_var))==FAILURE) {
  1496. Z_DELREF_P(EG(This));
  1497. }
  1498. }
  1499. }
  1500. EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
  1501. EG(opline_ptr) = &EX(opline);
  1502. EX(function_state).function = (zend_function *) op_array;
  1503. EX(function_state).arguments = NULL;
  1504. return execute_data;
  1505. }
  1506. /* }}} */
  1507. ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */
  1508. {
  1509. return i_create_execute_data_from_op_array(op_array, nested TSRMLS_CC);
  1510. }
  1511. /* }}} */
  1512. static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, call_slot *call TSRMLS_DC) /* {{{ */
  1513. {
  1514. zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
  1515. return ARG_SHOULD_BE_SENT_BY_REF(call->fbc, arg_num);
  1516. }
  1517. /* }}} */
  1518. static void **zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
  1519. {
  1520. zend_vm_stack p = EG(argument_stack);
  1521. zend_vm_stack_extend(count + 1 TSRMLS_CC);
  1522. EG(argument_stack)->top += count;
  1523. *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
  1524. while (count-- > 0) {
  1525. void *data = *(--p->top);
  1526. if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
  1527. zend_vm_stack r = p;
  1528. EG(argument_stack)->prev = p->prev;
  1529. p = p->prev;
  1530. efree(r);
  1531. }
  1532. *(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data;
  1533. }
  1534. return EG(argument_stack)->top++;
  1535. }
  1536. /* }}} */
  1537. static zend_always_inline void** zend_vm_stack_push_args(int count TSRMLS_DC) /* {{{ */
  1538. {
  1539. if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)
  1540. || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
  1541. return zend_vm_stack_push_args_with_copy(count TSRMLS_CC);
  1542. }
  1543. *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count;
  1544. return EG(argument_stack)->top++;
  1545. }
  1546. /* }}} */
  1547. #define ZEND_VM_NEXT_OPCODE() \
  1548. CHECK_SYMBOL_TABLES() \
  1549. ZEND_VM_INC_OPCODE(); \
  1550. ZEND_VM_CONTINUE()
  1551. #define ZEND_VM_SET_OPCODE(new_op) \
  1552. CHECK_SYMBOL_TABLES() \
  1553. OPLINE = new_op
  1554. #define ZEND_VM_JMP(new_op) \
  1555. if (EXPECTED(!EG(exception))) { \
  1556. ZEND_VM_SET_OPCODE(new_op); \
  1557. } else { \
  1558. LOAD_OPLINE(); \
  1559. } \
  1560. ZEND_VM_CONTINUE()
  1561. #define ZEND_VM_INC_OPCODE() \
  1562. OPLINE++
  1563. #ifdef __GNUC__
  1564. # define ZEND_VM_GUARD(name) __asm__("#" #name)
  1565. #else
  1566. # define ZEND_VM_GUARD(name)
  1567. #endif
  1568. #include "zend_vm_execute.h"
  1569. ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
  1570. {
  1571. if (opcode != ZEND_USER_OPCODE) {
  1572. if (handler == NULL) {
  1573. /* restore the original handler */
  1574. zend_user_opcodes[opcode] = opcode;
  1575. } else {
  1576. zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
  1577. }
  1578. zend_user_opcode_handlers[opcode] = handler;
  1579. return SUCCESS;
  1580. }
  1581. return FAILURE;
  1582. }
  1583. ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
  1584. {
  1585. return zend_user_opcode_handlers[opcode];
  1586. }
  1587. ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
  1588. return get_zval_ptr(op_type, node, execute_data, should_free, type);
  1589. }
  1590. ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) {
  1591. return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
  1592. }
  1593. /*
  1594. * Local variables:
  1595. * tab-width: 4
  1596. * c-basic-offset: 4
  1597. * indent-tabs-mode: t
  1598. * End:
  1599. */