Changeset 986 in svn for trunk/main/xc_utils.c


Ignore:
Timestamp:
2012-07-18T03:13:28Z (3 years ago)
Author:
Xuefer
Message:

split sandbox source

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/main/xc_utils.c

    r983 r986  
    2727#endif
    2828
    29 static void (*old_zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) = NULL;
    30 static void call_old_zend_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, ...) /* {{{ */
    31 {
    32     va_list args;
    33     va_start(args, format);
    34     old_zend_error_cb(type, error_filename, error_lineno, format, args);
    35 }
    3629/* }}} */
    3730
     
    579572/* }}} */
    580573
    581 typedef struct { /* sandbox {{{ */
    582     ZEND_24(NOTHING, const) char *filename;
    583 
    584     HashTable orig_included_files;
    585     HashTable *tmp_included_files;
    586 
    587 #ifdef HAVE_XCACHE_CONSTANT
    588     HashTable *orig_zend_constants;
    589     HashTable tmp_zend_constants;
    590 #endif
    591     HashTable *orig_function_table;
    592     HashTable *orig_class_table;
    593     HashTable *orig_auto_globals;
    594     HashTable tmp_function_table;
    595     HashTable tmp_class_table;
    596     HashTable tmp_auto_globals;
    597 #ifdef HAVE_XCACHE_CONSTANT
    598     Bucket    *tmp_internal_constant_tail;
    599 #endif
    600     Bucket    *tmp_internal_function_tail;
    601     Bucket    *tmp_internal_class_tail;
    602 
    603 #ifdef XCACHE_ERROR_CACHING
    604     int orig_user_error_handler_error_reporting;
    605     zend_uint compilererror_cnt;
    606     zend_uint compilererror_size;
    607     xc_compilererror_t *compilererrors;
    608 #endif
    609 
    610 #ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES
    611     zend_uint orig_compiler_options;
    612 #endif
    613 } xc_sandbox_t;
    614 
    615 #undef TG
    616 #undef OG
    617 #define TG(x) (sandbox->tmp_##x)
    618 #define OG(x) (sandbox->orig_##x)
    619 /* }}} */
    620 #ifdef XCACHE_ERROR_CACHING
    621 static void xc_sandbox_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) /* {{{ */
    622 {
    623     xc_compilererror_t *compilererror;
    624     xc_sandbox_t *sandbox;
    625     TSRMLS_FETCH();
    626 
    627     sandbox = (xc_sandbox_t *) XG(sandbox);
    628     if (!sandbox) {
    629         old_zend_error_cb(type, error_filename, error_lineno, format, args);
    630         return;
    631     }
    632 
    633     switch (type) {
    634 #ifdef E_STRICT
    635     case E_STRICT:
    636 #endif
    637 #ifdef E_DEPRECATED
    638     case E_DEPRECATED:
    639 #endif
    640         if (sandbox->compilererror_cnt <= sandbox->compilererror_size) {
    641             if (sandbox->compilererror_size) {
    642                 sandbox->compilererror_size += 16;
    643                 sandbox->compilererrors = erealloc(sandbox->compilererrors, sandbox->compilererror_size * sizeof(sandbox->compilererrors));
    644             }
    645             else {
    646                 sandbox->compilererror_size = 16;
    647                 sandbox->compilererrors = emalloc(sandbox->compilererror_size * sizeof(sandbox->compilererrors));
    648             }
    649         }
    650         compilererror = &sandbox->compilererrors[sandbox->compilererror_cnt++];
    651         compilererror->type = type;
    652         compilererror->lineno = error_lineno;
    653         compilererror->error_len = vspprintf(&compilererror->error, 0, format, args);
    654         break;
    655 
    656     default: {
    657         /* give up, and user handler is not supported in this case */
    658         zend_uint i;
    659         zend_uint old_lineno = CG(zend_lineno);
    660 
    661         for (i = 0; i < sandbox->compilererror_cnt; i ++) {
    662             compilererror = &sandbox->compilererrors[i];
    663             CG(zend_lineno) = compilererror->lineno;
    664             call_old_zend_error_cb(compilererror->type, error_filename, error_lineno, "%s", compilererror->error);
    665             efree(compilererror->error);
    666         }
    667         if (sandbox->compilererrors) {
    668             efree(sandbox->compilererrors);
    669             sandbox->compilererrors = NULL;
    670         }
    671         sandbox->compilererror_cnt  = 0;
    672         sandbox->compilererror_size = 0;
    673 
    674         CG(zend_lineno) = old_lineno;
    675         old_zend_error_cb(type, error_filename, error_lineno, format, args);
    676         break;
    677     }
    678     }
    679 }
    680 /* }}} */
    681 #endif
    682 #ifdef ZEND_ENGINE_2_1
    683 static zend_bool xc_auto_global_callback(ZEND_24(NOTHING, const) char *name, uint name_len TSRMLS_DC) /* {{{ */
    684 {
    685     return 0;
    686 }
    687 /* }}} */
    688 static int xc_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
    689 {
    690     if (auto_global->auto_global_callback) {
    691         auto_global->armed = 1;
    692         auto_global->auto_global_callback = xc_auto_global_callback;
    693     }
    694     else {
    695         auto_global->armed = 0;
    696     }
    697     return ZEND_HASH_APPLY_KEEP;
    698 }
    699 /* }}} */
    700 #endif
    701 
    702574void xc_hash_copy_if(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, xc_if_func_t checker) /* {{{ */
    703575{
     
    746618}
    747619/* }}} */
    748 static void xc_free_zend_constant(zend_constant *c) /* {{{ */
    749 {
    750     if (!(c->flags & CONST_PERSISTENT)) {
    751         zval_dtor(&c->value);
    752     }
    753     free(ZSTR_V(c->name));
    754 }
    755 /* }}} */
    756620void xc_copy_internal_zend_constants(HashTable *target, HashTable *source) /* {{{ */
    757621{
     
    761625/* }}} */
    762626#endif
    763 
    764 static xc_sandbox_t *xc_sandbox_init(xc_sandbox_t *sandbox, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */
    765 {
    766     HashTable *h;
    767 
    768     assert(sandbox);
    769     memset(sandbox, 0, sizeof(sandbox[0]));
    770 
    771     memcpy(&OG(included_files), &EG(included_files), sizeof(EG(included_files)));
    772 
    773 #ifdef HAVE_XCACHE_CONSTANT
    774     OG(zend_constants) = EG(zend_constants);
    775     EG(zend_constants) = &TG(zend_constants);
    776 #endif
    777 
    778     OG(function_table) = CG(function_table);
    779     CG(function_table) = &TG(function_table);
    780 
    781     OG(class_table) = CG(class_table);
    782     CG(class_table) = &TG(class_table);
    783     EG(class_table) = CG(class_table);
    784 
    785 #ifdef ZEND_ENGINE_2_1
    786     OG(auto_globals) = CG(auto_globals);
    787     CG(auto_globals) = &TG(auto_globals);
    788 #endif
    789 
    790     TG(included_files) = &EG(included_files);
    791 
    792     zend_hash_init_ex(TG(included_files), 5, NULL, NULL, 0, 1);
    793 #ifdef HAVE_XCACHE_CONSTANT
    794     h = OG(zend_constants);
    795     zend_hash_init_ex(&TG(zend_constants),  20, NULL, (dtor_func_t) xc_free_zend_constant, h->persistent, h->bApplyProtection);
    796     xc_copy_internal_zend_constants(&TG(zend_constants), &XG(internal_constant_table));
    797     TG(internal_constant_tail) = TG(zend_constants).pListTail;
    798 #endif
    799     h = OG(function_table);
    800     zend_hash_init_ex(&TG(function_table), 128, NULL, ZEND_FUNCTION_DTOR, h->persistent, h->bApplyProtection);
    801     {
    802         zend_function tmp_func;
    803         zend_hash_copy(&TG(function_table), &XG(internal_function_table), NULL, (void *) &tmp_func, sizeof(tmp_func));
    804     }
    805     TG(internal_function_tail) = TG(function_table).pListTail;
    806 
    807     h = OG(class_table);
    808     zend_hash_init_ex(&TG(class_table),     16, NULL, ZEND_CLASS_DTOR, h->persistent, h->bApplyProtection);
    809 #if 0 && TODO
    810     {
    811         xc_cest_t tmp_cest;
    812         zend_hash_copy(&TG(class_table), &XG(internal_class_table), NULL, (void *) &tmp_cest, sizeof(tmp_cest));
    813     }
    814 #endif
    815     TG(internal_class_tail) = TG(class_table).pListTail;
    816 
    817 #ifdef ZEND_ENGINE_2_1
    818     /* shallow copy, don't destruct */
    819     h = OG(auto_globals);
    820     zend_hash_init_ex(&TG(auto_globals),     8, NULL,           NULL, h->persistent, h->bApplyProtection);
    821     {
    822         zend_auto_global tmp_autoglobal;
    823 
    824         zend_hash_copy(&TG(auto_globals), OG(auto_globals), NULL, (void *) &tmp_autoglobal, sizeof(tmp_autoglobal));
    825         zend_hash_apply(&TG(auto_globals), (apply_func_t) xc_auto_global_arm TSRMLS_CC);
    826     }
    827 #endif
    828 
    829     sandbox->filename = filename;
    830 
    831 #ifdef XCACHE_ERROR_CACHING
    832     sandbox->orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting);
    833     EG(user_error_handler_error_reporting) = 0;
    834 
    835     sandbox->compilererror_cnt  = 0;
    836     sandbox->compilererror_size = 0;
    837 #endif
    838 
    839 #ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES
    840     sandbox->orig_compiler_options = CG(compiler_options);
    841     /* Using ZEND_COMPILE_IGNORE_INTERNAL_CLASSES for ZEND_FETCH_CLASS_RT_NS_CHECK
    842      */
    843     CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES | ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_DELAYED_BINDING;
    844 #endif
    845 
    846     XG(sandbox) = (void *) sandbox;
    847     return sandbox;
    848 }
    849 /* }}} */
    850 #ifndef ZEND_COMPILE_DELAYED_BINDING
    851 static void xc_early_binding_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */
    852 {
    853     xc_sandbox_t *sandbox = (xc_sandbox_t *) data;
    854     xc_do_early_binding(CG(active_op_array), OG(class_table), oplineno TSRMLS_CC);
    855 }
    856 /* }}} */
    857 #endif
    858 static void xc_sandbox_install(xc_sandbox_t *sandbox TSRMLS_DC) /* {{{ */
    859 {
    860     zend_uint i;
    861     Bucket *b;
    862 
    863 #ifdef HAVE_XCACHE_CONSTANT
    864     for (b = TG(zend_constants).pListHead; b != NULL && b != TG(internal_constant_tail); b = b->pListNext) {
    865         zend_constant *c = (zend_constant*) b->pData;
    866         xc_free_zend_constant(c);
    867     }
    868 
    869     b = TG(internal_constant_tail) ? TG(internal_constant_tail)->pListNext : TG(zend_constants).pListHead;
    870     /* install constants */
    871     while (b != NULL) {
    872         zend_constant *c = (zend_constant*) b->pData;
    873         xc_install_constant(sandbox->filename, c,
    874                 BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC);
    875         b = b->pListNext;
    876     }
    877 #endif
    878 
    879     b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
    880     /* install function */
    881     while (b != NULL) {
    882         zend_function *func = (zend_function*) b->pData;
    883         xc_install_function(sandbox->filename, func,
    884                 BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC);
    885         b = b->pListNext;
    886     }
    887 
    888     b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
    889     /* install class */
    890     while (b != NULL) {
    891         xc_install_class(sandbox->filename, (xc_cest_t*) b->pData, -1,
    892                 BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC);
    893         b = b->pListNext;
    894     }
    895 
    896 #ifdef ZEND_ENGINE_2_1
    897     /* trigger auto_globals jit */
    898     for (b = TG(auto_globals).pListHead; b != NULL; b = b->pListNext) {
    899         zend_auto_global *auto_global = (zend_auto_global *) b->pData;
    900         /* check if actived */
    901         if (auto_global->auto_global_callback && !auto_global->armed) {
    902             zend_u_is_auto_global(BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), auto_global->name_len TSRMLS_CC);
    903         }
    904     }
    905 #endif
    906 
    907 #ifdef ZEND_COMPILE_DELAYED_BINDING
    908     zend_do_delayed_early_binding(CG(active_op_array) TSRMLS_CC);
    909 #else
    910     xc_undo_pass_two(CG(active_op_array) TSRMLS_CC);
    911     xc_foreach_early_binding_class(CG(active_op_array), xc_early_binding_cb, (void *) sandbox TSRMLS_CC);
    912     xc_redo_pass_two(CG(active_op_array) TSRMLS_CC);
    913 #endif
    914 
    915 #ifdef XCACHE_ERROR_CACHING
    916     /* restore trigger errors */
    917     for (i = 0; i < sandbox->compilererror_cnt; i ++) {
    918         xc_compilererror_t *error = &sandbox->compilererrors[i];
    919         CG(zend_lineno) = error->lineno;
    920         zend_error(error->type, "%s", error->error);
    921     }
    922     CG(zend_lineno) = 0;
    923 #endif
    924 
    925     i = 1;
    926     /* still needed because in zend_language_scanner.l, require()/include() check file_handle.handle.stream.handle */
    927     zend_hash_add(&OG(included_files), sandbox->filename, strlen(sandbox->filename) + 1, (void *)&i, sizeof(int), NULL);
    928 }
    929 /* }}} */
    930 static void xc_sandbox_free(xc_sandbox_t *sandbox, zend_op_array *op_array TSRMLS_DC) /* {{{ */
    931 {
    932     XG(sandbox) = NULL;
    933 #ifdef XCACHE_ERROR_CACHING
    934     EG(user_error_handler_error_reporting) = sandbox->orig_user_error_handler_error_reporting;
    935 #endif
    936 
    937     /* restore first first install function/class */
    938 #ifdef HAVE_XCACHE_CONSTANT
    939     EG(zend_constants) = OG(zend_constants);
    940 #endif
    941     CG(function_table) = OG(function_table);
    942     CG(class_table)    = OG(class_table);
    943     EG(class_table)    = CG(class_table);
    944 #ifdef ZEND_ENGINE_2_1
    945     CG(auto_globals)   = OG(auto_globals);
    946 #endif
    947 
    948     if (op_array) {
    949         zend_op_array *old_active_op_array = CG(active_op_array);
    950         CG(in_compilation)    = 1;
    951         CG(compiled_filename) = ZEND_24(NOTHING, (char *)) sandbox->filename;
    952         CG(zend_lineno)       = 0;
    953 
    954         CG(active_op_array) = op_array;
    955         xc_sandbox_install(sandbox TSRMLS_CC);
    956         CG(active_op_array) = old_active_op_array;
    957 
    958         CG(in_compilation)    = 0;
    959         CG(compiled_filename) = NULL;
    960 
    961         /* no free as it's installed */
    962 #ifdef HAVE_XCACHE_CONSTANT
    963         TG(zend_constants).pDestructor = NULL;
    964 #endif
    965         TG(function_table).pDestructor = NULL;
    966         TG(class_table).pDestructor = NULL;
    967     }
    968 
    969     /* destroy all the tmp */
    970 #ifdef HAVE_XCACHE_CONSTANT
    971     zend_hash_destroy(&TG(zend_constants));
    972 #endif
    973     zend_hash_destroy(&TG(function_table));
    974     zend_hash_destroy(&TG(class_table));
    975 #ifdef ZEND_ENGINE_2_1
    976     zend_hash_destroy(&TG(auto_globals));
    977 #endif
    978     zend_hash_destroy(TG(included_files));
    979 
    980     /* restore orig here, as EG/CG holded tmp before */
    981     memcpy(&EG(included_files), &OG(included_files), sizeof(EG(included_files)));
    982 
    983 #ifdef XCACHE_ERROR_CACHING
    984     if (sandbox->compilererrors) {
    985         zend_uint i;
    986         for (i = 0; i < sandbox->compilererror_cnt; i ++) {
    987             efree(sandbox->compilererrors[i].error);
    988         }
    989         efree(sandbox->compilererrors);
    990     }
    991 #endif
    992 
    993 #ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES
    994     CG(compiler_options) = sandbox->orig_compiler_options;
    995 #endif
    996 }
    997 /* }}} */
    998 zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */
    999 {
    1000     xc_sandbox_t sandbox;
    1001     zend_op_array *op_array = NULL;
    1002     zend_bool catched = 0;
    1003 
    1004     memset(&sandbox, 0, sizeof(sandbox));
    1005     zend_try {
    1006         xc_sandbox_init(&sandbox, filename TSRMLS_CC);
    1007         op_array = sandboxed_func(data TSRMLS_CC);
    1008     } zend_catch {
    1009         catched = 1;
    1010     } zend_end_try();
    1011 
    1012     xc_sandbox_free(&sandbox, op_array TSRMLS_CC);
    1013     if (catched) {
    1014         zend_bailout();
    1015     }
    1016     return op_array;
    1017 }
    1018 /* {{{ */
    1019 const Bucket *xc_sandbox_user_function_begin(TSRMLS_D) /* {{{ */
    1020 {
    1021     xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox);
    1022     assert(sandbox);
    1023     return TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead;
    1024 }
    1025 /* {{{ */
    1026 const Bucket *xc_sandbox_user_class_begin(TSRMLS_D) /* {{{ */
    1027 {
    1028     xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox);
    1029     assert(sandbox);
    1030     return TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead;
    1031 }
    1032 /* {{{ */
    1033 #ifdef XCACHE_ERROR_CACHING
    1034 xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D) /* {{{ */
    1035 {
    1036     xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox);
    1037     assert(sandbox);
    1038     return sandbox->compilererrors;
    1039 }
    1040 /* }}} */
    1041 zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D) /* {{{ */
    1042 {
    1043     xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox);
    1044     assert(sandbox);
    1045     return sandbox->compilererror_cnt;
    1046 }
    1047 /* }}} */
    1048 #endif
    1049 
    1050 int xc_vtrace(const char *fmt, va_list args) /* {{{ */
    1051 {
    1052     return vfprintf(stderr, fmt, args);
    1053 }
    1054 /* }}} */
    1055 int xc_trace(const char *fmt, ...) /* {{{ */
    1056 {
    1057     va_list args;
    1058     int ret;
    1059 
    1060     va_start(args, fmt);
    1061     ret = xc_vtrace(fmt, args);
    1062     va_end(args);
    1063     return ret;
    1064 }
    1065 /* }}} */
    1066 
    1067 #ifndef ZEND_ENGINE_2_3
    1068 #include "ext/standard/php_string.h"
    1069 size_t xc_dirname(char *path, size_t len) /* {{{ */
    1070 {
    1071 #ifdef ZEND_ENGINE_2
    1072     return php_dirname(path, len);
    1073 #else
    1074     php_dirname(path, len);
    1075     return strlen(path);
    1076 #endif
    1077 }
    1078 /* }}} */
    1079 
    1080 long xc_atol(const char *str, int str_len) /* {{{ */
    1081 {
    1082     long retval;
    1083 
    1084     if (!str_len) {
    1085         str_len = strlen(str);
    1086     }
    1087 
    1088     retval = strtol(str, NULL, 0);
    1089     if (str_len > 0) {
    1090         switch (str[str_len - 1]) {
    1091         case 'g':
    1092         case 'G':
    1093             retval *= 1024;
    1094             /* break intentionally missing */
    1095         case 'm':
    1096         case 'M':
    1097             retval *= 1024;
    1098             /* break intentionally missing */
    1099         case 'k':
    1100         case 'K':
    1101             retval *= 1024;
    1102             break;
    1103         }
    1104     }
    1105 
    1106     return retval;
    1107 }
    1108 /* }}} */
    1109 
    1110 #endif
    1111 
    1112 /* init/destroy */
    1113 int xc_util_init(int module_number TSRMLS_DC) /* {{{ */
    1114 {
    1115 #ifdef XCACHE_ERROR_CACHING
    1116     old_zend_error_cb = zend_error_cb;
    1117     zend_error_cb = xc_sandbox_error_cb;
    1118 #endif
    1119 
    1120     return SUCCESS;
    1121 }
    1122 /* }}} */
    1123 void xc_util_destroy() /* {{{ */
    1124 {
    1125 #ifdef XCACHE_ERROR_CACHING
    1126     if (zend_error_cb == xc_sandbox_error_cb) {
    1127         zend_error_cb = old_zend_error_cb;
    1128     }
    1129 #endif
    1130 }
    1131 /* }}} */
    1132 
Note: See TracChangeset for help on using the changeset viewer.