Changeset 986 for trunk/main/xc_utils.c


Ignore:
Timestamp:
2012-07-18T05:13:28+02:00 (2 years ago)
Author:
moo
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.