Anomie has uploaded a new change for review.
https://gerrit.wikimedia.org/r/298312
Change subject: Update for PHP 7
......................................................................
Update for PHP 7
They made several changes that result in a lot of conditional
compilation:
* zval** is now zval*, and many (but not all) zval* are now plain zval.
zvals are often allocated on the stack now, so even when we do get a
zval* it might not last beyond the current function call.
* Objects are stored directly in zvals now, no more object store. This
also means we don't free the object in the 'free_obj' callback
anymore.
* The HashTable API changed significantly, it stores zvals instead of
arbitrary data, doesn't include the trailing \0 in keys anymore, and
has a completely new way of iterating.
* A new "zend_string" struct to replace char* + length. Although in most
cases we can get away with "zend_hash_str_*" methods to avoid having
to construct zend_strings.
* Various other gratuitous method signature changes.
Bug: T139558
Change-Id: I34ba41ace1f8ff14371a116e0d2880f4e7cf58c5
---
M data_conversion.c
M library.c
M luasandbox.c
M luasandbox_types.h
A tests/datatypes.phpt
M timer.c
6 files changed, 584 insertions(+), 181 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/php/luasandbox
refs/changes/12/298312/1
diff --git a/data_conversion.c b/data_conversion.c
index 0c0ccad..46a78ea 100644
--- a/data_conversion.c
+++ b/data_conversion.c
@@ -19,6 +19,7 @@
using std::isfinite;
#endif
+static void luasandbox_throw_runtimeerror(lua_State * L, zval * sandbox_zval,
const char *message TSRMLS_DC);
static inline int luasandbox_is_recursive(HashTable * ht);
static inline void luasandbox_protect_recursion(HashTable * ht);
static inline void luasandbox_unprotect_recursion(HashTable * ht);
@@ -67,6 +68,9 @@
int luasandbox_push_zval(lua_State * L, zval * z)
{
switch (Z_TYPE_P(z)) {
+#ifdef IS_UNDEF
+ case IS_UNDEF: // Close enough to IS_NULL
+#endif
case IS_NULL:
lua_pushnil(L);
break;
@@ -76,9 +80,19 @@
case IS_DOUBLE:
lua_pushnumber(L, Z_DVAL_P(z));
break;
+#ifdef IS_BOOL
case IS_BOOL:
lua_pushboolean(L, Z_BVAL_P(z));
break;
+#endif
+#ifdef IS_TRUE
+ case IS_TRUE:
+ lua_pushboolean(L, 1);
+ break;
+ case IS_FALSE:
+ lua_pushboolean(L, 0);
+ break;
+#endif
case IS_ARRAY:
if (!luasandbox_push_hashtable(L, Z_ARRVAL_P(z))) {
return 0;
@@ -92,7 +106,7 @@
if (instanceof_function(objce, luasandboxfunction_ce
TSRMLS_CC)) {
php_luasandboxfunction_obj * func_obj;
- func_obj = (php_luasandboxfunction_obj
*)zend_object_store_get_object(z TSRMLS_CC);
+ func_obj = GET_LUASANDBOXFUNCTION_OBJ(z);
lua_getfield(L, LUA_REGISTRYINDEX,
"php_luasandbox_chunks");
lua_rawgeti(L, -1, func_obj->index);
@@ -108,6 +122,11 @@
case IS_STRING:
lua_pushlstring(L, Z_STRVAL_P(z), Z_STRLEN_P(z));
break;
+#ifdef IS_REFERENCE
+ case IS_REFERENCE:
+ return luasandbox_push_zval(L, Z_REFVAL_P(z));
+#endif
+
case IS_RESOURCE:
default:
return 0;
@@ -122,16 +141,27 @@
*/
static int luasandbox_free_zval_userdata(lua_State * L)
{
- zval ** zpp = (zval**)lua_touserdata(L, 1);
+#if PHP_VERSION_ID < 70000
+ zval ** ud = (zval**)lua_touserdata(L, 1);
+#else
+ zval * ud = (zval*)lua_touserdata(L, 1);
+#endif
php_luasandbox_obj * intern = luasandbox_get_php_obj(L);
// Don't abort if the request has timed out, we need to be able to
clean up
luasandbox_enter_php_ignore_timeouts(L, intern);
- if (zpp && *zpp) {
- zval_ptr_dtor(zpp);
+#if PHP_VERSION_ID < 70000
+ if (ud && *ud) {
+ zval_ptr_dtor(ud);
+ *ud = NULL;
}
- *zpp = NULL;
+#else
+ if (ud && !Z_ISUNDEF_P(ud)) {
+ zval_ptr_dtor(ud);
+ ZVAL_UNDEF(ud);
+ }
+#endif
luasandbox_leave_php(L, intern);
return 0;
}
@@ -145,10 +175,14 @@
*/
void luasandbox_push_zval_userdata(lua_State * L, zval * z)
{
- zval ** ud;
- ud = (zval**)lua_newuserdata(L, sizeof(zval*));
+#if PHP_VERSION_ID < 70000
+ zval ** ud = (zval**)lua_newuserdata(L, sizeof(zval*));
*ud = z;
Z_ADDREF_P(z);
+#else
+ zval * ud = (zval*)lua_newuserdata(L, sizeof(zval));
+ ZVAL_COPY(ud, z);
+#endif
lua_getfield(L, LUA_REGISTRYINDEX, "php_luasandbox_zval_metatable");
lua_setmetatable(L, -2);
@@ -162,8 +196,6 @@
*/
static int luasandbox_push_hashtable(lua_State * L, HashTable * ht)
{
- HashPosition p;
-
// Recursion requires an arbitrary amount of stack space so we have to
// check the stack.
luaL_checkstack(L, 10, "converting PHP array to Lua");
@@ -179,6 +211,9 @@
return 0;
}
luasandbox_protect_recursion(ht);
+
+#if PHP_VERSION_ID < 70000
+ HashPosition p;
for (zend_hash_internal_pointer_reset_ex(ht, &p);
zend_hash_get_current_key_type_ex(ht, &p) !=
HASH_KEY_NON_EXISTANT;
zend_hash_move_forward_ex(ht, &p))
@@ -206,6 +241,30 @@
lua_settable(L, -3);
}
+#else
+ ulong lkey;
+ zend_string *key;
+ zval *value;
+ ZEND_HASH_FOREACH_KEY_VAL(ht, lkey, key, value)
+ {
+ if (key) {
+ lua_pushlstring(L, ZSTR_VAL(key), ZSTR_LEN(key));
+ } else {
+ lua_pushinteger(L, lkey);
+ }
+
+ if (!luasandbox_push_zval(L, value)) {
+ // Failed to process that data value
+ // Pop the key and the half-constructed table
+ lua_pop(L, 2);
+ luasandbox_unprotect_recursion(ht);
+ return 0;
+ }
+
+ lua_settable(L, -3);
+ } ZEND_HASH_FOREACH_END();
+#endif
+
luasandbox_unprotect_recursion(ht);
return 1;
}
@@ -267,33 +326,27 @@
const char * str;
size_t length;
str = lua_tolstring(L, index, &length);
+#if PHP_VERSION_ID < 70000
ZVAL_STRINGL(z, str, length, 1);
+#else
+ ZVAL_STRINGL(z, str, length);
+#endif
break;
}
case LUA_TTABLE: {
const void * ptr = lua_topointer(L, index);
- void * data = NULL;
int allocated = 0;
int success = 1;
if (recursionGuard) {
// Check for circular reference (infinite
recursion)
- if (zend_hash_find(recursionGuard, (char*)&ptr,
sizeof(void*), &data) == SUCCESS) {
+#if PHP_VERSION_ID < 70000
+ if (zend_hash_exists(recursionGuard,
(char*)&ptr, sizeof(void*)))
+#else
+ if (zend_hash_str_exists(recursionGuard,
(char*)&ptr, sizeof(void*)))
+#endif
+ {
// Found circular reference!
- zval *zex, *ztrace;
- MAKE_STD_ZVAL(zex);
- object_init_ex(zex,
luasandboxruntimeerror_ce);
-
- ALLOC_INIT_ZVAL(ztrace); // IS_NULL if
lua_to_zval fails.
- luasandbox_push_structured_trace(L, 1);
- luasandbox_lua_to_zval(ztrace, L, -1,
sandbox_zval, NULL TSRMLS_CC);
-
zend_update_property(luasandboxruntimeerror_ce, zex, "luaTrace",
sizeof("luaTrace")-1, ztrace TSRMLS_CC);
- zval_ptr_dtor(&ztrace);
- lua_pop(L, 1);
-
-
zend_update_property_string(luasandboxruntimeerror_ce, zex,
- "message", sizeof("message")-1,
"Cannot pass circular reference to PHP" TSRMLS_CC);
-
zend_update_property_long(luasandboxruntimeerror_ce, zex, "code",
sizeof("code")-1, -1 TSRMLS_CC);
- zend_throw_exception_object(zex
TSRMLS_CC);
+ luasandbox_throw_runtimeerror(L,
sandbox_zval, "Cannot pass circular reference to PHP" TSRMLS_CC);
ZVAL_NULL(z); // Need to set something
to prevent a segfault
return 0;
@@ -306,7 +359,13 @@
// Add the current table to the recursion guard
hashtable
// Use the pointer as the key, zero-length data
+#if PHP_VERSION_ID < 70000
zend_hash_update(recursionGuard, (char*)&ptr,
sizeof(void*), (void*)"", 1, NULL);
+#else
+ zval zv;
+ ZVAL_TRUE(&zv);
+ zend_hash_str_update(recursionGuard, (char*)&ptr,
sizeof(void*), &zv);
+#endif
// Process the array
array_init(z);
@@ -328,8 +387,7 @@
case LUA_TFUNCTION: {
int func_index;
php_luasandboxfunction_obj * func_obj;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(sandbox_zval
TSRMLS_CC);
+ php_luasandbox_obj * sandbox =
GET_LUASANDBOX_OBJ(sandbox_zval);
// Normalise the input index so that we can push
without invalidating it.
if (index < 0) {
@@ -353,10 +411,14 @@
// 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 TSRMLS_CC);
+ func_obj = GET_LUASANDBOXFUNCTION_OBJ(z);
func_obj->index = func_index;
+#if PHP_VERSION_ID < 70000
func_obj->sandbox = sandbox_zval;
Z_ADDREF_P(sandbox_zval);
+#else
+ ZVAL_COPY(&func_obj->sandbox, sandbox_zval);
+#endif
// Balance the stack
lua_pop(L, 1);
@@ -367,26 +429,9 @@
case LUA_TLIGHTUSERDATA:
// TODO: provide derived classes for each type
default: {
- zval *zex, *ztrace;
char *message;
-
spprintf(&message, 0, "Cannot pass %s to PHP",
lua_typename(L, lua_type(L, index)));
-
- MAKE_STD_ZVAL(zex);
- object_init_ex(zex, luasandboxruntimeerror_ce);
-
- ALLOC_INIT_ZVAL(ztrace); // IS_NULL if lua_to_zval
fails.
- luasandbox_push_structured_trace(L, 1);
- luasandbox_lua_to_zval(ztrace, L, -1, sandbox_zval,
NULL TSRMLS_CC);
- zend_update_property(luasandboxruntimeerror_ce, zex,
"luaTrace", sizeof("luaTrace")-1, ztrace TSRMLS_CC);
- zval_ptr_dtor(&ztrace);
- lua_pop(L, 1);
-
- zend_update_property_string(luasandboxruntimeerror_ce,
zex,
- "message", sizeof("message")-1, message
TSRMLS_CC);
- zend_update_property_long(luasandboxruntimeerror_ce,
zex, "code", sizeof("code")-1, -1 TSRMLS_CC);
- zend_throw_exception_object(zex TSRMLS_CC);
-
+ luasandbox_throw_runtimeerror(L, sandbox_zval, message
TSRMLS_CC);
efree(message);
ZVAL_NULL(z); // Need to set something to prevent a
segfault
@@ -483,12 +528,19 @@
{
const char * str;
size_t length;
- zval *value;
lua_Number n;
- // Convert value, then remove it
+#if PHP_VERSION_ID < 70000
+ zval *value, *valp;
ALLOC_INIT_ZVAL(value);
- if (!luasandbox_lua_to_zval(value, L, -1, sandbox_zval, recursionGuard
TSRMLS_CC)) {
+ valp = value;
+#else
+ zval value, *valp = &value;
+ ZVAL_NULL(&value);
+#endif
+
+ // Convert value, then remove it
+ if (!luasandbox_lua_to_zval(valp, L, -1, sandbox_zval, recursionGuard
TSRMLS_CC)) {
zval_ptr_dtor(&value);
return 0;
}
@@ -499,7 +551,11 @@
n = lua_tonumber(L, -1);
if (isfinite(n) && n == floor(n)) {
// Integer key
+#if PHP_VERSION_ID < 70000
zend_hash_index_update(ht, n, (void*)&value,
sizeof(zval*), NULL);
+#else
+ zend_hash_index_update(ht, n, valp);
+#endif
return 1;
}
}
@@ -509,33 +565,20 @@
str = lua_tolstring(L, -1, &length);
if ( str == NULL ) {
// Only strings and integers may be used as keys
- zval *zex, *ztrace;
char *message;
-
spprintf(&message, 0, "Cannot use %s as an array key when
passing data from Lua to PHP",
lua_typename(L, lua_type(L, -2))
);
-
- MAKE_STD_ZVAL(zex);
- object_init_ex(zex, luasandboxruntimeerror_ce);
-
- ALLOC_INIT_ZVAL(ztrace);
- luasandbox_push_structured_trace(L, 1);
- luasandbox_lua_to_zval(ztrace, L, -1, sandbox_zval, NULL
TSRMLS_CC);
- zend_update_property(luasandboxruntimeerror_ce, zex,
"luaTrace", sizeof("luaTrace")-1, ztrace TSRMLS_CC);
- zval_ptr_dtor(&ztrace);
- lua_pop(L, 1);
-
- zend_update_property_string(luasandboxruntimeerror_ce, zex,
- "message", sizeof("message")-1, message TSRMLS_CC);
- zend_update_property_long(luasandboxruntimeerror_ce, zex,
"code", sizeof("code")-1, -1 TSRMLS_CC);
- zend_throw_exception_object(zex TSRMLS_CC);
-
+ luasandbox_throw_runtimeerror(L, sandbox_zval, message
TSRMLS_CC);
efree(message);
return 0;
}
+#if PHP_VERSION_ID < 70000
zend_hash_update(ht, str, length + 1, (void*)&value, sizeof(zval*),
NULL);
+#else
+ zend_hash_str_update(ht, str, length, valp);
+#endif
lua_pop(L, 1);
return 1;
}
@@ -689,6 +732,43 @@
}
/* }}} */
+/** {{{ luasandbox_throw_runtimeerror
+ *
+ * Create and throw a luasandboxruntimeerror
+ */
+void luasandbox_throw_runtimeerror(lua_State * L, zval * sandbox_zval, const
char *message TSRMLS_DC)
+{
+ zval *zex, *ztrace;
+
+#if PHP_VERSION_ID < 70000
+ MAKE_STD_ZVAL(zex);
+ ALLOC_INIT_ZVAL(ztrace); // IS_NULL if lua_to_zval fails.
+#else
+ zval zvex, zvtrace;
+ zex = &zvex;
+ ztrace = &zvtrace;
+ ZVAL_NULL(ztrace); // IS_NULL if lua_to_zval fails.
+#endif
+
+ object_init_ex(zex, luasandboxruntimeerror_ce);
+
+ luasandbox_push_structured_trace(L, 1);
+ luasandbox_lua_to_zval(ztrace, L, -1, sandbox_zval, NULL TSRMLS_CC);
+ zend_update_property(luasandboxruntimeerror_ce, zex, "luaTrace",
sizeof("luaTrace")-1, ztrace TSRMLS_CC);
+#if PHP_VERSION_ID < 70000
+ zval_ptr_dtor(&ztrace);
+#else
+ zval_ptr_dtor(&zvtrace);
+#endif
+ lua_pop(L, 1);
+
+ zend_update_property_string(luasandboxruntimeerror_ce, zex,
+ "message", sizeof("message")-1, message TSRMLS_CC);
+ zend_update_property_long(luasandboxruntimeerror_ce, zex, "code",
sizeof("code")-1, -1 TSRMLS_CC);
+ zend_throw_exception_object(zex TSRMLS_CC);
+}
+/* }}} */
+
/** {{{ luasandbox_is_recursive
* Check if the recursion flag is set on this hashtable.
*
@@ -700,10 +780,13 @@
static inline int luasandbox_is_recursive(HashTable * ht) {
#ifdef HHVM
return (int)(protectionSet.get()->count(ht));
-#else
+#elif PHP_VERSION_ID < 70000
return ht->nApplyCount;
+#else
+ return ht->u.v.nApplyCount;
#endif
}
+/* }}} */
/** {{{ luasandbox_protect_recursion
*
@@ -712,10 +795,13 @@
static inline void luasandbox_protect_recursion(HashTable * ht) {
#ifdef HHVM
protectionSet.get()->insert(ht);
-#else
+#elif PHP_VERSION_ID < 70000
ht->nApplyCount++;
+#else
+ ht->u.v.nApplyCount++;
#endif
}
+/* }}} */
/** {{{ luasandbox_protect_recursion
*
@@ -724,8 +810,10 @@
static inline void luasandbox_unprotect_recursion(HashTable * ht) {
#ifdef HHVM
protectionSet.get()->erase(ht);
-#else
+#elif PHP_VERSION_ID < 70000
ht->nApplyCount--;
+#else
+ ht->u.v.nApplyCount--;
#endif
}
-
+/* }}} */
diff --git a/library.c b/library.c
index 0734b88..32b807e 100644
--- a/library.c
+++ b/library.c
@@ -134,14 +134,16 @@
while (lua_next(L, LUA_GLOBALSINDEX) != 0) {
const char * key;
size_t key_len;
- void * data;
lua_pop(L, 1);
if (lua_type(L, -1) != LUA_TSTRING) {
continue;
}
key = lua_tolstring(L, -1, &key_len);
- if (zend_hash_find(luasandbox_lib_get_allowed_globals(TSRMLS_C),
- (char*)key, key_len + 1, &data) == FAILURE)
+#if PHP_VERSION_ID < 70000
+ if
(!zend_hash_exists(luasandbox_lib_get_allowed_globals(TSRMLS_C), (char*)key,
key_len + 1))
+#else
+ if
(!zend_hash_str_exists(luasandbox_lib_get_allowed_globals(TSRMLS_C), key,
key_len))
+#endif
{
// Not allowed, delete it
lua_pushnil(L);
@@ -237,10 +239,21 @@
ALLOC_HASHTABLE(LUASANDBOX_G(allowed_globals));
zend_hash_init(LUASANDBOX_G(allowed_globals), n, NULL, NULL, 0);
+
+#if PHP_VERSION_ID >= 70000
+ zval zv;
+ ZVAL_TRUE(&zv);
+#endif
+
for (i = 0; luasandbox_allowed_globals[i]; i++) {
+#if PHP_VERSION_ID < 70000
zend_hash_update(LUASANDBOX_G(allowed_globals),
luasandbox_allowed_globals[i],
strlen(luasandbox_allowed_globals[i]) + 1,
(void*)"", 1, NULL);
+#else
+ zend_hash_str_update(LUASANDBOX_G(allowed_globals),
+ luasandbox_allowed_globals[i],
strlen(luasandbox_allowed_globals[i]), &zv);
+#endif
}
return LUASANDBOX_G(allowed_globals);
diff --git a/luasandbox.c b/luasandbox.c
index 53e273a..d31f9a8 100644
--- a/luasandbox.c
+++ b/luasandbox.c
@@ -14,12 +14,33 @@
#include "zend_exceptions.h"
#include "php_luasandbox.h"
#include "luasandbox_timer.h"
+#if PHP_VERSION_ID < 70000
#include "ext/standard/php_smart_str.h"
+#else
+#include "zend_smart_str.h"
+#endif
#include "luasandbox_version.h"
// Compatability for PHP <= 5.3.6
#ifndef ZEND_FE_END
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
+#endif
+
+// Compatability typedefs and defines to hide some PHP5/PHP7 differences
+#if PHP_VERSION_ID < 70000
+typedef zend_object_value object_constructor_ret_t;
+typedef int str_param_len_t;
+typedef long long_param_t;
+typedef zval*** star_param_t;
+#define compat_zend_register_internal_class_ex(ce, parent_ce)
zend_register_internal_class_ex(ce, parent_ce, NULL TSRMLS_CC)
+#define compat_add_assoc_string(assoc, key, val) add_assoc_string((assoc),
(key), (val), 1)
+#else
+typedef zend_object* object_constructor_ret_t;
+typedef size_t str_param_len_t;
+typedef zend_long long_param_t;
+typedef zval* star_param_t;
+#define compat_zend_register_internal_class_ex(ce, parent_ce)
zend_register_internal_class_ex(ce, parent_ce)
+#define compat_add_assoc_string(assoc, key, val) add_assoc_string((assoc),
(key), (val))
#endif
#define CHECK_VALID_STATE(state) \
@@ -31,10 +52,10 @@
static PHP_GINIT_FUNCTION(luasandbox);
static PHP_GSHUTDOWN_FUNCTION(luasandbox);
static int luasandbox_post_deactivate();
-static zend_object_value luasandbox_new(zend_class_entry *ce TSRMLS_DC);
+static object_constructor_ret_t luasandbox_new(zend_class_entry *ce TSRMLS_DC);
static lua_State * luasandbox_newstate(php_luasandbox_obj * intern TSRMLS_DC);
static void luasandbox_free_storage(void *object TSRMLS_DC);
-static zend_object_value luasandboxfunction_new(zend_class_entry *ce
TSRMLS_DC);
+static object_constructor_ret_t luasandboxfunction_new(zend_class_entry *ce
TSRMLS_DC);
static void luasandboxfunction_free_storage(void *object TSRMLS_DC);
static int luasandbox_panic(lua_State * L);
static lua_State * luasandbox_state_from_zval(zval * this_ptr TSRMLS_DC);
@@ -46,7 +67,7 @@
lua_State ** pstate, php_luasandbox_obj ** psandbox TSRMLS_DC);
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);
+ star_param_t args, int numArgs, zval * return_value TSRMLS_DC);
static void luasandbox_handle_error(php_luasandbox_obj * sandbox, int status
TSRMLS_DC);
static int luasandbox_dump_writer(lua_State * L, const void * p, size_t sz,
void * ud);
static zend_bool luasandbox_instanceof(
@@ -73,6 +94,11 @@
zend_class_entry *luasandboxfunction_ce;
ZEND_DECLARE_MODULE_GLOBALS(luasandbox);
+
+#if PHP_VERSION_ID >= 70000
+static zend_object_handlers luasandbox_object_handlers;
+static zend_object_handlers luasandboxfunction_object_handlers;
+#endif
/** {{{ arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_luasandbox_getVersionInfo, 0)
@@ -234,8 +260,7 @@
"PERCENT", sizeof("PERCENT")-1, LUASANDBOX_PERCENT TSRMLS_CC);
INIT_CLASS_ENTRY(ce, "LuaSandboxError", luasandbox_empty_methods);
- luasandboxerror_ce = zend_register_internal_class_ex(
- &ce, zend_exception_get_default(TSRMLS_C), NULL
TSRMLS_CC);
+ luasandboxerror_ce = compat_zend_register_internal_class_ex(&ce,
zend_exception_get_default(TSRMLS_C));
zend_declare_class_constant_long(luasandboxerror_ce,
"RUN", sizeof("RUN")-1, LUA_ERRRUN TSRMLS_CC);
zend_declare_class_constant_long(luasandboxerror_ce,
@@ -246,37 +271,37 @@
"ERR", sizeof("ERR")-1, LUA_ERRERR TSRMLS_CC);
INIT_CLASS_ENTRY(ce, "LuaSandboxRuntimeError",
luasandbox_empty_methods);
- luasandboxruntimeerror_ce = zend_register_internal_class_ex(
- &ce, luasandboxerror_ce, NULL TSRMLS_CC);
+ luasandboxruntimeerror_ce = compat_zend_register_internal_class_ex(&ce,
luasandboxerror_ce);
INIT_CLASS_ENTRY(ce, "LuaSandboxFatalError", luasandbox_empty_methods);
- luasandboxfatalerror_ce = zend_register_internal_class_ex(
- &ce, luasandboxerror_ce, NULL TSRMLS_CC);
+ luasandboxfatalerror_ce = compat_zend_register_internal_class_ex(&ce,
luasandboxerror_ce);
INIT_CLASS_ENTRY(ce, "LuaSandboxSyntaxError", luasandbox_empty_methods);
- luasandboxsyntaxerror_ce = zend_register_internal_class_ex(
- &ce, luasandboxfatalerror_ce, NULL TSRMLS_CC);
+ luasandboxsyntaxerror_ce = compat_zend_register_internal_class_ex(&ce,
luasandboxfatalerror_ce);
INIT_CLASS_ENTRY(ce, "LuaSandboxMemoryError", luasandbox_empty_methods);
- luasandboxmemoryerror_ce = zend_register_internal_class_ex(
- &ce, luasandboxfatalerror_ce, NULL TSRMLS_CC);
+ luasandboxmemoryerror_ce = compat_zend_register_internal_class_ex(&ce,
luasandboxfatalerror_ce);
INIT_CLASS_ENTRY(ce, "LuaSandboxErrorError", luasandbox_empty_methods);
- luasandboxerrorerror_ce = zend_register_internal_class_ex(
- &ce, luasandboxfatalerror_ce, NULL TSRMLS_CC);
+ luasandboxerrorerror_ce = compat_zend_register_internal_class_ex(&ce,
luasandboxfatalerror_ce);
INIT_CLASS_ENTRY(ce, "LuaSandboxTimeoutError",
luasandbox_empty_methods);
- luasandboxtimeouterror_ce = zend_register_internal_class_ex(
- &ce, luasandboxfatalerror_ce, NULL TSRMLS_CC);
+ luasandboxtimeouterror_ce = compat_zend_register_internal_class_ex(&ce,
luasandboxfatalerror_ce);
// Deprecated, for catch blocks only
INIT_CLASS_ENTRY(ce, "LuaSandboxEmergencyTimeoutError",
luasandbox_empty_methods);
- luasandboxemergencytimeouterror_ce = zend_register_internal_class_ex(
- &ce, luasandboxfatalerror_ce, NULL TSRMLS_CC);
+ luasandboxemergencytimeouterror_ce =
compat_zend_register_internal_class_ex(&ce, luasandboxfatalerror_ce);
INIT_CLASS_ENTRY(ce, "LuaSandboxFunction", luasandboxfunction_methods);
luasandboxfunction_ce = zend_register_internal_class(&ce TSRMLS_CC);
luasandboxfunction_ce->create_object = luasandboxfunction_new;
+
+#if PHP_VERSION_ID >= 70000
+ memcpy(&luasandbox_object_handlers, zend_get_std_object_handlers(),
sizeof(zend_object_handlers));
+ luasandbox_object_handlers.free_obj =
(zend_object_free_obj_t)luasandbox_free_storage;
+ memcpy(&luasandboxfunction_object_handlers,
zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ luasandboxfunction_object_handlers.free_obj =
(zend_object_free_obj_t)luasandboxfunction_free_storage;
+#endif
luasandbox_timer_minit(TSRMLS_C);
@@ -343,10 +368,9 @@
*
* "new" handler for the LuaSandbox class
*/
-static zend_object_value luasandbox_new(zend_class_entry *ce TSRMLS_DC)
+static object_constructor_ret_t luasandbox_new(zend_class_entry *ce TSRMLS_DC)
{
php_luasandbox_obj * sandbox;
- zend_object_value retval;
// Create the internal object
sandbox = (php_luasandbox_obj*)emalloc(sizeof(php_luasandbox_obj));
@@ -364,7 +388,9 @@
// Initialise the timer
luasandbox_timer_create(&sandbox->timer, sandbox);
+#if PHP_VERSION_ID < 70000
// Put the object into the store
+ zend_object_value retval;
retval.handle = zend_objects_store_put(
sandbox,
(zend_objects_store_dtor_t)zend_objects_destroy_object,
@@ -373,6 +399,11 @@
retval.handlers = zend_get_std_object_handlers();
LUASANDBOX_G(active_count)++;
return retval;
+#else
+ sandbox->std.handlers = &luasandbox_object_handlers;
+ LUASANDBOX_G(active_count)++;
+ return &sandbox->std;
+#endif
}
/* }}} */
@@ -424,7 +455,9 @@
sandbox->state = NULL;
}
zend_object_std_dtor(&sandbox->std TSRMLS_CC);
+#if PHP_VERSION_ID < 70000
efree(object);
+#endif
LUASANDBOX_G(active_count)--;
}
/* }}} */
@@ -433,10 +466,9 @@
*
* "new" handler for the LuaSandboxFunction class.
*/
-static zend_object_value luasandboxfunction_new(zend_class_entry *ce TSRMLS_DC)
+static object_constructor_ret_t luasandboxfunction_new(zend_class_entry *ce
TSRMLS_DC)
{
php_luasandboxfunction_obj * intern;
- zend_object_value retval;
// Create the internal object
intern =
(php_luasandboxfunction_obj*)emalloc(sizeof(php_luasandboxfunction_obj));
@@ -446,7 +478,9 @@
object_properties_init(&intern->std, ce);
#endif
+#if PHP_VERSION_ID < 70000
// Put the object into the store
+ zend_object_value retval;
retval.handle = zend_objects_store_put(
intern,
(zend_objects_store_dtor_t)zend_objects_destroy_object,
@@ -454,6 +488,10 @@
NULL TSRMLS_CC);
retval.handlers = zend_get_std_object_handlers();
return retval;
+#else
+ intern->std.handlers = &luasandboxfunction_object_handlers;
+ return &intern->std;
+#endif
}
/* }}} */
@@ -466,9 +504,9 @@
static void luasandboxfunction_free_storage(void *object TSRMLS_DC)
{
php_luasandboxfunction_obj * func = (php_luasandboxfunction_obj*)object;
- if (func->sandbox) {
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(func->sandbox TSRMLS_CC);
+ if (LUASANDBOXFUNCTION_SANDBOX_IS_OK(func)) {
+ zval *zsandbox = LUASANDBOXFUNCTION_GET_SANDBOX_ZVALPTR(func);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(zsandbox);
if (sandbox && sandbox->state) {
lua_State * L = sandbox->state;
@@ -483,9 +521,16 @@
// Delete the parent reference
zval_ptr_dtor(&func->sandbox);
+#if PHP_VERSION_ID < 70000
+ func->sandbox = NULL;
+#else
+ ZVAL_UNDEF(&func->sandbox);
+#endif
}
zend_object_std_dtor(&func->std TSRMLS_CC);
+#if PHP_VERSION_ID < 70000
efree(object);
+#endif
}
/* }}} */
@@ -522,8 +567,7 @@
*/
static lua_State * luasandbox_state_from_zval(zval * this_ptr TSRMLS_DC)
{
- php_luasandbox_obj * intern = (php_luasandbox_obj*)
- zend_object_store_get_object(this_ptr TSRMLS_CC);
+ php_luasandbox_obj * intern = GET_LUASANDBOX_OBJ(this_ptr);
return intern->state;
}
/* }}} */
@@ -536,15 +580,14 @@
static void luasandbox_load_helper(int binary, INTERNAL_FUNCTION_PARAMETERS)
{
char *code, *chunkName = NULL;
- int codeLength, chunkNameLength;
+ str_param_len_t codeLength, chunkNameLength;
int status;
lua_State * L;
int have_mark;
php_luasandbox_obj * sandbox;
int was_paused;
- sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(this_ptr TSRMLS_CC);
+ sandbox = GET_LUASANDBOX_OBJ(getThis());
L = sandbox->state;
CHECK_VALID_STATE(L);
@@ -598,7 +641,7 @@
}
// Make a zval out of it, and return false on error
- if (!luasandbox_lua_to_zval(return_value, L, lua_gettop(L), this_ptr,
NULL TSRMLS_CC) ||
+ if (!luasandbox_lua_to_zval(return_value, L, lua_gettop(L), getThis(),
NULL TSRMLS_CC) ||
Z_TYPE_P(return_value) == IS_NULL
) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
@@ -618,10 +661,10 @@
PHP_METHOD(LuaSandbox, getVersionInfo)
{
array_init_size(return_value, 2);
- add_assoc_string(return_value, "LuaSandbox", LUASANDBOX_VERSION, 1);
- add_assoc_string(return_value, "Lua", LUA_RELEASE, 1);
+ compat_add_assoc_string(return_value, "LuaSandbox", LUASANDBOX_VERSION);
+ compat_add_assoc_string(return_value, "Lua", LUA_RELEASE);
#ifdef LUAJIT_VERSION
- add_assoc_string(return_value, "LuaJIT", LUAJIT_VERSION, 1);
+ compat_add_assoc_string(return_value, "LuaJIT", LUAJIT_VERSION);
#endif
}
@@ -667,6 +710,16 @@
zend_class_entry * ce;
zval *zex, *ztrace;
+#if PHP_VERSION_ID < 70000
+ MAKE_STD_ZVAL(zex);
+ ALLOC_INIT_ZVAL(ztrace); // IS_NULL if lua_to_zval fails.
+#else
+ zval zvex, zvtrace;
+ zex = &zvex;
+ ztrace = &zvtrace;
+ ZVAL_NULL(ztrace);
+#endif
+
if (EG(exception)) {
lua_pop(L, 1);
return;
@@ -696,20 +749,22 @@
break;
}
- MAKE_STD_ZVAL(zex);
object_init_ex(zex, ce);
if (luasandbox_is_trace_error(L, -1)) {
// Push the trace on to the top of the stack
lua_rawgeti(L, -1, 3);
// Convert it to a zval
- ALLOC_INIT_ZVAL(ztrace); // IS_NULL if lua_to_zval fails.
- luasandbox_lua_to_zval(ztrace, L, -1, sandbox->current_zval,
NULL TSRMLS_CC);
+ luasandbox_lua_to_zval(ztrace, L, -1,
LUASANDBOX_GET_CURRENT_ZVAL_PTR(sandbox), NULL TSRMLS_CC);
// Put it in the exception object
zend_update_property(ce, zex, "luaTrace", sizeof("luaTrace")-1,
ztrace TSRMLS_CC);
- zval_ptr_dtor(&ztrace);
lua_pop(L, 1);
}
+#if PHP_VERSION_ID < 70000
+ zval_ptr_dtor(&ztrace);
+#else
+ zval_ptr_dtor(&zvtrace);
+#endif
// Initialise standard properties
// We would get Zend to do this, but the code for it is wrapped inside
some
@@ -733,9 +788,8 @@
*/
PHP_METHOD(LuaSandbox, setMemoryLimit)
{
- long limit;
- php_luasandbox_obj * intern = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ long_param_t limit;
+ php_luasandbox_obj * intern = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
&limit) == FAILURE)
@@ -765,8 +819,7 @@
{
zval *zp_limit = NULL;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
struct timespec limit = {0, 0};
@@ -777,8 +830,12 @@
}
if (!zp_limit
- || (Z_TYPE_P(zp_limit) == IS_BOOL && Z_BVAL_P(zp_limit) == 0))
- {
+#ifdef IS_BOOL
+ || (Z_TYPE_P(zp_limit) == IS_BOOL && Z_BVAL_P(zp_limit) == 0)
+#else
+ || Z_TYPE_P(zp_limit) == IS_FALSE
+#endif
+ ) {
// No limit
sandbox->is_cpu_limited = 0;
} else {
@@ -823,8 +880,7 @@
PHP_METHOD(LuaSandbox, getCPUUsage)
{
struct timespec ts;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
@@ -854,8 +910,7 @@
*/
PHP_METHOD(LuaSandbox, pauseUsageTimer)
{
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
@@ -876,8 +931,7 @@
*/
PHP_METHOD(LuaSandbox, unpauseUsageTimer)
{
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
@@ -901,8 +955,7 @@
{
double period = 2e-3;
struct timespec ts;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|d", &period) ==
FAILURE) {
RETURN_FALSE;
}
@@ -919,8 +972,7 @@
PHP_METHOD(LuaSandbox, disableProfiler)
{
struct timespec ts = {0, 0};
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
luasandbox_timer_enable_profiler(&sandbox->timer, &ts);
}
/* }}} */
@@ -930,10 +982,17 @@
Bucket *bucket_a, *bucket_b;
size_t value_a, value_b;
+#if PHP_VERSION_ID < 70000
bucket_a = *((Bucket **) a);
bucket_b = *((Bucket **) b);
value_a = *(size_t*)bucket_a->pData;
value_b = *(size_t*)bucket_b->pData;
+#else
+ bucket_a = (Bucket *) a;
+ bucket_b = (Bucket *) b;
+ value_a = (size_t)Z_LVAL(bucket_a->val);
+ value_b = (size_t)Z_LVAL(bucket_b->val);
+#endif
if (value_a < value_b) {
return 1;
@@ -960,10 +1019,8 @@
*/
PHP_METHOD(LuaSandbox, getProfilerFunctionReport)
{
- long units = LUASANDBOX_SECONDS;
- HashPosition p;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ long_param_t units = LUASANDBOX_SECONDS;
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &units) ==
FAILURE) {
RETURN_FALSE;
}
@@ -984,7 +1041,11 @@
}
// Sort the input array in descending order of time usage
+#if PHP_VERSION_ID < 70000
zend_hash_sort(counts, zend_qsort, luasandbox_sort_profile, 0
TSRMLS_CC);
+#else
+ zend_hash_sort_ex(counts, zend_qsort, luasandbox_sort_profile, 0);
+#endif
array_init_size(return_value, zend_hash_num_elements(counts));
@@ -999,6 +1060,8 @@
}
}
+#if PHP_VERSION_ID < 70000
+ HashPosition p;
for (zend_hash_internal_pointer_reset_ex(counts, &p);
zend_hash_get_current_key_type_ex(counts, &p) !=
HASH_KEY_NON_EXISTANT;
zend_hash_move_forward_ex(counts, &p))
@@ -1017,6 +1080,20 @@
add_assoc_double_ex(return_value, func_name,
func_name_length, *count * scale);
}
}
+#else
+ zend_string *key;
+ zval *count, v;
+ ZVAL_NULL(&v);
+ ZEND_HASH_FOREACH_STR_KEY_VAL(counts, key, count)
+ {
+ if (units == LUASANDBOX_SAMPLES) {
+ zend_hash_add(Z_ARRVAL_P(return_value), key, count);
+ } else {
+ ZVAL_LONG(&v, Z_LVAL_P(count) * scale);
+ zend_hash_add(Z_ARRVAL_P(return_value), key, &v);
+ }
+ } ZEND_HASH_FOREACH_END();
+#endif
#ifdef LUASANDBOX_REPORT_OVERRUNS
if (units == LUASANDBOX_SAMPLES) {
@@ -1032,8 +1109,7 @@
/** {{{ LuaSandbox::getMemoryUsage */
PHP_METHOD(LuaSandbox, getMemoryUsage)
{
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
@@ -1046,8 +1122,7 @@
/** {{{ LuaSandbox::getPeakMemoryUsage */
PHP_METHOD(LuaSandbox, getPeakMemoryUsage)
{
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
RETURN_FALSE;
@@ -1075,12 +1150,11 @@
PHP_METHOD(LuaSandbox, callFunction)
{
char *name;
- int nameLength = 0;
- zend_uint numArgs = 0;
- zval *** args = NULL;
+ str_param_len_t nameLength = 0;
+ int numArgs = 0;
+ star_param_t args = NULL;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
lua_State * L = sandbox->state;
CHECK_VALID_STATE(L);
@@ -1100,10 +1174,12 @@
luasandbox_call_helper(L, getThis(), sandbox, args, numArgs,
return_value TSRMLS_CC);
}
+#if PHP_VERSION_ID < 70000
// Delete varargs
if (numArgs) {
efree(args);
}
+#endif
}
/* }}} */
@@ -1119,8 +1195,7 @@
{
zval *z;
- php_luasandbox_obj * sandbox = (php_luasandbox_obj*)
- zend_object_store_get_object(getThis() TSRMLS_CC);
+ php_luasandbox_obj * sandbox = GET_LUASANDBOX_OBJ(getThis());
lua_State * L = sandbox->state;
CHECK_VALID_STATE(L);
@@ -1133,7 +1208,7 @@
luasandbox_push_zval_userdata(L, z);
lua_pushcclosure(L, luasandbox_call_php, 1);
- if (!luasandbox_lua_to_zval(return_value, L, lua_gettop(L), this_ptr,
NULL TSRMLS_CC) ||
+ if (!luasandbox_lua_to_zval(return_value, L, lua_gettop(L), getThis(),
NULL TSRMLS_CC) ||
Z_TYPE_P(return_value) == IS_NULL
) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
@@ -1153,16 +1228,15 @@
static int luasandbox_function_init(zval * this_ptr,
php_luasandboxfunction_obj ** pfunc,
lua_State ** pstate, php_luasandbox_obj ** psandbox TSRMLS_DC)
{
- *pfunc = (php_luasandboxfunction_obj *)
- zend_object_store_get_object(this_ptr TSRMLS_CC);
- if (!*pfunc || !(*pfunc)->sandbox || !(*pfunc)->index) {
+ *pfunc = GET_LUASANDBOXFUNCTION_OBJ(this_ptr);
+ if (!*pfunc || !LUASANDBOXFUNCTION_SANDBOX_IS_OK(*pfunc) ||
!(*pfunc)->index) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"attempt to call uninitialized LuaSandboxFunction
object" );
return 0;
}
- *psandbox = (php_luasandbox_obj*)
- zend_object_store_get_object((*pfunc)->sandbox TSRMLS_CC);
+ zval *zsandbox = LUASANDBOXFUNCTION_GET_SANDBOX_ZVALPTR(*pfunc);
+ *psandbox = GET_LUASANDBOX_OBJ(zsandbox);
*pstate = (*psandbox)->state;
if (!*pstate) {
@@ -1209,8 +1283,8 @@
*/
PHP_METHOD(LuaSandboxFunction, call)
{
- zend_uint numArgs = 0;
- zval *** args = NULL;
+ int numArgs = 0;
+ star_param_t args = NULL;
php_luasandboxfunction_obj * func;
lua_State * L;
@@ -1227,12 +1301,15 @@
}
// Call the function
- luasandbox_call_helper(L, func->sandbox, sandbox, args, numArgs,
return_value TSRMLS_CC);
+ luasandbox_call_helper(L, LUASANDBOXFUNCTION_GET_SANDBOX_ZVALPTR(func),
+ sandbox, args, numArgs, return_value TSRMLS_CC);
+#if PHP_VERSION_ID < 70000
// Delete varargs
if (numArgs) {
efree(args);
}
+#endif
}
/** }}} */
@@ -1246,7 +1323,11 @@
{
int status;
int timer_started = 0;
+#if PHP_VERSION_ID < 70000
zval * old_zval;
+#else
+ zval old_zval;
+#endif
int was_paused;
int old_allow_pause;
@@ -1267,8 +1348,13 @@
// Save the current zval for later use in luasandbox_call_php. Restore
it
// after execution finishes, to support re-entrancy.
+#if PHP_VERSION_ID < 70000
old_zval = sandbox->current_zval;
sandbox->current_zval = sandbox_zval;
+#else
+ ZVAL_COPY_VALUE(&old_zval, &sandbox->current_zval);
+ ZVAL_COPY_VALUE(&sandbox->current_zval, sandbox_zval);
+#endif
// Make sure this is counted against the Lua usage time limit, and set
the
// allow_pause flag.
@@ -1281,7 +1367,11 @@
sandbox->in_lua++;
status = lua_pcall(sandbox->state, nargs, nresults, errfunc);
sandbox->in_lua--;
+#if PHP_VERSION_ID < 70000
sandbox->current_zval = old_zval;
+#else
+ ZVAL_COPY_VALUE(&sandbox->current_zval, &old_zval);
+#endif
// Restore pause state
sandbox->allow_pause = old_allow_pause;
@@ -1310,13 +1400,14 @@
* to an array containing all the results.
*/
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)
+ star_param_t args, int numArgs, zval * return_value TSRMLS_DC)
{
// Save the top position
int origTop = lua_gettop(L);
// Keep track of the stack index where the return values will appear
int retIndex = origTop + 2;
int i, numResults;
+ zval *v;
// Check to see if the value is a valid function
if (lua_type(L, -1) != LUA_TFUNCTION) {
@@ -1340,7 +1431,12 @@
RETURN_FALSE;
}
for (i = 0; i < numArgs; i++) {
- if (!luasandbox_push_zval(L, *(args[i]))) {
+#if PHP_VERSION_ID < 70000
+ v = *(args[i]);
+#else
+ v = &(args[i]);
+#endif
+ if (!luasandbox_push_zval(L, v)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"unable to convert argument %d to a lua value",
i + 1);
lua_settop(L, origTop - 1);
@@ -1360,6 +1456,7 @@
// Fill the array with the results
for (i = 0; i < numResults; i++) {
+#if PHP_VERSION_ID < 70000
zval * element;
ALLOC_INIT_ZVAL(element); // ensure elem is inited in case we
bail
if (!luasandbox_lua_to_zval(element, L, retIndex + i,
sandbox_zval, NULL TSRMLS_CC)) {
@@ -1370,6 +1467,16 @@
zend_hash_next_index_insert(Z_ARRVAL_P(return_value),
(void*)&element,
sizeof(zval*), NULL);
+#else
+ zval element;
+ ZVAL_NULL(&element); // ensure elem is inited in case we bail
+ if (!luasandbox_lua_to_zval(&element, L, retIndex + i,
sandbox_zval, NULL TSRMLS_CC)) {
+ // Convert failed (which means an exception), so bail.
+ zval_ptr_dtor(&element);
+ break;
+ }
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &element);
+#endif
}
// Balance the stack
@@ -1463,10 +1570,9 @@
{
lua_State * L = luasandbox_state_from_zval(getThis() TSRMLS_CC);
char * libname = NULL;
- int libname_len = 0;
+ str_param_len_t libname_len = 0;
zval * zfunctions = NULL;
HashTable * functions;
- HashPosition p;
CHECK_VALID_STATE(L);
@@ -1491,6 +1597,8 @@
lua_createtable(L, 0, zend_hash_num_elements(functions));
}
+#if PHP_VERSION_ID < 70000
+ HashPosition p;
for (zend_hash_internal_pointer_reset_ex(functions, &p);
zend_hash_get_current_key_type_ex(functions, &p) !=
HASH_KEY_NON_EXISTANT;
zend_hash_move_forward_ex(functions, &p))
@@ -1518,6 +1626,27 @@
// Add it to the table
lua_rawset(L, -3);
}
+#else
+ ulong lkey;
+ zend_string *key;
+ zval *callback;
+ ZEND_HASH_FOREACH_KEY_VAL(functions, lkey, key, callback)
+ {
+ // Push the key
+ if ( key ) {
+ lua_pushlstring(L, ZSTR_VAL(key), ZSTR_LEN(key));
+ } else {
+ lua_pushinteger(L, lkey);
+ }
+
+ // Push the callback zval and create the closure
+ luasandbox_push_zval_userdata(L, callback);
+ lua_pushcclosure(L, luasandbox_call_php, 1);
+
+ // Add it to the table
+ lua_rawset(L, -3);
+ } ZEND_HASH_FOREACH_END();
+#endif
// Move the new table to the global namespace
// The key is on the stack already
@@ -1553,24 +1682,24 @@
luasandbox_enter_php(L, intern);
- zval ** callback_pp = (zval**)lua_touserdata(L, lua_upvalueindex(1));
- zval *retval_ptr = NULL;
+ zval * callback_p;
+#if PHP_VERSION_ID < 70000
+ callback_p = *(zval**)lua_touserdata(L, lua_upvalueindex(1));
+#else
+ callback_p = (zval*)lua_touserdata(L, lua_upvalueindex(1));
+#endif
zend_fcall_info fci;
zend_fcall_info_cache fcc;
char *is_callable_error = NULL;
int top = lua_gettop(L);
int i;
- void **temp;
- zval **pointers;
- zval ***double_pointers;
int num_results = 0;
int status;
- HashPosition p;
HashTable * ht;
TSRMLS_FETCH();
// Based on zend_parse_arg_impl()
- if (zend_fcall_info_init(*callback_pp, 0, &fci, &fcc, NULL,
+ if (zend_fcall_info_init(callback_p, 0, &fci, &fcc, NULL,
&is_callable_error TSRMLS_CC) != SUCCESS)
{
// Handle errors similar to the way PHP does it: show a warning
and
@@ -1583,14 +1712,22 @@
return 1;
}
+#if PHP_VERSION_ID < 70000
+ zval *retval_ptr = NULL;
fci.retval_ptr_ptr = &retval_ptr;
+#else
+ zval retval;
+ fci.retval = &retval;
+#endif
// Make an array of zval double-pointers to hold the arguments
int args_failed = 0;
- temp = (void**)ecalloc(top, sizeof(void*) * 2);
- double_pointers = (zval***)temp;
- pointers = (zval**)(temp + top);
+ star_param_t args;
+#if PHP_VERSION_ID < 70000
+ args = (zval***)ecalloc(top * 2, sizeof(void*));
+ zval **pointers = (zval**)(args + top);
for (i = 0; i < top; i++ ) {
+ args[i] = &(pointers[i]);
ALLOC_INIT_ZVAL(pointers[i]); // ensure is inited in case we
fail
if (!luasandbox_lua_to_zval(pointers[i], L, i + 1,
intern->current_zval, NULL TSRMLS_CC)) {
// Argument conversion failed, so skip the call. The
PHP exception
@@ -1600,14 +1737,27 @@
top = i + 1;
break;
}
- double_pointers[i] = &(pointers[i]);
}
+#else
+ args = (zval *)ecalloc(top, sizeof(zval));
+ for (i = 0; i < top; i++ ) {
+ ZVAL_NULL(&args[i]); // ensure is inited in case we fail
+ if (!luasandbox_lua_to_zval(&args[i], L, i + 1,
&intern->current_zval, NULL TSRMLS_CC)) {
+ // Argument conversion failed, so skip the call. The
PHP exception
+ // from the conversion will be handled below, along
with freeing
+ // all the zvals in args[0 <= i < top].
+ args_failed = 1;
+ top = i + 1;
+ break;
+ }
+ }
+#endif
if (!args_failed) {
// Initialise the fci. Use zend_fcall_info_args_restore() since
that's an
// almost-legitimate way to avoid the extra malloc that we'd
get from
// zend_fcall_info_argp()
- zend_fcall_info_args_restore(&fci, top, double_pointers);
+ zend_fcall_info_args_restore(&fci, top, args);
// Sanity check, timers should never be paused at this point
assert(!luasandbox_timer_is_paused(&intern->timer));
@@ -1618,14 +1768,15 @@
// Automatically unpause now that PHP has returned
luasandbox_timer_unpause(&intern->timer);
- if (status == SUCCESS && fci.retval_ptr_ptr &&
*fci.retval_ptr_ptr)
- {
+#if PHP_VERSION_ID < 70000
+ if (status == SUCCESS && fci.retval_ptr_ptr &&
*fci.retval_ptr_ptr) {
// Push the return values back to Lua
if (Z_TYPE_PP(fci.retval_ptr_ptr) == IS_NULL) {
// No action
} else if (Z_TYPE_PP(fci.retval_ptr_ptr) == IS_ARRAY) {
ht = Z_ARRVAL_PP(fci.retval_ptr_ptr);
luaL_checkstack(L, zend_hash_num_elements(ht) +
10, "converting PHP return array to Lua");
+ HashPosition p;
for (zend_hash_internal_pointer_reset_ex(ht,
&p);
zend_hash_get_current_key_type_ex(ht, &p) != HASH_KEY_NON_EXISTANT;
zend_hash_move_forward_ex(ht,
&p))
@@ -1641,22 +1792,53 @@
}
zval_ptr_dtor(&retval_ptr);
}
+#else
+ if (status == SUCCESS) {
+ // Push the return values back to Lua
+ if (Z_ISNULL_P(fci.retval) || Z_ISUNDEF_P(fci.retval)) {
+ // No action
+ } else if (Z_TYPE_P(fci.retval) == IS_ARRAY) {
+ ht = Z_ARRVAL_P(fci.retval);
+ luaL_checkstack(L, zend_hash_num_elements(ht) +
10, "converting PHP return array to Lua");
+
+ zval *value;
+ ZEND_HASH_FOREACH_VAL(ht, value)
+ {
+ luasandbox_push_zval(L, value);
+ num_results++;
+ } ZEND_HASH_FOREACH_END();
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "function tried to return a single
value to Lua without wrapping it in an array");
+ }
+ zval_ptr_dtor(&retval);
+ }
+#endif
}
// Free the argument zvals
for (i = 0; i < top; i++) {
- zval_ptr_dtor(&(pointers[i]));
+#if PHP_VERSION_ID < 70000
+ zval_ptr_dtor(args[i]);
+#else
+ zval_ptr_dtor(&(args[i]));
+#endif
}
-
- // Free the pointer arrays
- efree(temp);
+ efree(args);
luasandbox_leave_php(L, intern);
// If an exception occurred, convert it to a Lua error
if (EG(exception)) {
// Get the error message and push it to the stack
+#if PHP_VERSION_ID < 70000
zend_class_entry * ce = Z_OBJCE_P(EG(exception));
zval * zmsg = zend_read_property(ce, EG(exception), "message",
sizeof("message")-1, 1 TSRMLS_CC);
+#else
+ zval exception, rv;
+ ZVAL_OBJ(&exception, EG(exception));
+ zend_class_entry * ce = Z_OBJCE(exception);
+ zval * zmsg = zend_read_property(ce, &exception, "message",
sizeof("message")-1, 1, &rv);
+#endif
if (zmsg && Z_TYPE_P(zmsg) == IS_STRING) {
lua_pushlstring(L, Z_STRVAL_P(zmsg), Z_STRLEN_P(zmsg));
} else {
@@ -1699,8 +1881,13 @@
lua_dump(L, luasandbox_dump_writer, (void*)&buf);
smart_str_0(&buf);
+#if PHP_VERSION_ID < 70000
if (buf.len) {
RETURN_STRINGL(buf.c, buf.len, 0);
+#else
+ if (buf.s) {
+ RETURN_STR(buf.s);
+#endif
} else {
smart_str_free(&buf);
RETURN_EMPTY_STRING();
diff --git a/luasandbox_types.h b/luasandbox_types.h
index a5e5a4c..e437f9f 100644
--- a/luasandbox_types.h
+++ b/luasandbox_types.h
@@ -77,7 +77,11 @@
php_luasandbox_alloc alloc;
int in_php;
int in_lua;
+#if PHP_VERSION_ID < 70000
zval * current_zval; /* The zval for the LuaSandbox which is currently
executing Lua code */
+#else
+ zval current_zval; /* The zval for the LuaSandbox which is currently
executing Lua code */
+#endif
volatile int timed_out;
int is_cpu_limited;
luasandbox_timer_set timer;
@@ -89,10 +93,29 @@
struct _php_luasandboxfunction_obj {
zend_object std;
+#if PHP_VERSION_ID < 70000
zval * sandbox;
+#else
+ zval sandbox;
+#endif
int index;
};
typedef struct _php_luasandboxfunction_obj php_luasandboxfunction_obj;
+// Accessor macros
+#if PHP_VERSION_ID < 70000
+#define GET_LUASANDBOX_OBJ(z) (php_luasandbox_obj
*)zend_object_store_get_object(z TSRMLS_CC)
+#define GET_LUASANDBOXFUNCTION_OBJ(z) (php_luasandboxfunction_obj
*)zend_object_store_get_object(z TSRMLS_CC)
+#define LUASANDBOXFUNCTION_SANDBOX_IS_OK(pfunc) (pfunc)->sandbox
+#define LUASANDBOXFUNCTION_GET_SANDBOX_ZVALPTR(pfunc) (pfunc)->sandbox
+#define LUASANDBOX_GET_CURRENT_ZVAL_PTR(psandbox) (psandbox)->current_zval
+#else
+#define GET_LUASANDBOX_OBJ(z) (php_luasandbox_obj *)Z_OBJ_P(z)
+#define GET_LUASANDBOXFUNCTION_OBJ(z) (php_luasandboxfunction_obj *)Z_OBJ_P(z)
+#define LUASANDBOXFUNCTION_SANDBOX_IS_OK(pfunc) !Z_ISUNDEF((pfunc)->sandbox)
+#define LUASANDBOXFUNCTION_GET_SANDBOX_ZVALPTR(pfunc) &((pfunc)->sandbox)
+#define LUASANDBOX_GET_CURRENT_ZVAL_PTR(psandbox) &((psandbox)->current_zval)
+#endif
+
#endif /*LUASANDBOX_TYPES_H*/
diff --git a/tests/datatypes.phpt b/tests/datatypes.phpt
new file mode 100644
index 0000000..50443dd
--- /dev/null
+++ b/tests/datatypes.phpt
@@ -0,0 +1,55 @@
+--TEST--
+Data type round-tripping
+--FILE--
+<?php
+
+function doTest( $test, $data ) {
+ printf( "%-25s ", "$test:" );
+
+ $sandbox = new LuaSandbox;
+ $sandbox->setMemoryLimit( 100000 );
+ $sandbox->setCPULimit( 0.1 );
+ try {
+ $ret = $sandbox->loadString( 'return ...' )->call( $data );
+ printf( "%s\n", preg_replace( '/\s+/', ' ', var_export(
$ret[0], 1 ) ) );
+ } catch ( LuaSandboxError $e ) {
+ printf( "EXCEPTION: %s\n", $e->getMessage() );
+ }
+}
+
+doTest( 'null', null );
+doTest( 'int', 123 );
+doTest( 'long', 17179869184 );
+doTest( 'double', 3.125 );
+doTest( 'NAN', NAN );
+doTest( 'INF', INF );
+doTest( 'true', true );
+doTest( 'false', false );
+doTest( 'string', 'foobar' );
+doTest( 'empty string', '' );
+doTest( 'string containing NULs', "foo\0bar" );
+doTest( 'array', array( 'foo', 'bar' ) );
+doTest( 'associative array', array( 'foo', 'bar' => 'baz' ) );
+doTest( 'object', (object)array( 'foo' => 1, 'bar' => 'baz' ) );
+doTest( 'object with numeric keys', (object)array( 'foo', 'bar' ) );
+
+$var = 42;
+doTest( 'array with reference', [ &$var ] );
+
+--EXPECT--
+null: NULL
+int: 123
+long: 17179869184
+double: 3.125
+NAN: NAN
+INF: INF
+true: true
+false: false
+string: 'foobar'
+empty string: ''
+string containing NULs: 'foo' . "\0" . 'bar'
+array: array ( 1 => 'bar', 0 => 'foo', )
+associative array: array ( 0 => 'foo', 'bar' => 'baz', )
+object: array ( 'bar' => 'baz', 'foo' => 1, )
+object with numeric keys: array ( 1 => 'bar', 0 => 'foo', )
+array with reference: array ( 0 => 42, )
diff --git a/timer.c b/timer.c
index 98494e6..b6baf67 100644
--- a/timer.c
+++ b/timer.c
@@ -239,13 +239,29 @@
}
lua_getupvalue(L, -1, 1);
+#if PHP_VERSION_ID < 70000
zval ** callback_pp = (zval**)lua_touserdata(L, -1);
if (!callback_pp || !*callback_pp) {
return NULL;
}
char * callback_name;
- if (zend_is_callable(*callback_pp, IS_CALLABLE_CHECK_SILENT,
&callback_name TSRMLS_CC)) {
- snprintf(buffer, sizeof(buffer), "%s", callback_name);
+ zend_bool ok = zend_is_callable(*callback_pp, IS_CALLABLE_CHECK_SILENT,
&callback_name TSRMLS_CC);
+#else
+ zval * callback_p = (zval*)lua_touserdata(L, -1);
+ if (!callback_p) {
+ return NULL;
+ }
+ zend_string * callback_name;
+ zend_bool ok = zend_is_callable(callback_p, IS_CALLABLE_CHECK_SILENT,
&callback_name);
+#endif
+ if (ok) {
+ snprintf(buffer, sizeof(buffer), "%s",
+#if PHP_VERSION_ID < 70000
+ callback_name
+#else
+ ZSTR_VAL(callback_name)
+#endif
+ );
return buffer;
} else {
return NULL;
@@ -282,7 +298,14 @@
if (name) {
prof_name_size += strlen(name);
}
+
+#if PHP_VERSION_ID < 70000
char prof_name[prof_name_size];
+#else
+ zend_string *zstr = zend_string_alloc(prof_name_size, 0);
+ char *prof_name = ZSTR_VAL(zstr);
+#endif
+
if (!name) {
if (ar->linedefined > 0) {
snprintf(prof_name, prof_name_size, "<%s:%d>",
ar->short_src, ar->linedefined);
@@ -298,11 +321,13 @@
snprintf(prof_name, prof_name_size, "%s", name);
}
}
+
+ luasandbox_timer_set * lts = &sandbox->timer;
+ HashTable * ht = lts->function_counts;
+#if PHP_VERSION_ID < 70000
// Key length in zend_hash conventionally includes the null byte
uint key_length = (uint)strlen(prof_name) + 1;
ulong h = zend_inline_hash_func(prof_name, key_length);
- luasandbox_timer_set * lts = &sandbox->timer;
- HashTable * ht = lts->function_counts;
size_t * elt;
if (SUCCESS == zend_hash_quick_find(ht, prof_name, key_length, h,
(void**)&elt)) {
(*elt) += signal_count;
@@ -310,6 +335,18 @@
size_t init = signal_count;
zend_hash_quick_add(ht, prof_name, key_length, h,
(void**)&init, sizeof(size_t), NULL);
}
+#else
+ ZSTR_LEN(zstr) = strlen(prof_name);
+ zval *elt = zend_hash_find(ht, zstr);
+ if (elt != NULL) {
+ ZVAL_LONG(elt, Z_LVAL_P(elt) + signal_count);
+ } else {
+ zval v;
+ ZVAL_LONG(&v, signal_count);
+ zend_hash_add(ht, zstr, &v);
+ }
+ zend_string_release(zstr);
+#endif
lts->total_count += signal_count;
}
--
To view, visit https://gerrit.wikimedia.org/r/298312
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I34ba41ace1f8ff14371a116e0d2880f4e7cf58c5
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/php/luasandbox
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits