https://www.mediawiki.org/wiki/Special:Code/MediaWiki/113890
Revision: 113890
Author: tstarling
Date: 2012-03-15 03:50:16 +0000 (Thu, 15 Mar 2012)
Log Message:
-----------
* Allow LuaSandbox objects to be re-entered, i.e. lua -> php -> lua.
* When there is an emergency timeout, make the LuaSandbox object "invalid",
with state=NULL, instead of re-initialising it.
* Cleaned up conversion of LUA_TFUNCTION to PHP LuaSandboxFunction object, from
r110080.
* Fixed code duplication from r110080 by merging the two places where
LuaSandboxFunction objects are made. Moved zval allocation to the
luasandbox_lua_to_zval() caller so that it can set return_value.
* In luasandbox_lua_to_zval(), fixed negative index handling in the
LUA_TFUNCTION case.
* Fixed handling of the case where more than 2^31 chunks are created
* Added LuaSandboxFunction::__construct(), which just throws an error, to
prevent creation of these objects with "new LuaSandboxFunction"
* Fixed a couple of missing TSRM parameters
* Added some test cases
Modified Paths:
--------------
trunk/php/luasandbox/luasandbox.c
trunk/php/luasandbox/php_luasandbox.h
Added Paths:
-----------
trunk/php/luasandbox/tests/LuaSandboxFunction_construct.phpt
trunk/php/luasandbox/tests/call.phpt
trunk/php/luasandbox/tests/callback_exception.phpt
trunk/php/luasandbox/tests/dump_loadBinary_call.phpt
trunk/php/luasandbox/tests/invalid_state.phpt
trunk/php/luasandbox/tests/loadString.phpt
trunk/php/luasandbox/tests/reentrant.phpt
Modified: trunk/php/luasandbox/luasandbox.c
===================================================================
--- trunk/php/luasandbox/luasandbox.c 2012-03-15 02:00:16 UTC (rev 113889)
+++ trunk/php/luasandbox/luasandbox.c 2012-03-15 03:50:16 UTC (rev 113890)
@@ -23,6 +23,12 @@
#define LUASANDBOX_LJ_64
#endif
+#define CHECK_VALID_STATE(state) \
+ if (!state) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid LuaSandbox
state"); \
+ RETURN_FALSE; \
+ }
+
static zend_object_value luasandbox_new(zend_class_entry *ce TSRMLS_DC);
static lua_State * luasandbox_newstate(php_luasandbox_obj * intern);
static void luasandbox_free_storage(void *object TSRMLS_DC);
@@ -42,15 +48,18 @@
static void luasandbox_set_timespec(struct timespec * dest, double source);
static int luasandbox_function_init(zval * this_ptr,
php_luasandboxfunction_obj ** pfunc,
lua_State ** pstate, php_luasandbox_obj ** psandbox TSRMLS_DC);
-static void luasandbox_call_helper(lua_State * L, php_luasandbox_obj * sandbox,
+static void luasandbox_call_helper(lua_State * L, zval * sandbox_zval,
+ php_luasandbox_obj * sandbox,
zval *** args, zend_uint numArgs, zval * return_value TSRMLS_DC);
static int luasandbox_push_zval(lua_State * L, zval * z);
static void luasandbox_push_zval_userdata(lua_State * L, zval * z);
-static zval * luasandbox_lua_to_zval(lua_State * L, int index, HashTable *
recursionGuard);
+static void luasandbox_lua_to_zval(zval * z, lua_State * L, int index,
+ zval * sandbox_zval, HashTable * recursionGuard TSRMLS_DC);
static void luasandbox_lua_to_array(HashTable *ht, lua_State *L, int index,
- HashTable * recursionGuard);
+ zval * sandbox_zval, HashTable * recursionGuard TSRMLS_DC);
static php_luasandbox_obj * luasandbox_get_php_obj(lua_State * L);
static void luasandbox_handle_error(lua_State * L, int status);
+static void luasandbox_handle_emergency_timeout(php_luasandbox_obj * sandbox);
static int luasandbox_push_hashtable(lua_State * L, HashTable * ht);
static int luasandbox_call_php(lua_State * L);
static int luasandbox_dump_writer(lua_State * L, const void * p, size_t sz,
void * ud);
@@ -145,6 +154,9 @@
ZEND_ARG_INFO(0, functions)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_luasandboxfunction___construct, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO(arginfo_luasandboxfunction_call, 0)
ZEND_ARG_INFO(0, ...)
ZEND_END_ARG_INFO()
@@ -171,6 +183,8 @@
};
const zend_function_entry luasandboxfunction_methods[] = {
+ PHP_ME(LuaSandboxFunction, __construct,
arginfo_luasandboxfunction___construct,
+ ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
PHP_ME(LuaSandboxFunction, call, arginfo_luasandboxfunction_call, 0)
PHP_ME(LuaSandboxFunction, dump, arginfo_luasandboxfunction_dump, 0)
{NULL, NULL, NULL}
@@ -298,9 +312,9 @@
*/
static inline void luasandbox_enter_php(lua_State * L, php_luasandbox_obj *
intern)
{
- intern->in_php = 1;
+ intern->in_php ++;
if (intern->timed_out) {
- intern->in_php = 0;
+ intern->in_php --;
luaL_error(L, luasandbox_timeout_message);
}
}
@@ -313,7 +327,7 @@
*/
static inline void luasandbox_leave_php(lua_State * L, php_luasandbox_obj *
intern)
{
- intern->in_php = 0;
+ intern->in_php --;
}
/* }}} */
@@ -418,7 +432,7 @@
// Register a pointer to the PHP object so that C functions can find it
lua_pushlightuserdata(L, (void*)intern);
lua_setfield(L, LUA_REGISTRYINDEX, "php_luasandbox_obj");
-
+
// Create the metatable for zval destruction
lua_createtable(L, 0, 1);
lua_pushcfunction(L, luasandbox_free_zval_userdata);
@@ -437,16 +451,18 @@
{
php_luasandbox_obj * intern = (php_luasandbox_obj*)object;
- // In 64-bit LuaJIT mode, restore the old allocator before calling
- // lua_close() because lua_close() actually checks that the value of
the
- // function pointer is unchanged before destroying the underlying
- // allocator. If the allocator has been changed, the mmap is not freed.
+ if (intern->state) {
+ // In 64-bit LuaJIT mode, restore the old allocator before
calling
+ // lua_close() because lua_close() actually checks that the
value of the
+ // function pointer is unchanged before destroying the
underlying
+ // allocator. If the allocator has been changed, the mmap is
not freed.
#ifdef LUASANDBOX_LJ_64
- lua_setallocf(intern->state, intern->old_alloc, intern->old_alloc_ud);
+ lua_setallocf(intern->state, intern->old_alloc,
intern->old_alloc_ud);
#endif
- lua_close(intern->state);
- intern->state = NULL;
+ lua_close(intern->state);
+ intern->state = NULL;
+ }
zend_object_std_dtor(&intern->std);
efree(object);
}
@@ -455,9 +471,6 @@
/** {{{ luasandboxfunction_new
*
* "new" handler for the LuaSandboxFunction class.
- *
- * TODO: Make it somehow impossible to construct these objects from user code.
- * Only LuaSandbox methods should be constructing them.
*/
static zend_object_value luasandboxfunction_new(zend_class_entry *ce TSRMLS_CC)
{
@@ -492,14 +505,16 @@
if (func->sandbox) {
php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
zend_object_store_get_object(func->sandbox TSRMLS_CC);
- lua_State * L = sandbox->state;
+ if (sandbox && sandbox->state) {
+ lua_State * L = sandbox->state;
- // Delete the chunk
- if (func->index) {
- lua_getfield(L, LUA_REGISTRYINDEX,
"php_luasandbox_chunks");
- lua_pushnil(L);
- lua_rawseti(L, -2, func->index);
- lua_pop(L, 1);
+ // Delete the chunk
+ if (func->index) {
+ lua_getfield(L, LUA_REGISTRYINDEX,
"php_luasandbox_chunks");
+ lua_pushnil(L);
+ lua_rawseti(L, -2, func->index);
+ lua_pop(L, 1);
+ }
}
// Delete the parent reference
@@ -548,9 +563,9 @@
{
php_luasandbox_obj * obj = (php_luasandbox_obj*)ud;
void * nptr;
- obj->in_php = 1;
+ obj->in_php ++;
if (!luasandbox_update_memory_accounting(obj, osize, nsize)) {
- obj->in_php = 0;
+ obj->in_php --;
return NULL;
}
@@ -564,7 +579,7 @@
} else {
nptr = erealloc(ptr, nsize);
}
- obj->in_php = 0;
+ obj->in_php --;
return nptr;
}
/* }}} */
@@ -668,20 +683,8 @@
sandbox = (php_luasandbox_obj*)
zend_object_store_get_object(this_ptr TSRMLS_CC);
L = sandbox->state;
+ CHECK_VALID_STATE(L);
- // The following code puts zval of the sandbox object into the register.
- // Why here? It should have been done at the constructor, but there was
- // no getThis() available at that point. Let's hope user will not run
any
- // code requiring this register until he actually loads the code.
- // Why put it? Because when creating function object we need a zval,
- // not just php_luasandbox_obj, since we are going to reference to it
from
- // the function object, and such referencing is possible only through
zvalues.
- // Let us hope putting zval into Lua register won't corrupt any PHP
internal
- // mechanisms.
- // FIXME: there should be a better way of doing this.
- lua_pushlightuserdata(L, (void*)getThis());
- lua_setfield(L, LUA_REGISTRYINDEX, "php_luasandbox_obj_zval");
-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
&code, &codeLength, &chunkName,
&chunkNameLength) == FAILURE) {
RETURN_FALSE;
@@ -713,33 +716,20 @@
RETURN_FALSE;
}
- // Get the chunks table
- lua_getfield(L, LUA_REGISTRYINDEX, "php_luasandbox_chunks");
-
- // Get the next free index
- index = ++(sandbox->function_index);
- if (index >= INT_MAX) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "too many chunks loaded already");
- RETURN_FALSE;
- }
-
// Parse the string into a function on the stack
status = luaL_loadbuffer(L, code, codeLength, chunkName);
if (status != 0) {
luasandbox_handle_error(L, status);
return;
}
-
- // Store the resulting function to the chunks table
- lua_rawseti(L, -2, (int)index);
- // Create a LuaSandboxFunction object to hold a reference to the
function
- object_init_ex(return_value, luasandboxfunction_ce);
- func_obj =
(php_luasandboxfunction_obj*)zend_object_store_get_object(return_value);
- func_obj->index = index;
- func_obj->sandbox = getThis();
- Z_ADDREF_P(getThis());
+ // Make a zval out of it, and return false on error
+ luasandbox_lua_to_zval(return_value, L, lua_gettop(L), this_ptr, NULL
TSRMLS_CC);
+ if (Z_TYPE_P(return_value) == IS_NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "too many chunks loaded already");
+ RETVAL_FALSE;
+ }
// Balance the stack
lua_pop(L, 1);
@@ -773,6 +763,23 @@
}
/* }}} */
+/** {{{ luasandbox_handle_emergency_timeout
+ *
+ * Handle the situation where the emergency_timeout flag is set. Throws an
+ * appropriate exception and destroys the state.
+ */
+static void luasandbox_handle_emergency_timeout(php_luasandbox_obj * sandbox)
+{
+ lua_close(sandbox->state);
+ sandbox->state = NULL;
+ sandbox->emergency_timed_out = 0;
+ zend_throw_exception(luasandboxemergencytimeout_ce,
+ "The maximum execution time was exceeded "
+ "and the current Lua statement failed to return, leading to "
+ "destruction of the Lua state", LUA_ERRRUN);
+}
+/* }}} */
+
/** {{{ luasandbox_handle_error
*
* Handles the error return situation from lua_pcall() and lua_load(), where a
@@ -945,6 +952,7 @@
php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
zend_object_store_get_object(getThis() TSRMLS_CC);
lua_State * L = sandbox->state;
+ CHECK_VALID_STATE(L);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s*",
&name, &nameLength, &args, &numArgs) == FAILURE)
@@ -959,7 +967,7 @@
RETVAL_FALSE;
} else {
// Call it
- luasandbox_call_helper(L, sandbox, args, numArgs, return_value
TSRMLS_CC);
+ luasandbox_call_helper(L, getThis(), sandbox, args, numArgs,
return_value TSRMLS_CC);
}
// Delete varargs
@@ -980,6 +988,8 @@
*pfunc = (php_luasandboxfunction_obj *)
zend_object_store_get_object(this_ptr TSRMLS_CC);
if (!*pfunc || !(*pfunc)->sandbox || !(*pfunc)->index) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "attempt to call uninitialized LuaSandboxFunction
object" );
return 0;
}
@@ -987,6 +997,11 @@
zend_object_store_get_object((*pfunc)->sandbox TSRMLS_CC);
*pstate = (*psandbox)->state;
+ if (!*pstate) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid LuaSandbox
state");
+ return 0;
+ }
+
// Find the function
lua_getfield(*pstate, LUA_REGISTRYINDEX, "php_luasandbox_chunks");
lua_rawgeti(*pstate, -1, (*pfunc)->index);
@@ -998,6 +1013,16 @@
}
/* }}} */
+/* {{{ proto private final LuaSandboxFunction::__construct()
+ *
+ * Construct a LuaSandboxFunction object. Do not call this directly, use
+ * LuaSandbox::loadString().
+ */
+PHP_METHOD(LuaSandboxFunction, __construct)
+{
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "LuaSandboxFunction cannot be
constructed directly");
+}
+
/** {{{ proto array LuaSandboxFunction::call(...)
*
* Call a LuaSandboxFunction. The arguments to this function are passed through
@@ -1023,8 +1048,6 @@
php_luasandbox_obj * sandbox;
if (!luasandbox_function_init(getThis(), &func, &L, &sandbox
TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "attempt to call uninitialized LuaSandboxFunction
object" );
RETURN_FALSE;
}
@@ -1035,7 +1058,7 @@
}
// Call the function
- luasandbox_call_helper(L, sandbox, args, numArgs, return_value
TSRMLS_CC);
+ luasandbox_call_helper(L, func->sandbox, sandbox, args, numArgs,
return_value TSRMLS_CC);
// Delete varargs
if (numArgs) {
@@ -1049,7 +1072,7 @@
* Call the function at the top of the stack and then pop it. Set return_value
* to an array containing all the results.
*/
-static void luasandbox_call_helper(lua_State * L, php_luasandbox_obj *
sandbox,
+static void luasandbox_call_helper(lua_State * L, zval * sandbox_zval,
php_luasandbox_obj * sandbox,
zval *** args, zend_uint numArgs, zval * return_value TSRMLS_DC)
{
// Save the top position
@@ -1058,6 +1081,7 @@
int cpu_limited = 0;
luasandbox_timer_set t;
int i, numResults;
+ zval * old_zval;
// Check to see if the value is a valid function
if (lua_type(L, -1) != LUA_TFUNCTION) {
@@ -1078,7 +1102,7 @@
}
// Initialise the CPU limit timer
- if (sandbox->is_cpu_limited) {
+ if (!sandbox->in_lua && sandbox->is_cpu_limited) {
cpu_limited = 1;
if (!LUASANDBOX_G(signal_handler_installed)) {
luasandbox_timer_install_handler(&LUASANDBOX_G(old_handler));
@@ -1087,26 +1111,26 @@
&sandbox->cpu_emergency_limit);
}
+ // Save the current zval for later use in luasandbox_call_php. Restore
it
+ // after execution finishes, to support re-entrancy.
+ old_zval = sandbox->current_zval;
+ sandbox->current_zval = sandbox_zval;
+
// Call the function
+ sandbox->in_lua++;
status = lua_pcall(L, numArgs, LUA_MULTRET, 0);
+ sandbox->in_lua--;
+ sandbox->current_zval = old_zval;
// Stop the timer
if (cpu_limited) {
luasandbox_timer_stop(&t);
}
-
- // If there was an emergency timeout, destroy the state
if (sandbox->emergency_timed_out) {
- lua_close(L);
- L = sandbox->state = luasandbox_newstate(sandbox);
- sandbox->emergency_timed_out = 0;
- zend_throw_exception(luasandboxemergencytimeout_ce,
- "The maximum execution time was exceeded "
- "and the current Lua statement failed to return,
leading to "
- "destruction of the Lua state", LUA_ERRRUN);
+ luasandbox_handle_emergency_timeout(sandbox);
return;
}
-
+
// Handle normal errors
if (status) {
luasandbox_handle_error(L, status);
@@ -1120,7 +1144,9 @@
// Fill the array with the results
for (i = 0; i < numResults; i++) {
- zval * element = luasandbox_lua_to_zval(L, origTop + i, NULL);
+ zval * element;
+ MAKE_STD_ZVAL(element);
+ luasandbox_lua_to_zval(element, L, origTop + i, sandbox_zval,
NULL TSRMLS_CC);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value),
(void*)&element,
sizeof(zval*), NULL);
@@ -1300,23 +1326,23 @@
/** {{{ luasandbox_lua_to_zval
*
- * Convert a lua value to a zval. Allocates the zval on the heap and returns
- * a pointer to it.
+ * Convert a lua value to a zval.
*
* If a value is encountered that can't be converted to a zval, a
LuaPlaceholder
* object is returned instead.
*
+ * @param z A pointer to the destination zval
* @param L The lua state
* @param index The stack index to the input value
+ * @param sandbox_zval A zval poiting to a valid LuaSandbox object which will
be
+ * used for the parent object of any LuaSandboxFunction objects created.
* @param recursionGuard A hashtable for keeping track of tables that have
been
* processed, to allow infinite recursion to be avoided. External callers
* should set this to NULL.
*/
-static zval * luasandbox_lua_to_zval(lua_State * L, int index, HashTable *
recursionGuard)
+static void luasandbox_lua_to_zval(zval * z, lua_State * L, int index,
+ zval * sandbox_zval, HashTable * recursionGuard TSRMLS_DC)
{
- zval * z;
- MAKE_STD_ZVAL(z);
-
switch (lua_type(L, index)) {
case LUA_TNIL:
ZVAL_NULL(z);
@@ -1379,7 +1405,7 @@
// Process the array
array_init(z);
- luasandbox_lua_to_array(Z_ARRVAL_P(z), L, index,
recursionGuard);
+ luasandbox_lua_to_array(Z_ARRVAL_P(z), L, index,
sandbox_zval, recursionGuard TSRMLS_CC);
if (allocated) {
zend_hash_destroy(recursionGuard);
@@ -1390,37 +1416,35 @@
case LUA_TFUNCTION: {
int func_index;
php_luasandboxfunction_obj * func_obj;
- php_luasandbox_obj * sandbox;
- zval * sandbox_zval;
+ php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
+ zend_object_store_get_object(sandbox_zval);
+
+ // Normalise the input index so that we can push
without invalidating it.
+ if (index < 0) {
+ index += lua_gettop(L) + 1;
+ }
- // Get the sandbox object and its zval
- sandbox = luasandbox_get_php_obj(L);
- lua_getfield(L, LUA_REGISTRYINDEX,
"php_luasandbox_obj_zval");
- sandbox_zval = (zval*)lua_touserdata(L, -1);
- assert(sandbox_zval != NULL);
- lua_pop(L, 1);
-
// Get the chunks table
lua_getfield(L, LUA_REGISTRYINDEX,
"php_luasandbox_chunks");
// Get the next free index
- func_index = ++(sandbox->function_index);
- if (func_index >= INT_MAX) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "too many chunks loaded
already");
+ if (sandbox->function_index >= INT_MAX) {
ZVAL_NULL(z);
+ lua_pop(L, 1);
+ break;
}
+ func_index = ++(sandbox->function_index);
- // Put the function together with other chunks
- lua_pushvalue(L, index - 1);
- lua_rawseti(L, -2, (int)func_index);
+ // Store it in the chunks table
+ lua_pushvalue(L, index);
+ lua_rawseti(L, -2, func_index);
// Create a LuaSandboxFunction object to hold a
reference to the function
object_init_ex(z, luasandboxfunction_ce);
func_obj =
(php_luasandboxfunction_obj*)zend_object_store_get_object(z);
func_obj->index = func_index;
func_obj->sandbox = sandbox_zval;
- Z_ADDREF_P(func_obj->sandbox);
+ Z_ADDREF_P(sandbox_zval);
// Balance the stack
lua_pop(L, 1);
@@ -1433,7 +1457,6 @@
// TODO: provide derived classes for each type
object_init_ex(z, luasandboxplaceholder_ce);
}
- return z;
}
/* }}} */
@@ -1442,7 +1465,7 @@
* Append the elements of the table in the specified index to the given
HashTable.
*/
static void luasandbox_lua_to_array(HashTable *ht, lua_State *L, int index,
- HashTable * recursionGuard)
+ zval * sandbox_zval, HashTable * recursionGuard TSRMLS_DC)
{
const char * str;
size_t length;
@@ -1455,7 +1478,8 @@
lua_pushnil(L);
while (lua_next(L, index) != 0) {
- value = luasandbox_lua_to_zval(L, -1, recursionGuard);
+ MAKE_STD_ZVAL(value);
+ luasandbox_lua_to_zval(value, L, -1, sandbox_zval,
recursionGuard TSRMLS_CC);
// Make a copy of the key so that we can call lua_tolstring()
which is destructive
lua_pushvalue(L, -2);
@@ -1509,6 +1533,8 @@
HashTable * functions;
Bucket * p;
+ CHECK_VALID_STATE(L);
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa",
&libname, &libname_len, &zfunctions) == FAILURE)
{
@@ -1577,6 +1603,7 @@
zval **pointers;
zval ***double_pointers;
int num_results = 0;
+ TSRMLS_FETCH();
// Based on zend_parse_arg_impl()
if (zend_fcall_info_init(*callback_pp, 0, &fci, &fcc, NULL,
@@ -1599,7 +1626,8 @@
double_pointers = (zval***)temp;
pointers = (zval**)(temp + top);
for (i = 0; i < top; i++ ) {
- pointers[i] = luasandbox_lua_to_zval(L, i + 1, NULL);
+ MAKE_STD_ZVAL(pointers[i]);
+ luasandbox_lua_to_zval(pointers[i], L, i + 1,
intern->current_zval, NULL TSRMLS_CC);
double_pointers[i] = &(pointers[i]);
}
@@ -1649,8 +1677,6 @@
smart_str buf = {0};
if (!luasandbox_function_init(getThis(), &func, &L, &sandbox
TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "attempt to call uninitialized LuaSandboxFunction
object" );
RETURN_FALSE;
}
Modified: trunk/php/luasandbox/php_luasandbox.h
===================================================================
--- trunk/php/luasandbox/php_luasandbox.h 2012-03-15 02:00:16 UTC (rev
113889)
+++ trunk/php/luasandbox/php_luasandbox.h 2012-03-15 03:50:16 UTC (rev
113890)
@@ -34,6 +34,7 @@
PHP_METHOD(LuaSandbox, callFunction);
PHP_METHOD(LuaSandbox, registerLibrary);
+PHP_METHOD(LuaSandboxFunction, __construct);
PHP_METHOD(LuaSandboxFunction, call);
PHP_METHOD(LuaSandboxFunction, dump);
@@ -57,6 +58,8 @@
lua_Alloc old_alloc;
void * old_alloc_ud;
int in_php;
+ int in_lua;
+ zval * current_zval; /* The zval for the LuaSandbox which is currently
executing Lua code */
volatile int timed_out;
volatile int emergency_timed_out;
int is_cpu_limited;
Added: trunk/php/luasandbox/tests/LuaSandboxFunction_construct.phpt
===================================================================
--- trunk/php/luasandbox/tests/LuaSandboxFunction_construct.phpt
(rev 0)
+++ trunk/php/luasandbox/tests/LuaSandboxFunction_construct.phpt
2012-03-15 03:50:16 UTC (rev 113890)
@@ -0,0 +1,10 @@
+--TEST--
+LuaSandboxFunction::construct() is private
+--SKIPIF--
+<?php if (!extension_loaded("luasandbox")) print "skip"; ?>
+--FILE--
+<?php
+new LuaSandboxFunction;
+?>
+--EXPECTF--
+Fatal error: Call to private LuaSandboxFunction::__construct() from invalid
context in %s on line %d
Added: trunk/php/luasandbox/tests/call.phpt
===================================================================
--- trunk/php/luasandbox/tests/call.phpt (rev 0)
+++ trunk/php/luasandbox/tests/call.phpt 2012-03-15 03:50:16 UTC (rev
113890)
@@ -0,0 +1,11 @@
+--TEST--
+LuaSandboxFunction::call
+--FILE--
+<?php
+$sandbox = new LuaSandbox;
+var_dump( $sandbox->loadString( 'return 1' )->call() );
+--EXPECT--
+array(1) {
+ [0]=>
+ int(1)
+}
Added: trunk/php/luasandbox/tests/callback_exception.phpt
===================================================================
--- trunk/php/luasandbox/tests/callback_exception.phpt
(rev 0)
+++ trunk/php/luasandbox/tests/callback_exception.phpt 2012-03-15 03:50:16 UTC
(rev 113890)
@@ -0,0 +1,18 @@
+--TEST--
+Exception in a PHP function called from Lua
+--FILE--
+<?php
+
+function throw_exception() {
+ throw new Exception('message');
+}
+$sandbox = new LuaSandbox;
+$sandbox->registerLibrary( 'test', array( 'throw_exception' =>
'throw_exception' ) );
+$f = $sandbox->loadString('test.throw_exception()');
+try {
+ $f->call();
+} catch ( Exception $e ) {
+ print $e->getMessage();
+}
+--EXPECT--
+message
Added: trunk/php/luasandbox/tests/dump_loadBinary_call.phpt
===================================================================
--- trunk/php/luasandbox/tests/dump_loadBinary_call.phpt
(rev 0)
+++ trunk/php/luasandbox/tests/dump_loadBinary_call.phpt 2012-03-15
03:50:16 UTC (rev 113890)
@@ -0,0 +1,21 @@
+--TEST--
+dump -> loadBinary -> call
+--FILE--
+<?php
+
+var_dump( $sandbox = new LuaSandbox );
+var_dump( $f = $sandbox->loadString( 'return 1' ) );
+$dump = $f->dump();
+var_dump( $restore = $sandbox->loadBinary( $dump ) );
+var_dump( $restore->call() );
+--EXPECT--
+object(LuaSandbox)#1 (0) {
+}
+object(LuaSandboxFunction)#2 (0) {
+}
+object(LuaSandboxFunction)#3 (0) {
+}
+array(1) {
+ [0]=>
+ int(1)
+}
Added: trunk/php/luasandbox/tests/invalid_state.phpt
===================================================================
--- trunk/php/luasandbox/tests/invalid_state.phpt
(rev 0)
+++ trunk/php/luasandbox/tests/invalid_state.phpt 2012-03-15 03:50:16 UTC
(rev 113890)
@@ -0,0 +1,27 @@
+--TEST--
+Functions called on an invalid LuaSandbox, after emergency timeout
+--FILE--
+<?php
+$sandbox = new LuaSandbox;
+$sandbox->setCPULimit(100, 0.1);
+$f = $sandbox->loadString('while true do end');
+$dump = $f->dump();
+try {
+ $f->call();
+} catch (LuaSandboxEmergencyTimeout $e) {
+ print $e->getMessage() . "\n";
+}
+$f->call();
+$sandbox->loadString('foo()');
+$sandbox->loadBinary($dump);
+$sandbox->callFunction('foo');
+--EXPECTF--
+The maximum execution time was exceeded and the current Lua statement failed
to return, leading to destruction of the Lua state
+
+Warning: LuaSandboxFunction::call(): invalid LuaSandbox state in %s on line %d
+
+Warning: LuaSandbox::loadString(): invalid LuaSandbox state in %s on line %d
+
+Warning: LuaSandbox::loadBinary(): invalid LuaSandbox state in %s on line %d
+
+Warning: LuaSandbox::callFunction(): invalid LuaSandbox state in %s on line %d
Added: trunk/php/luasandbox/tests/loadString.phpt
===================================================================
--- trunk/php/luasandbox/tests/loadString.phpt (rev 0)
+++ trunk/php/luasandbox/tests/loadString.phpt 2012-03-15 03:50:16 UTC (rev
113890)
@@ -0,0 +1,17 @@
+--TEST--
+loadString 1
+--FILE--
+<?php
+var_dump($sandbox = new LuaSandbox);
+var_dump($f = $sandbox->loadString('foo()'));
+try {
+ $f = $sandbox->loadString('foo');
+} catch( Exception $e ) {
+ print $e->getMessage();
+}
+--EXPECTF--
+object(LuaSandbox)#1 (0) {
+}
+object(LuaSandboxFunction)#2 (0) {
+}
+[string ""]:1: '=' expected near '<eof>'
Added: trunk/php/luasandbox/tests/reentrant.phpt
===================================================================
--- trunk/php/luasandbox/tests/reentrant.phpt (rev 0)
+++ trunk/php/luasandbox/tests/reentrant.phpt 2012-03-15 03:50:16 UTC (rev
113890)
@@ -0,0 +1,53 @@
+--TEST--
+Re-entering Lua during a callback to PHP
+--FILE--
+<?php
+$sandbox = new LuaSandbox;
+$chunk = $sandbox->loadString('
+ function factorial(n)
+ if n <= 1 then
+ return 1
+ else
+ return n * test.factorial(n - 1)
+ end
+ end
+
+ return factorial
+');
+
+$ret = $chunk->call();
+$luaFactorial = $ret[0];
+
+$sandbox->registerLibrary( 'test', array( 'factorial' => 'factorial' ) );
+
+function factorial($n) {
+ global $luaFactorial;
+ if ($n <= 1) {
+ return 1;
+ } else {
+ $ret = $luaFactorial->call($n - 1);
+ return $n * $ret[0];
+ }
+}
+
+print factorial(10) . "\n";
+var_dump( $luaFactorial->call(10) );
+
+try {
+ $luaFactorial->call(1000000000);
+} catch ( LuaSandboxError $e ) {
+ print $e->getMessage() . "\n";
+}
+try {
+ factorial(1000000000);
+} catch ( LuaSandboxError $e ) {
+ print $e->getMessage() . "\n";
+}
+--EXPECT--
+3628800
+array(1) {
+ [0]=>
+ int(3628800)
+}
+C stack overflow
+C stack overflow
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs