From 3f8e65d24a37800301156bc851d3390ad6260f5b Mon Sep 17 00:00:00 2001 From: Xuefer Date: Wed, 18 Jul 2012 03:13:28 +0000 Subject: [PATCH] split sandbox source git-svn-id: svn://svn.lighttpd.net/xcache/trunk@986 c26eb9a1-5813-0410-bd6c-c2e55f420ca7 --- config.m4 | 1 + config.w32 | 1 + main/xc_sandbox.c | 518 ++++++++++++++++++++++++++++++++++++++++++++++ main/xc_sandbox.h | 19 ++ main/xc_utils.c | 506 -------------------------------------------- main/xc_utils.h | 11 - xcache.c | 1 + 7 files changed, 540 insertions(+), 517 deletions(-) create mode 100644 main/xc_sandbox.c create mode 100644 main/xc_sandbox.h diff --git a/config.m4 b/config.m4 index e395f3c..d0234fc 100644 --- a/config.m4 +++ b/config.m4 @@ -29,6 +29,7 @@ if test "$PHP_XCACHE" != "no"; then main/xc_mem.c \ main/xc_opcode_spec.c \ main/xc_processor.c \ + main/xc_sandbox.c \ main/xc_shm.c \ main/xc_shm_mmap.c \ main/xc_utils.c \ diff --git a/config.w32 b/config.w32 index e2717ea..a56bbf1 100644 --- a/config.w32 +++ b/config.w32 @@ -17,6 +17,7 @@ if (PHP_XCACHE != "no") { main/xc_lock.c \ main/xc_mem.c \ main/xc_opcode_spec.c \ + main/xc_sandbox.c \ main/xc_shm.c \ main/xc_shm_mmap.c \ main/xc_utils.c \ diff --git a/main/xc_sandbox.c b/main/xc_sandbox.c new file mode 100644 index 0000000..debd98a --- /dev/null +++ b/main/xc_sandbox.c @@ -0,0 +1,518 @@ + +#include "xcache.h" +#include "xc_sandbox.h" +#include "xc_utils.h" +#include "xcache_globals.h" + +/* utilities used by sandbox */ +static void (*old_zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) = NULL; +static void call_old_zend_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, ...) /* {{{ */ +{ + va_list args; + va_start(args, format); + old_zend_error_cb(type, error_filename, error_lineno, format, args); +} +/* }}} */ +#ifdef ZEND_ENGINE_2_1 +static zend_bool xc_auto_global_callback(ZEND_24(NOTHING, const) char *name, uint name_len TSRMLS_DC) /* {{{ */ +{ + return 0; +} +/* }}} */ +static int xc_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */ +{ + if (auto_global->auto_global_callback) { + auto_global->armed = 1; + auto_global->auto_global_callback = xc_auto_global_callback; + } + else { + auto_global->armed = 0; + } + return ZEND_HASH_APPLY_KEEP; +} +/* }}} */ +#endif + +#ifdef HAVE_XCACHE_CONSTANT +static void xc_free_zend_constant(zend_constant *c) /* {{{ */ +{ + if (!(c->flags & CONST_PERSISTENT)) { + zval_dtor(&c->value); + } + free(ZSTR_V(c->name)); +} +/* }}} */ +#endif + +typedef struct { /* sandbox {{{ */ + ZEND_24(NOTHING, const) char *filename; + + HashTable orig_included_files; + HashTable *tmp_included_files; + +#ifdef HAVE_XCACHE_CONSTANT + HashTable *orig_zend_constants; + HashTable tmp_zend_constants; +#endif + HashTable *orig_function_table; + HashTable *orig_class_table; + HashTable *orig_auto_globals; + HashTable tmp_function_table; + HashTable tmp_class_table; + HashTable tmp_auto_globals; +#ifdef HAVE_XCACHE_CONSTANT + Bucket *tmp_internal_constant_tail; +#endif + Bucket *tmp_internal_function_tail; + Bucket *tmp_internal_class_tail; + +#ifdef XCACHE_ERROR_CACHING + int orig_user_error_handler_error_reporting; + zend_uint compilererror_cnt; + zend_uint compilererror_size; + xc_compilererror_t *compilererrors; +#endif + +#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES + zend_uint orig_compiler_options; +#endif +} xc_sandbox_t; + +#undef TG +#undef OG +#define TG(x) (sandbox->tmp_##x) +#define OG(x) (sandbox->orig_##x) +/* }}} */ +#ifdef XCACHE_ERROR_CACHING +static void xc_sandbox_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) /* {{{ */ +{ + xc_compilererror_t *compilererror; + xc_sandbox_t *sandbox; + TSRMLS_FETCH(); + + sandbox = (xc_sandbox_t *) XG(sandbox); + if (!sandbox) { + old_zend_error_cb(type, error_filename, error_lineno, format, args); + return; + } + + switch (type) { +#ifdef E_STRICT + case E_STRICT: +#endif +#ifdef E_DEPRECATED + case E_DEPRECATED: +#endif + if (sandbox->compilererror_cnt <= sandbox->compilererror_size) { + if (sandbox->compilererror_size) { + sandbox->compilererror_size += 16; + sandbox->compilererrors = erealloc(sandbox->compilererrors, sandbox->compilererror_size * sizeof(sandbox->compilererrors)); + } + else { + sandbox->compilererror_size = 16; + sandbox->compilererrors = emalloc(sandbox->compilererror_size * sizeof(sandbox->compilererrors)); + } + } + compilererror = &sandbox->compilererrors[sandbox->compilererror_cnt++]; + compilererror->type = type; + compilererror->lineno = error_lineno; + compilererror->error_len = vspprintf(&compilererror->error, 0, format, args); + break; + + default: { + /* give up, and user handler is not supported in this case */ + zend_uint i; + zend_uint old_lineno = CG(zend_lineno); + + for (i = 0; i < sandbox->compilererror_cnt; i ++) { + compilererror = &sandbox->compilererrors[i]; + CG(zend_lineno) = compilererror->lineno; + call_old_zend_error_cb(compilererror->type, error_filename, error_lineno, "%s", compilererror->error); + efree(compilererror->error); + } + if (sandbox->compilererrors) { + efree(sandbox->compilererrors); + sandbox->compilererrors = NULL; + } + sandbox->compilererror_cnt = 0; + sandbox->compilererror_size = 0; + + CG(zend_lineno) = old_lineno; + old_zend_error_cb(type, error_filename, error_lineno, format, args); + break; + } + } +} +/* }}} */ +#endif + +static xc_sandbox_t *xc_sandbox_init(xc_sandbox_t *sandbox, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */ +{ + HashTable *h; + + assert(sandbox); + memset(sandbox, 0, sizeof(sandbox[0])); + + memcpy(&OG(included_files), &EG(included_files), sizeof(EG(included_files))); + +#ifdef HAVE_XCACHE_CONSTANT + OG(zend_constants) = EG(zend_constants); + EG(zend_constants) = &TG(zend_constants); +#endif + + OG(function_table) = CG(function_table); + CG(function_table) = &TG(function_table); + + OG(class_table) = CG(class_table); + CG(class_table) = &TG(class_table); + EG(class_table) = CG(class_table); + +#ifdef ZEND_ENGINE_2_1 + OG(auto_globals) = CG(auto_globals); + CG(auto_globals) = &TG(auto_globals); +#endif + + TG(included_files) = &EG(included_files); + + zend_hash_init_ex(TG(included_files), 5, NULL, NULL, 0, 1); +#ifdef HAVE_XCACHE_CONSTANT + h = OG(zend_constants); + zend_hash_init_ex(&TG(zend_constants), 20, NULL, (dtor_func_t) xc_free_zend_constant, h->persistent, h->bApplyProtection); + xc_copy_internal_zend_constants(&TG(zend_constants), &XG(internal_constant_table)); + TG(internal_constant_tail) = TG(zend_constants).pListTail; +#endif + h = OG(function_table); + zend_hash_init_ex(&TG(function_table), 128, NULL, ZEND_FUNCTION_DTOR, h->persistent, h->bApplyProtection); + { + zend_function tmp_func; + zend_hash_copy(&TG(function_table), &XG(internal_function_table), NULL, (void *) &tmp_func, sizeof(tmp_func)); + } + TG(internal_function_tail) = TG(function_table).pListTail; + + h = OG(class_table); + zend_hash_init_ex(&TG(class_table), 16, NULL, ZEND_CLASS_DTOR, h->persistent, h->bApplyProtection); +#if 0 && TODO + { + xc_cest_t tmp_cest; + zend_hash_copy(&TG(class_table), &XG(internal_class_table), NULL, (void *) &tmp_cest, sizeof(tmp_cest)); + } +#endif + TG(internal_class_tail) = TG(class_table).pListTail; + +#ifdef ZEND_ENGINE_2_1 + /* shallow copy, don't destruct */ + h = OG(auto_globals); + zend_hash_init_ex(&TG(auto_globals), 8, NULL, NULL, h->persistent, h->bApplyProtection); + { + zend_auto_global tmp_autoglobal; + + zend_hash_copy(&TG(auto_globals), OG(auto_globals), NULL, (void *) &tmp_autoglobal, sizeof(tmp_autoglobal)); + zend_hash_apply(&TG(auto_globals), (apply_func_t) xc_auto_global_arm TSRMLS_CC); + } +#endif + + sandbox->filename = filename; + +#ifdef XCACHE_ERROR_CACHING + sandbox->orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting); + EG(user_error_handler_error_reporting) = 0; + + sandbox->compilererror_cnt = 0; + sandbox->compilererror_size = 0; +#endif + +#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES + sandbox->orig_compiler_options = CG(compiler_options); + /* Using ZEND_COMPILE_IGNORE_INTERNAL_CLASSES for ZEND_FETCH_CLASS_RT_NS_CHECK + */ + CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES | ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_DELAYED_BINDING; +#endif + + XG(sandbox) = (void *) sandbox; + return sandbox; +} +/* }}} */ + +#ifndef ZEND_COMPILE_DELAYED_BINDING +static void xc_early_binding_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */ +{ + xc_sandbox_t *sandbox = (xc_sandbox_t *) data; + xc_do_early_binding(CG(active_op_array), OG(class_table), oplineno TSRMLS_CC); +} +/* }}} */ +#endif +static void xc_sandbox_install(xc_sandbox_t *sandbox TSRMLS_DC) /* {{{ */ +{ + zend_uint i; + Bucket *b; + +#ifdef HAVE_XCACHE_CONSTANT + for (b = TG(zend_constants).pListHead; b != NULL && b != TG(internal_constant_tail); b = b->pListNext) { + zend_constant *c = (zend_constant*) b->pData; + xc_free_zend_constant(c); + } + + b = TG(internal_constant_tail) ? TG(internal_constant_tail)->pListNext : TG(zend_constants).pListHead; + /* install constants */ + while (b != NULL) { + zend_constant *c = (zend_constant*) b->pData; + xc_install_constant(sandbox->filename, c, + BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); + b = b->pListNext; + } +#endif + + b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead; + /* install function */ + while (b != NULL) { + zend_function *func = (zend_function*) b->pData; + xc_install_function(sandbox->filename, func, + BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); + b = b->pListNext; + } + + b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead; + /* install class */ + while (b != NULL) { + xc_install_class(sandbox->filename, (xc_cest_t*) b->pData, -1, + BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); + b = b->pListNext; + } + +#ifdef ZEND_ENGINE_2_1 + /* trigger auto_globals jit */ + for (b = TG(auto_globals).pListHead; b != NULL; b = b->pListNext) { + zend_auto_global *auto_global = (zend_auto_global *) b->pData; + /* check if actived */ + if (auto_global->auto_global_callback && !auto_global->armed) { + zend_u_is_auto_global(BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), auto_global->name_len TSRMLS_CC); + } + } +#endif + +#ifdef ZEND_COMPILE_DELAYED_BINDING + zend_do_delayed_early_binding(CG(active_op_array) TSRMLS_CC); +#else + xc_undo_pass_two(CG(active_op_array) TSRMLS_CC); + xc_foreach_early_binding_class(CG(active_op_array), xc_early_binding_cb, (void *) sandbox TSRMLS_CC); + xc_redo_pass_two(CG(active_op_array) TSRMLS_CC); +#endif + +#ifdef XCACHE_ERROR_CACHING + /* restore trigger errors */ + for (i = 0; i < sandbox->compilererror_cnt; i ++) { + xc_compilererror_t *error = &sandbox->compilererrors[i]; + CG(zend_lineno) = error->lineno; + zend_error(error->type, "%s", error->error); + } + CG(zend_lineno) = 0; +#endif + + i = 1; + /* still needed because in zend_language_scanner.l, require()/include() check file_handle.handle.stream.handle */ + zend_hash_add(&OG(included_files), sandbox->filename, strlen(sandbox->filename) + 1, (void *)&i, sizeof(int), NULL); +} +/* }}} */ +static void xc_sandbox_free(xc_sandbox_t *sandbox, zend_op_array *op_array TSRMLS_DC) /* {{{ */ +{ + XG(sandbox) = NULL; +#ifdef XCACHE_ERROR_CACHING + EG(user_error_handler_error_reporting) = sandbox->orig_user_error_handler_error_reporting; +#endif + + /* restore first first install function/class */ +#ifdef HAVE_XCACHE_CONSTANT + EG(zend_constants) = OG(zend_constants); +#endif + CG(function_table) = OG(function_table); + CG(class_table) = OG(class_table); + EG(class_table) = CG(class_table); +#ifdef ZEND_ENGINE_2_1 + CG(auto_globals) = OG(auto_globals); +#endif + + if (op_array) { + zend_op_array *old_active_op_array = CG(active_op_array); + CG(in_compilation) = 1; + CG(compiled_filename) = ZEND_24(NOTHING, (char *)) sandbox->filename; + CG(zend_lineno) = 0; + + CG(active_op_array) = op_array; + xc_sandbox_install(sandbox TSRMLS_CC); + CG(active_op_array) = old_active_op_array; + + CG(in_compilation) = 0; + CG(compiled_filename) = NULL; + + /* no free as it's installed */ +#ifdef HAVE_XCACHE_CONSTANT + TG(zend_constants).pDestructor = NULL; +#endif + TG(function_table).pDestructor = NULL; + TG(class_table).pDestructor = NULL; + } + + /* destroy all the tmp */ +#ifdef HAVE_XCACHE_CONSTANT + zend_hash_destroy(&TG(zend_constants)); +#endif + zend_hash_destroy(&TG(function_table)); + zend_hash_destroy(&TG(class_table)); +#ifdef ZEND_ENGINE_2_1 + zend_hash_destroy(&TG(auto_globals)); +#endif + zend_hash_destroy(TG(included_files)); + + /* restore orig here, as EG/CG holded tmp before */ + memcpy(&EG(included_files), &OG(included_files), sizeof(EG(included_files))); + +#ifdef XCACHE_ERROR_CACHING + if (sandbox->compilererrors) { + zend_uint i; + for (i = 0; i < sandbox->compilererror_cnt; i ++) { + efree(sandbox->compilererrors[i].error); + } + efree(sandbox->compilererrors); + } +#endif + +#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES + CG(compiler_options) = sandbox->orig_compiler_options; +#endif +} +/* }}} */ +zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */ +{ + xc_sandbox_t sandbox; + zend_op_array *op_array = NULL; + zend_bool catched = 0; + + memset(&sandbox, 0, sizeof(sandbox)); + zend_try { + xc_sandbox_init(&sandbox, filename TSRMLS_CC); + op_array = sandboxed_func(data TSRMLS_CC); + } zend_catch { + catched = 1; + } zend_end_try(); + + xc_sandbox_free(&sandbox, op_array TSRMLS_CC); + if (catched) { + zend_bailout(); + } + return op_array; +} +/* {{{ */ +const Bucket *xc_sandbox_user_function_begin(TSRMLS_D) /* {{{ */ +{ + xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); + assert(sandbox); + return TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead; +} +/* {{{ */ +const Bucket *xc_sandbox_user_class_begin(TSRMLS_D) /* {{{ */ +{ + xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); + assert(sandbox); + return TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead; +} +/* {{{ */ +#ifdef XCACHE_ERROR_CACHING +xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D) /* {{{ */ +{ + xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); + assert(sandbox); + return sandbox->compilererrors; +} +/* }}} */ +zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D) /* {{{ */ +{ + xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); + assert(sandbox); + return sandbox->compilererror_cnt; +} +/* }}} */ +#endif + +int xc_vtrace(const char *fmt, va_list args) /* {{{ */ +{ + return vfprintf(stderr, fmt, args); +} +/* }}} */ +int xc_trace(const char *fmt, ...) /* {{{ */ +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = xc_vtrace(fmt, args); + va_end(args); + return ret; +} +/* }}} */ + +#ifndef ZEND_ENGINE_2_3 +#include "ext/standard/php_string.h" +size_t xc_dirname(char *path, size_t len) /* {{{ */ +{ +#ifdef ZEND_ENGINE_2 + return php_dirname(path, len); +#else + php_dirname(path, len); + return strlen(path); +#endif +} +/* }}} */ + +long xc_atol(const char *str, int str_len) /* {{{ */ +{ + long retval; + + if (!str_len) { + str_len = strlen(str); + } + + retval = strtol(str, NULL, 0); + if (str_len > 0) { + switch (str[str_len - 1]) { + case 'g': + case 'G': + retval *= 1024; + /* break intentionally missing */ + case 'm': + case 'M': + retval *= 1024; + /* break intentionally missing */ + case 'k': + case 'K': + retval *= 1024; + break; + } + } + + return retval; +} +/* }}} */ + +#endif + +/* init/destroy */ +int xc_util_init(int module_number TSRMLS_DC) /* {{{ */ +{ +#ifdef XCACHE_ERROR_CACHING + old_zend_error_cb = zend_error_cb; + zend_error_cb = xc_sandbox_error_cb; +#endif + + return SUCCESS; +} +/* }}} */ +void xc_util_destroy() /* {{{ */ +{ +#ifdef XCACHE_ERROR_CACHING + if (zend_error_cb == xc_sandbox_error_cb) { + zend_error_cb = old_zend_error_cb; + } +#endif +} +/* }}} */ + diff --git a/main/xc_sandbox.h b/main/xc_sandbox.h new file mode 100644 index 0000000..9e9f210 --- /dev/null +++ b/main/xc_sandbox.h @@ -0,0 +1,19 @@ +#ifndef _22077CFAC35518969B4416944ACBA159 +#define _22077CFAC35518969B4416944ACBA159 + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/* return op_array to install */ +typedef zend_op_array *(*xc_sandboxed_func_t)(void *data TSRMLS_DC); +zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC); +const Bucket *xc_sandbox_user_function_begin(TSRMLS_D); +const Bucket *xc_sandbox_user_class_begin(TSRMLS_D); +zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D); +#ifdef XCACHE_ERROR_CACHING +xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D); +zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D); +#endif + +#endif /* _22077CFAC35518969B4416944ACBA159 */ diff --git a/main/xc_utils.c b/main/xc_utils.c index 4830c7e..48c53df 100644 --- a/main/xc_utils.c +++ b/main/xc_utils.c @@ -26,13 +26,6 @@ } while(0) #endif -static void (*old_zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) = NULL; -static void call_old_zend_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, ...) /* {{{ */ -{ - va_list args; - va_start(args, format); - old_zend_error_cb(type, error_filename, error_lineno, format, args); -} /* }}} */ xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr, /* {{{ */ @@ -578,127 +571,6 @@ ZESW(xc_cest_t *, void) xc_install_class(ZEND_24(NOTHING, const) char *filename, } /* }}} */ -typedef struct { /* sandbox {{{ */ - ZEND_24(NOTHING, const) char *filename; - - HashTable orig_included_files; - HashTable *tmp_included_files; - -#ifdef HAVE_XCACHE_CONSTANT - HashTable *orig_zend_constants; - HashTable tmp_zend_constants; -#endif - HashTable *orig_function_table; - HashTable *orig_class_table; - HashTable *orig_auto_globals; - HashTable tmp_function_table; - HashTable tmp_class_table; - HashTable tmp_auto_globals; -#ifdef HAVE_XCACHE_CONSTANT - Bucket *tmp_internal_constant_tail; -#endif - Bucket *tmp_internal_function_tail; - Bucket *tmp_internal_class_tail; - -#ifdef XCACHE_ERROR_CACHING - int orig_user_error_handler_error_reporting; - zend_uint compilererror_cnt; - zend_uint compilererror_size; - xc_compilererror_t *compilererrors; -#endif - -#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES - zend_uint orig_compiler_options; -#endif -} xc_sandbox_t; - -#undef TG -#undef OG -#define TG(x) (sandbox->tmp_##x) -#define OG(x) (sandbox->orig_##x) -/* }}} */ -#ifdef XCACHE_ERROR_CACHING -static void xc_sandbox_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) /* {{{ */ -{ - xc_compilererror_t *compilererror; - xc_sandbox_t *sandbox; - TSRMLS_FETCH(); - - sandbox = (xc_sandbox_t *) XG(sandbox); - if (!sandbox) { - old_zend_error_cb(type, error_filename, error_lineno, format, args); - return; - } - - switch (type) { -#ifdef E_STRICT - case E_STRICT: -#endif -#ifdef E_DEPRECATED - case E_DEPRECATED: -#endif - if (sandbox->compilererror_cnt <= sandbox->compilererror_size) { - if (sandbox->compilererror_size) { - sandbox->compilererror_size += 16; - sandbox->compilererrors = erealloc(sandbox->compilererrors, sandbox->compilererror_size * sizeof(sandbox->compilererrors)); - } - else { - sandbox->compilererror_size = 16; - sandbox->compilererrors = emalloc(sandbox->compilererror_size * sizeof(sandbox->compilererrors)); - } - } - compilererror = &sandbox->compilererrors[sandbox->compilererror_cnt++]; - compilererror->type = type; - compilererror->lineno = error_lineno; - compilererror->error_len = vspprintf(&compilererror->error, 0, format, args); - break; - - default: { - /* give up, and user handler is not supported in this case */ - zend_uint i; - zend_uint old_lineno = CG(zend_lineno); - - for (i = 0; i < sandbox->compilererror_cnt; i ++) { - compilererror = &sandbox->compilererrors[i]; - CG(zend_lineno) = compilererror->lineno; - call_old_zend_error_cb(compilererror->type, error_filename, error_lineno, "%s", compilererror->error); - efree(compilererror->error); - } - if (sandbox->compilererrors) { - efree(sandbox->compilererrors); - sandbox->compilererrors = NULL; - } - sandbox->compilererror_cnt = 0; - sandbox->compilererror_size = 0; - - CG(zend_lineno) = old_lineno; - old_zend_error_cb(type, error_filename, error_lineno, format, args); - break; - } - } -} -/* }}} */ -#endif -#ifdef ZEND_ENGINE_2_1 -static zend_bool xc_auto_global_callback(ZEND_24(NOTHING, const) char *name, uint name_len TSRMLS_DC) /* {{{ */ -{ - return 0; -} -/* }}} */ -static int xc_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */ -{ - if (auto_global->auto_global_callback) { - auto_global->armed = 1; - auto_global->auto_global_callback = xc_auto_global_callback; - } - else { - auto_global->armed = 0; - } - return ZEND_HASH_APPLY_KEEP; -} -/* }}} */ -#endif - void xc_hash_copy_if(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, xc_if_func_t checker) /* {{{ */ { Bucket *p; @@ -745,14 +617,6 @@ void xc_zend_constant_dtor(zend_constant *c) /* {{{ */ free(ZSTR_V(c->name)); } /* }}} */ -static void xc_free_zend_constant(zend_constant *c) /* {{{ */ -{ - if (!(c->flags & CONST_PERSISTENT)) { - zval_dtor(&c->value); - } - free(ZSTR_V(c->name)); -} -/* }}} */ void xc_copy_internal_zend_constants(HashTable *target, HashTable *source) /* {{{ */ { zend_constant tmp_const; @@ -760,373 +624,3 @@ void xc_copy_internal_zend_constants(HashTable *target, HashTable *source) /* {{ } /* }}} */ #endif - -static xc_sandbox_t *xc_sandbox_init(xc_sandbox_t *sandbox, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */ -{ - HashTable *h; - - assert(sandbox); - memset(sandbox, 0, sizeof(sandbox[0])); - - memcpy(&OG(included_files), &EG(included_files), sizeof(EG(included_files))); - -#ifdef HAVE_XCACHE_CONSTANT - OG(zend_constants) = EG(zend_constants); - EG(zend_constants) = &TG(zend_constants); -#endif - - OG(function_table) = CG(function_table); - CG(function_table) = &TG(function_table); - - OG(class_table) = CG(class_table); - CG(class_table) = &TG(class_table); - EG(class_table) = CG(class_table); - -#ifdef ZEND_ENGINE_2_1 - OG(auto_globals) = CG(auto_globals); - CG(auto_globals) = &TG(auto_globals); -#endif - - TG(included_files) = &EG(included_files); - - zend_hash_init_ex(TG(included_files), 5, NULL, NULL, 0, 1); -#ifdef HAVE_XCACHE_CONSTANT - h = OG(zend_constants); - zend_hash_init_ex(&TG(zend_constants), 20, NULL, (dtor_func_t) xc_free_zend_constant, h->persistent, h->bApplyProtection); - xc_copy_internal_zend_constants(&TG(zend_constants), &XG(internal_constant_table)); - TG(internal_constant_tail) = TG(zend_constants).pListTail; -#endif - h = OG(function_table); - zend_hash_init_ex(&TG(function_table), 128, NULL, ZEND_FUNCTION_DTOR, h->persistent, h->bApplyProtection); - { - zend_function tmp_func; - zend_hash_copy(&TG(function_table), &XG(internal_function_table), NULL, (void *) &tmp_func, sizeof(tmp_func)); - } - TG(internal_function_tail) = TG(function_table).pListTail; - - h = OG(class_table); - zend_hash_init_ex(&TG(class_table), 16, NULL, ZEND_CLASS_DTOR, h->persistent, h->bApplyProtection); -#if 0 && TODO - { - xc_cest_t tmp_cest; - zend_hash_copy(&TG(class_table), &XG(internal_class_table), NULL, (void *) &tmp_cest, sizeof(tmp_cest)); - } -#endif - TG(internal_class_tail) = TG(class_table).pListTail; - -#ifdef ZEND_ENGINE_2_1 - /* shallow copy, don't destruct */ - h = OG(auto_globals); - zend_hash_init_ex(&TG(auto_globals), 8, NULL, NULL, h->persistent, h->bApplyProtection); - { - zend_auto_global tmp_autoglobal; - - zend_hash_copy(&TG(auto_globals), OG(auto_globals), NULL, (void *) &tmp_autoglobal, sizeof(tmp_autoglobal)); - zend_hash_apply(&TG(auto_globals), (apply_func_t) xc_auto_global_arm TSRMLS_CC); - } -#endif - - sandbox->filename = filename; - -#ifdef XCACHE_ERROR_CACHING - sandbox->orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting); - EG(user_error_handler_error_reporting) = 0; - - sandbox->compilererror_cnt = 0; - sandbox->compilererror_size = 0; -#endif - -#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES - sandbox->orig_compiler_options = CG(compiler_options); - /* Using ZEND_COMPILE_IGNORE_INTERNAL_CLASSES for ZEND_FETCH_CLASS_RT_NS_CHECK - */ - CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES | ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_DELAYED_BINDING; -#endif - - XG(sandbox) = (void *) sandbox; - return sandbox; -} -/* }}} */ -#ifndef ZEND_COMPILE_DELAYED_BINDING -static void xc_early_binding_cb(zend_op *opline, int oplineno, void *data TSRMLS_DC) /* {{{ */ -{ - xc_sandbox_t *sandbox = (xc_sandbox_t *) data; - xc_do_early_binding(CG(active_op_array), OG(class_table), oplineno TSRMLS_CC); -} -/* }}} */ -#endif -static void xc_sandbox_install(xc_sandbox_t *sandbox TSRMLS_DC) /* {{{ */ -{ - zend_uint i; - Bucket *b; - -#ifdef HAVE_XCACHE_CONSTANT - for (b = TG(zend_constants).pListHead; b != NULL && b != TG(internal_constant_tail); b = b->pListNext) { - zend_constant *c = (zend_constant*) b->pData; - xc_free_zend_constant(c); - } - - b = TG(internal_constant_tail) ? TG(internal_constant_tail)->pListNext : TG(zend_constants).pListHead; - /* install constants */ - while (b != NULL) { - zend_constant *c = (zend_constant*) b->pData; - xc_install_constant(sandbox->filename, c, - BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); - b = b->pListNext; - } -#endif - - b = TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead; - /* install function */ - while (b != NULL) { - zend_function *func = (zend_function*) b->pData; - xc_install_function(sandbox->filename, func, - BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); - b = b->pListNext; - } - - b = TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead; - /* install class */ - while (b != NULL) { - xc_install_class(sandbox->filename, (xc_cest_t*) b->pData, -1, - BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), b->nKeyLength, b->h TSRMLS_CC); - b = b->pListNext; - } - -#ifdef ZEND_ENGINE_2_1 - /* trigger auto_globals jit */ - for (b = TG(auto_globals).pListHead; b != NULL; b = b->pListNext) { - zend_auto_global *auto_global = (zend_auto_global *) b->pData; - /* check if actived */ - if (auto_global->auto_global_callback && !auto_global->armed) { - zend_u_is_auto_global(BUCKET_KEY_TYPE(b), ZSTR(BUCKET_KEY_S(b)), auto_global->name_len TSRMLS_CC); - } - } -#endif - -#ifdef ZEND_COMPILE_DELAYED_BINDING - zend_do_delayed_early_binding(CG(active_op_array) TSRMLS_CC); -#else - xc_undo_pass_two(CG(active_op_array) TSRMLS_CC); - xc_foreach_early_binding_class(CG(active_op_array), xc_early_binding_cb, (void *) sandbox TSRMLS_CC); - xc_redo_pass_two(CG(active_op_array) TSRMLS_CC); -#endif - -#ifdef XCACHE_ERROR_CACHING - /* restore trigger errors */ - for (i = 0; i < sandbox->compilererror_cnt; i ++) { - xc_compilererror_t *error = &sandbox->compilererrors[i]; - CG(zend_lineno) = error->lineno; - zend_error(error->type, "%s", error->error); - } - CG(zend_lineno) = 0; -#endif - - i = 1; - /* still needed because in zend_language_scanner.l, require()/include() check file_handle.handle.stream.handle */ - zend_hash_add(&OG(included_files), sandbox->filename, strlen(sandbox->filename) + 1, (void *)&i, sizeof(int), NULL); -} -/* }}} */ -static void xc_sandbox_free(xc_sandbox_t *sandbox, zend_op_array *op_array TSRMLS_DC) /* {{{ */ -{ - XG(sandbox) = NULL; -#ifdef XCACHE_ERROR_CACHING - EG(user_error_handler_error_reporting) = sandbox->orig_user_error_handler_error_reporting; -#endif - - /* restore first first install function/class */ -#ifdef HAVE_XCACHE_CONSTANT - EG(zend_constants) = OG(zend_constants); -#endif - CG(function_table) = OG(function_table); - CG(class_table) = OG(class_table); - EG(class_table) = CG(class_table); -#ifdef ZEND_ENGINE_2_1 - CG(auto_globals) = OG(auto_globals); -#endif - - if (op_array) { - zend_op_array *old_active_op_array = CG(active_op_array); - CG(in_compilation) = 1; - CG(compiled_filename) = ZEND_24(NOTHING, (char *)) sandbox->filename; - CG(zend_lineno) = 0; - - CG(active_op_array) = op_array; - xc_sandbox_install(sandbox TSRMLS_CC); - CG(active_op_array) = old_active_op_array; - - CG(in_compilation) = 0; - CG(compiled_filename) = NULL; - - /* no free as it's installed */ -#ifdef HAVE_XCACHE_CONSTANT - TG(zend_constants).pDestructor = NULL; -#endif - TG(function_table).pDestructor = NULL; - TG(class_table).pDestructor = NULL; - } - - /* destroy all the tmp */ -#ifdef HAVE_XCACHE_CONSTANT - zend_hash_destroy(&TG(zend_constants)); -#endif - zend_hash_destroy(&TG(function_table)); - zend_hash_destroy(&TG(class_table)); -#ifdef ZEND_ENGINE_2_1 - zend_hash_destroy(&TG(auto_globals)); -#endif - zend_hash_destroy(TG(included_files)); - - /* restore orig here, as EG/CG holded tmp before */ - memcpy(&EG(included_files), &OG(included_files), sizeof(EG(included_files))); - -#ifdef XCACHE_ERROR_CACHING - if (sandbox->compilererrors) { - zend_uint i; - for (i = 0; i < sandbox->compilererror_cnt; i ++) { - efree(sandbox->compilererrors[i].error); - } - efree(sandbox->compilererrors); - } -#endif - -#ifdef ZEND_COMPILE_IGNORE_INTERNAL_CLASSES - CG(compiler_options) = sandbox->orig_compiler_options; -#endif -} -/* }}} */ -zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC) /* {{{ */ -{ - xc_sandbox_t sandbox; - zend_op_array *op_array = NULL; - zend_bool catched = 0; - - memset(&sandbox, 0, sizeof(sandbox)); - zend_try { - xc_sandbox_init(&sandbox, filename TSRMLS_CC); - op_array = sandboxed_func(data TSRMLS_CC); - } zend_catch { - catched = 1; - } zend_end_try(); - - xc_sandbox_free(&sandbox, op_array TSRMLS_CC); - if (catched) { - zend_bailout(); - } - return op_array; -} -/* {{{ */ -const Bucket *xc_sandbox_user_function_begin(TSRMLS_D) /* {{{ */ -{ - xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); - assert(sandbox); - return TG(internal_function_tail) ? TG(internal_function_tail)->pListNext : TG(function_table).pListHead; -} -/* {{{ */ -const Bucket *xc_sandbox_user_class_begin(TSRMLS_D) /* {{{ */ -{ - xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); - assert(sandbox); - return TG(internal_class_tail) ? TG(internal_class_tail)->pListNext : TG(class_table).pListHead; -} -/* {{{ */ -#ifdef XCACHE_ERROR_CACHING -xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D) /* {{{ */ -{ - xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); - assert(sandbox); - return sandbox->compilererrors; -} -/* }}} */ -zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D) /* {{{ */ -{ - xc_sandbox_t *sandbox = (xc_sandbox_t *) XG(sandbox); - assert(sandbox); - return sandbox->compilererror_cnt; -} -/* }}} */ -#endif - -int xc_vtrace(const char *fmt, va_list args) /* {{{ */ -{ - return vfprintf(stderr, fmt, args); -} -/* }}} */ -int xc_trace(const char *fmt, ...) /* {{{ */ -{ - va_list args; - int ret; - - va_start(args, fmt); - ret = xc_vtrace(fmt, args); - va_end(args); - return ret; -} -/* }}} */ - -#ifndef ZEND_ENGINE_2_3 -#include "ext/standard/php_string.h" -size_t xc_dirname(char *path, size_t len) /* {{{ */ -{ -#ifdef ZEND_ENGINE_2 - return php_dirname(path, len); -#else - php_dirname(path, len); - return strlen(path); -#endif -} -/* }}} */ - -long xc_atol(const char *str, int str_len) /* {{{ */ -{ - long retval; - - if (!str_len) { - str_len = strlen(str); - } - - retval = strtol(str, NULL, 0); - if (str_len > 0) { - switch (str[str_len - 1]) { - case 'g': - case 'G': - retval *= 1024; - /* break intentionally missing */ - case 'm': - case 'M': - retval *= 1024; - /* break intentionally missing */ - case 'k': - case 'K': - retval *= 1024; - break; - } - } - - return retval; -} -/* }}} */ - -#endif - -/* init/destroy */ -int xc_util_init(int module_number TSRMLS_DC) /* {{{ */ -{ -#ifdef XCACHE_ERROR_CACHING - old_zend_error_cb = zend_error_cb; - zend_error_cb = xc_sandbox_error_cb; -#endif - - return SUCCESS; -} -/* }}} */ -void xc_util_destroy() /* {{{ */ -{ -#ifdef XCACHE_ERROR_CACHING - if (zend_error_cb == xc_sandbox_error_cb) { - zend_error_cb = old_zend_error_cb; - } -#endif -} -/* }}} */ - diff --git a/main/xc_utils.h b/main/xc_utils.h index d03aed3..f82a03f 100644 --- a/main/xc_utils.h +++ b/main/xc_utils.h @@ -40,17 +40,6 @@ ZESW(xc_cest_t *, void) xc_install_class(ZEND_24(NOTHING, const) char *filename, #define XCACHE_ERROR_CACHING #endif -/* return op_array to install */ -typedef zend_op_array *(*xc_sandboxed_func_t)(void *data TSRMLS_DC); -zend_op_array *xc_sandbox(xc_sandboxed_func_t sandboxed_func, void *data, ZEND_24(NOTHING, const) char *filename TSRMLS_DC); -const Bucket *xc_sandbox_user_function_begin(TSRMLS_D); -const Bucket *xc_sandbox_user_class_begin(TSRMLS_D); -zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D); -#ifdef XCACHE_ERROR_CACHING -xc_compilererror_t *xc_sandbox_compilererrors(TSRMLS_D); -zend_uint xc_sandbox_compilererror_cnt(TSRMLS_D); -#endif - void xc_zend_class_add_ref(zend_class_entry ZESW(*ce, **ce)); typedef zend_bool (*xc_if_func_t)(void *data); diff --git a/xcache.c b/xcache.c index 931e70b..642dc89 100644 --- a/xcache.c +++ b/xcache.c @@ -34,6 +34,7 @@ #include "xc_const_string.h" #include "xc_opcode_spec.h" #include "xc_utils.h" +#include "xc_sandbox.h" #include "util/xc_align.h" #include "util/xc_stack.h" #include "util/xc_vector.h"