XCache is a fast, stable PHP opcode cacher that has been proven and is now running on production servers under high load. https://xcache.lighttpd.net/
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.
 
 
 
 
 
 

190 lines
4.6 KiB

  1. #include "xc_disassembler.h"
  2. #include "xcache.h"
  3. #include "xc_utils.h"
  4. #include "xc_processor.h"
  5. static void xc_dasm(zval *output, zend_op_array *op_array TSRMLS_DC) /* {{{ */
  6. {
  7. const Bucket *b;
  8. zval *zv, *list;
  9. xc_compile_result_t cr;
  10. int bufsize = 2;
  11. char *buf;
  12. xc_dasm_t dasm;
  13. xc_compile_result_init_cur(&cr, op_array TSRMLS_CC);
  14. xc_apply_op_array(&cr, (apply_func_t) xc_undo_pass_two TSRMLS_CC);
  15. xc_apply_op_array(&cr, (apply_func_t) xc_fix_opcode TSRMLS_CC);
  16. /* go */
  17. array_init(output);
  18. ALLOC_INIT_ZVAL(zv);
  19. array_init(zv);
  20. xc_dasm_zend_op_array(&dasm, zv, op_array TSRMLS_CC);
  21. add_assoc_zval_ex(output, ZEND_STRS("op_array"), zv);
  22. buf = emalloc(bufsize);
  23. ALLOC_INIT_ZVAL(list);
  24. array_init(list);
  25. for (b = xc_sandbox_user_function_begin(TSRMLS_C); b; b = b->pListNext) {
  26. int keysize, keyLength;
  27. ALLOC_INIT_ZVAL(zv);
  28. array_init(zv);
  29. xc_dasm_zend_function(&dasm, zv, b->pData TSRMLS_CC);
  30. keysize = BUCKET_KEY_SIZE(b) + 2;
  31. if (keysize > bufsize) {
  32. do {
  33. bufsize *= 2;
  34. } while (keysize > bufsize);
  35. buf = erealloc(buf, bufsize);
  36. }
  37. memcpy(buf, BUCKET_KEY_S(b), keysize);
  38. buf[keysize - 2] = buf[keysize - 1] = ""[0];
  39. keyLength = b->nKeyLength;
  40. #ifdef IS_UNICODE
  41. if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
  42. if (buf[0] == ""[0] && buf[1] == ""[0]) {
  43. keyLength ++;
  44. }
  45. } else
  46. #endif
  47. {
  48. if (buf[0] == ""[0]) {
  49. keyLength ++;
  50. }
  51. }
  52. add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
  53. }
  54. add_assoc_zval_ex(output, ZEND_STRS("function_table"), list);
  55. ALLOC_INIT_ZVAL(list);
  56. array_init(list);
  57. for (b = xc_sandbox_user_class_begin(TSRMLS_C); b; b = b->pListNext) {
  58. int keysize, keyLength;
  59. ALLOC_INIT_ZVAL(zv);
  60. array_init(zv);
  61. xc_dasm_zend_class_entry(&dasm, zv, CestToCePtr(*(xc_cest_t *)b->pData) TSRMLS_CC);
  62. keysize = BUCKET_KEY_SIZE(b) + 2;
  63. if (keysize > bufsize) {
  64. do {
  65. bufsize *= 2;
  66. } while (keysize > bufsize);
  67. buf = erealloc(buf, bufsize);
  68. }
  69. memcpy(buf, BUCKET_KEY_S(b), keysize);
  70. buf[keysize - 2] = buf[keysize - 1] = ""[0];
  71. keyLength = b->nKeyLength;
  72. #ifdef IS_UNICODE
  73. if (BUCKET_KEY_TYPE(b) == IS_UNICODE) {
  74. if (buf[0] == ""[0] && buf[1] == ""[0]) {
  75. keyLength ++;
  76. }
  77. } else
  78. #endif
  79. {
  80. if (buf[0] == ""[0]) {
  81. keyLength ++;
  82. }
  83. }
  84. add_u_assoc_zval_ex(list, BUCKET_KEY_TYPE(b), ZSTR(buf), keyLength, zv);
  85. }
  86. efree(buf);
  87. add_assoc_zval_ex(output, ZEND_STRS("class_table"), list);
  88. /*xc_apply_op_array(&cr, (apply_func_t) xc_redo_pass_two TSRMLS_CC);*/
  89. xc_compile_result_free(&cr);
  90. }
  91. /* }}} */
  92. typedef struct xc_dasm_sandboxed_t { /* {{{ */
  93. enum Type {
  94. xc_dasm_file_t
  95. , xc_dasm_string_t
  96. } type;
  97. union {
  98. zval *zfilename;
  99. struct {
  100. zval *source;
  101. char *eval_name;
  102. } compile_string;
  103. } input;
  104. zval *output;
  105. } xc_dasm_sandboxed_t; /* {{{ */
  106. zend_op_array *xc_dasm_sandboxed(void *data TSRMLS_DC)
  107. {
  108. zend_bool catched = 0;
  109. zend_op_array *op_array = NULL;
  110. xc_dasm_sandboxed_t *sandboxed_dasm = (xc_dasm_sandboxed_t *) data;
  111. zend_try {
  112. if (sandboxed_dasm->type == xc_dasm_file_t) {
  113. op_array = compile_filename(ZEND_REQUIRE, sandboxed_dasm->input.zfilename TSRMLS_CC);
  114. }
  115. else {
  116. op_array = compile_string(sandboxed_dasm->input.compile_string.source, sandboxed_dasm->input.compile_string.eval_name TSRMLS_CC);
  117. }
  118. } zend_catch {
  119. catched = 1;
  120. } zend_end_try();
  121. if (catched || !op_array) {
  122. #define return_value sandboxed_dasm->output
  123. RETVAL_FALSE;
  124. #undef return_value
  125. return NULL;
  126. }
  127. xc_dasm(sandboxed_dasm->output, op_array TSRMLS_CC);
  128. /* free */
  129. #ifdef ZEND_ENGINE_2
  130. destroy_op_array(op_array TSRMLS_CC);
  131. #else
  132. destroy_op_array(op_array);
  133. #endif
  134. efree(op_array);
  135. return NULL;
  136. } /* }}} */
  137. void xc_dasm_string(zval *output, zval *source TSRMLS_DC) /* {{{ */
  138. {
  139. xc_dasm_sandboxed_t sandboxed_dasm;
  140. char *eval_name = zend_make_compiled_string_description("runtime-created function" TSRMLS_CC);
  141. sandboxed_dasm.output = output;
  142. sandboxed_dasm.type = xc_dasm_string_t;
  143. sandboxed_dasm.input.compile_string.source = source;
  144. sandboxed_dasm.input.compile_string.eval_name = eval_name;
  145. xc_sandbox(&xc_dasm_sandboxed, (void *) &sandboxed_dasm, eval_name TSRMLS_CC);
  146. efree(eval_name);
  147. }
  148. /* }}} */
  149. void xc_dasm_file(zval *output, const char *filename TSRMLS_DC) /* {{{ */
  150. {
  151. zval *zfilename;
  152. xc_dasm_sandboxed_t sandboxed_dasm;
  153. MAKE_STD_ZVAL(zfilename);
  154. zfilename->value.str.val = estrdup(filename);
  155. zfilename->value.str.len = strlen(filename);
  156. zfilename->type = IS_STRING;
  157. sandboxed_dasm.output = output;
  158. sandboxed_dasm.type = xc_dasm_file_t;
  159. sandboxed_dasm.input.zfilename = zfilename;
  160. xc_sandbox(&xc_dasm_sandboxed, (void *) &sandboxed_dasm, zfilename->value.str.val TSRMLS_CC);
  161. zval_dtor(zfilename);
  162. FREE_ZVAL(zfilename);
  163. }
  164. /* }}} */