You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

554 lines
15 KiB

27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 0.91 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.zend.com/license/0_91.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. #include <stdio.h>
  20. #include <signal.h>
  21. #include "zend.h"
  22. #include "zend_compile.h"
  23. #include "zend_execute.h"
  24. #include "zend_API.h"
  25. #include "zend_ptr_stack.h"
  26. #include "zend_variables.h"
  27. #include "zend_operators.h"
  28. #include "zend_constants.h"
  29. #include "zend_extensions.h"
  30. ZEND_API void (*zend_execute)(zend_op_array *op_array ELS_DC);
  31. #if ZEND_DEBUG
  32. static void (*original_sigsegv_handler)(int);
  33. static void zend_handle_sigsegv(int dummy)
  34. {
  35. fflush(stdout);
  36. fflush(stderr);
  37. if (original_sigsegv_handler==zend_handle_sigsegv) {
  38. signal(SIGSEGV, original_sigsegv_handler);
  39. } else {
  40. signal(SIGSEGV, SIG_DFL);
  41. }
  42. {
  43. ELS_FETCH();
  44. fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
  45. active_opline->opcode,
  46. active_opline-EG(active_op_array)->opcodes,
  47. get_active_function_name(),
  48. zend_get_executed_filename(ELS_C),
  49. zend_get_executed_lineno(ELS_C));
  50. }
  51. if (original_sigsegv_handler!=zend_handle_sigsegv) {
  52. original_sigsegv_handler(dummy);
  53. }
  54. }
  55. #endif
  56. static void zend_extension_activator(zend_extension *extension)
  57. {
  58. if (extension->activate) {
  59. extension->activate();
  60. }
  61. }
  62. static void zend_extension_deactivator(zend_extension *extension)
  63. {
  64. if (extension->deactivate) {
  65. extension->deactivate();
  66. }
  67. }
  68. void init_executor(CLS_D ELS_DC)
  69. {
  70. var_uninit(&EG(uninitialized_zval));
  71. var_uninit(&EG(error_zval));
  72. EG(uninitialized_zval).refcount = 1;
  73. EG(uninitialized_zval).is_ref=0;
  74. EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);
  75. EG(error_zval).refcount = 1;
  76. EG(error_zval).is_ref=0;
  77. EG(error_zval_ptr)=&EG(error_zval);
  78. zend_ptr_stack_init(&EG(arg_types_stack));
  79. zend_stack_init(&EG(overloaded_objects_stack));
  80. /* destroys stack frame, therefore makes core dumps worthless */
  81. #if 0
  82. #if ZEND_DEBUG
  83. original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
  84. #endif
  85. #endif
  86. EG(return_value) = &EG(global_return_value);
  87. var_reset(EG(return_value));
  88. EG(symtable_cache_ptr) = EG(symtable_cache)-1;
  89. EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1;
  90. EG(no_extensions)=0;
  91. EG(function_table) = CG(function_table);
  92. EG(class_table) = CG(class_table);
  93. zend_ptr_stack_init(&EG(argument_stack));
  94. EG(main_op_array) = NULL;
  95. zend_hash_init(&EG(symbol_table), 50, NULL, PVAL_PTR_DTOR, 0);
  96. EG(active_symbol_table) = &EG(symbol_table);
  97. zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_activator);
  98. EG(opline_ptr) = NULL;
  99. EG(garbage_ptr) = 0;
  100. EG(suspend_garbage) = 0;
  101. zend_hash_init(&EG(imported_files), 5, NULL, NULL, 0);
  102. }
  103. void shutdown_executor(ELS_D)
  104. {
  105. zval_dtor(&EG(global_return_value));
  106. zend_ptr_stack_destroy(&EG(arg_types_stack));
  107. zend_stack_destroy(&EG(overloaded_objects_stack));
  108. while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
  109. zend_hash_destroy(*EG(symtable_cache_ptr));
  110. efree(*EG(symtable_cache_ptr));
  111. EG(symtable_cache_ptr)--;
  112. }
  113. zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_deactivator);
  114. zend_hash_destroy(&EG(symbol_table));
  115. destroy_resource_list(); /* must be destroyed after the main symbol table is destroyed */
  116. zend_ptr_stack_destroy(&EG(argument_stack));
  117. if (EG(main_op_array)) {
  118. destroy_op_array(EG(main_op_array));
  119. efree(EG(main_op_array));
  120. }
  121. clean_non_persistent_constants();
  122. #if ZEND_DEBUG
  123. signal(SIGSEGV, original_sigsegv_handler);
  124. #endif
  125. while (EG(garbage_ptr)--) {
  126. zval_dtor(EG(garbage)[EG(garbage_ptr)]);
  127. efree(EG(garbage)[EG(garbage_ptr)]);
  128. }
  129. zend_hash_destroy(&EG(imported_files));
  130. }
  131. ZEND_API char *get_active_function_name()
  132. {
  133. ELS_FETCH();
  134. switch(EG(function_state_ptr)->function->type) {
  135. case ZEND_USER_FUNCTION: {
  136. char *function_name = ((zend_op_array *) EG(function_state_ptr)->function)->function_name;
  137. if (function_name) {
  138. return function_name;
  139. } else {
  140. return "main";
  141. }
  142. }
  143. break;
  144. case ZEND_INTERNAL_FUNCTION:
  145. return ((zend_internal_function *) EG(function_state_ptr)->function)->function_name;
  146. break;
  147. default:
  148. return NULL;
  149. }
  150. }
  151. ZEND_API char *zend_get_executed_filename(ELS_D)
  152. {
  153. if (EG(opline_ptr)) {
  154. return active_opline->filename;
  155. } else {
  156. return "[no active file]";
  157. }
  158. }
  159. ZEND_API uint zend_get_executed_lineno(ELS_D)
  160. {
  161. if (EG(opline_ptr)) {
  162. return active_opline->lineno;
  163. } else {
  164. return 0;
  165. }
  166. }
  167. ZEND_API inline void safe_free_zval_ptr(zval *p)
  168. {
  169. ELS_FETCH();
  170. if (p!=EG(uninitialized_zval_ptr)) {
  171. efree(p);
  172. }
  173. }
  174. ZEND_API int _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC)
  175. {
  176. #if DEBUG_ZEND>=2
  177. printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, (*zval_ptr)->refcount, (*zval_ptr)->refcount-1);
  178. #endif
  179. (*zval_ptr)->refcount--;
  180. if ((*zval_ptr)->refcount==0) {
  181. zval_dtor(*zval_ptr);
  182. safe_free_zval_ptr(*zval_ptr);
  183. }
  184. return 1;
  185. }
  186. ZEND_API inline int i_zend_is_true(zval *op)
  187. {
  188. int result;
  189. switch (op->type) {
  190. case IS_LONG:
  191. case IS_BOOL:
  192. case IS_RESOURCE:
  193. result = (op->value.lval?1:0);
  194. break;
  195. case IS_DOUBLE:
  196. result = (op->value.dval ? 1 : 0);
  197. break;
  198. case IS_STRING:
  199. if (op->value.str.len == 0
  200. || (op->value.str.len==1 && op->value.str.val[0]=='0')) {
  201. result = 0;
  202. } else {
  203. result = 1;
  204. }
  205. break;
  206. case IS_ARRAY:
  207. result = (zend_hash_num_elements(op->value.ht)?1:0);
  208. break;
  209. case IS_OBJECT:
  210. result = (zend_hash_num_elements(op->value.obj.properties)?1:0);
  211. break;
  212. default:
  213. result = 0;
  214. break;
  215. }
  216. return result;
  217. }
  218. ZEND_API int zend_is_true(zval *op)
  219. {
  220. return i_zend_is_true(op);
  221. }
  222. ZEND_API int zval_update_constant(zval **pp)
  223. {
  224. zval *p = *pp;
  225. if (p->type == IS_CONSTANT) {
  226. zval c;
  227. int refcount = p->refcount;
  228. if (!zend_get_constant(p->value.str.val, p->value.str.len, &c)) {
  229. zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
  230. p->value.str.val,
  231. p->value.str.val);
  232. p->type = IS_STRING;
  233. } else {
  234. STR_FREE(p->value.str.val);
  235. *p = c;
  236. }
  237. INIT_PZVAL(p);
  238. p->refcount = refcount;
  239. } else if (p->type == IS_ARRAY) {
  240. zend_hash_apply(p->value.ht, (int (*)(void *)) zval_update_constant);
  241. }
  242. return 0;
  243. }
  244. int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval *params[])
  245. {
  246. zval ***params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
  247. int i;
  248. int ex_retval;
  249. for (i=0; i<param_count; i++) {
  250. params_array[i] = &params[i];
  251. }
  252. ex_retval = call_user_function_ex(function_table, object, function_name, retval, param_count, params_array, 1);
  253. efree(params_array);
  254. return ex_retval;
  255. }
  256. int call_user_function_ex(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval **params[], int no_separation)
  257. {
  258. int i;
  259. zval *original_return_value;
  260. HashTable *calling_symbol_table;
  261. zend_function_state function_state;
  262. zend_function_state *original_function_state_ptr;
  263. zend_op_array *original_op_array;
  264. zend_op **original_opline_ptr;
  265. ELS_FETCH();
  266. if (object) {
  267. if (object->type != IS_OBJECT) {
  268. return FAILURE;
  269. }
  270. function_table = &object->value.obj.ce->function_table;
  271. }
  272. original_function_state_ptr = EG(function_state_ptr);
  273. zend_str_tolower(function_name->value.str.val, function_name->value.str.len);
  274. if (zend_hash_find(function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function_state.function)==FAILURE) {
  275. return FAILURE;
  276. }
  277. for (i=0; i<param_count; i++) {
  278. zval *param;
  279. if (function_state.function->common.arg_types
  280. && i<function_state.function->common.arg_types[0]
  281. && function_state.function->common.arg_types[i+1]==BYREF_FORCE
  282. && !PZVAL_IS_REF(*params[i])) {
  283. if ((*params[i])->refcount>1) {
  284. zval *new_zval;
  285. if (no_separation) {
  286. return FAILURE;
  287. }
  288. new_zval = (zval *) emalloc(sizeof(zval));
  289. *new_zval = **params[i];
  290. zval_copy_ctor(new_zval);
  291. new_zval->refcount = 1;
  292. (*params[i])->refcount--;
  293. *params[i] = new_zval;
  294. }
  295. (*params[i])->refcount++;
  296. (*params[i])->is_ref = 1;
  297. param = *params[i];
  298. } else if (*params[i] != &EG(uninitialized_zval)) {
  299. (*params[i])->refcount++;
  300. param = *params[i];
  301. } else {
  302. param = (zval *) emalloc(sizeof(zval));
  303. *param = **(params[i]);
  304. INIT_PZVAL(param);
  305. }
  306. zend_ptr_stack_push(&EG(argument_stack), param);
  307. }
  308. zend_ptr_stack_push(&EG(argument_stack), (void *) (long) param_count);
  309. var_uninit(retval);
  310. if (function_state.function->type == ZEND_USER_FUNCTION) {
  311. calling_symbol_table = EG(active_symbol_table);
  312. EG(active_symbol_table) = (HashTable *) emalloc(sizeof(HashTable));
  313. zend_hash_init(EG(active_symbol_table), 0, NULL, PVAL_PTR_DTOR, 0);
  314. if (object) {
  315. zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr;
  316. var_uninit(dummy);
  317. INIT_PZVAL(dummy);
  318. zend_hash_update_ptr(EG(active_symbol_table), "this", sizeof("this"), dummy, sizeof(zval *), (void **) &this_ptr);
  319. zend_assign_to_variable_reference(NULL, this_ptr, &object, NULL ELS_CC);
  320. }
  321. original_return_value = EG(return_value);
  322. original_op_array = EG(active_op_array);
  323. EG(return_value) = retval;
  324. EG(active_op_array) = (zend_op_array *) function_state.function;
  325. original_opline_ptr = EG(opline_ptr);
  326. zend_execute(EG(active_op_array) ELS_CC);
  327. zend_hash_destroy(EG(active_symbol_table));
  328. efree(EG(active_symbol_table));
  329. EG(active_symbol_table) = calling_symbol_table;
  330. EG(active_op_array) = original_op_array;
  331. EG(return_value)=original_return_value;
  332. EG(opline_ptr) = original_opline_ptr;
  333. } else {
  334. ((zend_internal_function *) function_state.function)->handler(param_count, retval, &EG(regular_list), &EG(persistent_list), object, 1);
  335. }
  336. zend_ptr_stack_clear_multiple(ELS_C);
  337. EG(function_state_ptr) = original_function_state_ptr;
  338. return SUCCESS;
  339. }
  340. ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC)
  341. {
  342. zval pv;
  343. zend_op_array *new_op_array;
  344. zend_op_array *original_active_op_array = EG(active_op_array);
  345. zend_function_state *original_function_state_ptr = EG(function_state_ptr);
  346. int original_handle_op_arrays;
  347. if (retval) {
  348. pv.value.str.len = strlen(str)+sizeof("return ;")-1;
  349. pv.value.str.val = emalloc(pv.value.str.len+1);
  350. strcpy(pv.value.str.val, "return ");
  351. strcat(pv.value.str.val, str);
  352. strcat(pv.value.str.val, " ;");
  353. } else {
  354. pv.value.str.len = strlen(str);
  355. pv.value.str.val = estrndup(str, pv.value.str.len);
  356. }
  357. pv.type = IS_STRING;
  358. /*printf("Evaluating '%s'\n", pv.value.str.val);*/
  359. original_handle_op_arrays = CG(handle_op_arrays);
  360. CG(handle_op_arrays) = 0;
  361. new_op_array = compile_string(&pv CLS_CC);
  362. CG(handle_op_arrays) = original_handle_op_arrays;
  363. if (new_op_array) {
  364. zval dummy_retval;
  365. zval *original_return_value = EG(return_value);
  366. zend_op **original_opline_ptr = EG(opline_ptr);
  367. EG(return_value) = (retval?retval:&dummy_retval);
  368. var_reset(EG(return_value));
  369. EG(active_op_array) = new_op_array;
  370. EG(no_extensions)=1;
  371. zend_execute(new_op_array ELS_CC);
  372. EG(no_extensions)=0;
  373. EG(opline_ptr) = original_opline_ptr;
  374. EG(active_op_array) = original_active_op_array;
  375. EG(function_state_ptr) = original_function_state_ptr;
  376. destroy_op_array(new_op_array);
  377. efree(new_op_array);
  378. EG(return_value) = original_return_value;
  379. if (!retval) {
  380. zval_dtor(&dummy_retval);
  381. }
  382. } else {
  383. printf("Failed executing:\n%s\n", str);
  384. }
  385. zval_dtor(&pv);
  386. }
  387. ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts ELS_DC)
  388. {
  389. zval *variable_ptr = *variable_ptr_ptr;
  390. zval *value_ptr;
  391. if (!value_ptr_ptr) {
  392. zend_error(E_ERROR, "Cannot create references to string offsets nor overloaded objects");
  393. return;
  394. }
  395. value_ptr = *value_ptr_ptr;
  396. if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) {
  397. variable_ptr_ptr = &EG(uninitialized_zval_ptr);
  398. /* } else if (variable_ptr==&EG(uninitialized_zval) || variable_ptr!=value_ptr) { */
  399. } else if (variable_ptr_ptr != value_ptr_ptr) {
  400. variable_ptr->refcount--;
  401. if (variable_ptr->refcount==0) {
  402. zendi_zval_dtor(*variable_ptr);
  403. efree(variable_ptr);
  404. }
  405. if (!PZVAL_IS_REF(value_ptr)) {
  406. /* break it away */
  407. value_ptr->refcount--;
  408. if (value_ptr->refcount>0) {
  409. *value_ptr_ptr = (zval *) emalloc(sizeof(zval));
  410. **value_ptr_ptr = *value_ptr;
  411. value_ptr = *value_ptr_ptr;
  412. zendi_zval_copy_ctor(*value_ptr);
  413. }
  414. value_ptr->refcount = 1;
  415. value_ptr->is_ref = 1;
  416. }
  417. *variable_ptr_ptr = value_ptr;
  418. value_ptr->refcount++;
  419. } else {
  420. /* nothing to do */
  421. }
  422. if (result && (result->op_type != IS_UNUSED)) {
  423. Ts[result->u.var].var.ptr_ptr = variable_ptr_ptr;
  424. SELECTIVE_PZVAL_LOCK(*variable_ptr_ptr, result);
  425. AI_USE_PTR(Ts[result->u.var].var);
  426. }
  427. }
  428. #if SUPPORT_INTERACTIVE
  429. void execute_new_code(CLS_D)
  430. {
  431. ELS_FETCH();
  432. if (!EG(interactive)
  433. || CG(active_op_array)->backpatch_count>0
  434. || CG(active_op_array)->function_name
  435. || CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
  436. return;
  437. }
  438. CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number;
  439. CG(active_op_array)->end_op_number = CG(active_op_array)->last;
  440. EG(active_op_array) = CG(active_op_array);
  441. zend_execute(CG(active_op_array) ELS_CC);
  442. CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number;
  443. }
  444. #endif
  445. /* these are a dedicated, optimized, function, and shouldn't be used for any purpose
  446. * other than by Zend's executor
  447. */
  448. ZEND_API inline void zend_ptr_stack_clear_multiple(ELS_D)
  449. {
  450. void **p = EG(argument_stack).top_element-1;
  451. int delete_count = (ulong) *p;
  452. EG(argument_stack).top -= (delete_count+1);
  453. while (--delete_count>=0) {
  454. zval_ptr_dtor((zval **) --p);
  455. }
  456. EG(argument_stack).top_element = p;
  457. }
  458. ZEND_API int zend_ptr_stack_get_arg(int requested_arg, void **data ELS_DC)
  459. {
  460. void **p = EG(argument_stack).top_element-1;
  461. int arg_count = (ulong) *p;
  462. if (requested_arg>arg_count) {
  463. return FAILURE;
  464. }
  465. *data = (p-arg_count+requested_arg-1);
  466. return SUCCESS;
  467. }