From f8abae031894217f8a5a6df9d002cd3bbd81e02c Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Mon, 18 Jan 2016 16:29:02 +0900 Subject: [PATCH 1/9] WIP: user serializer --- ext/session/config.m4 | 4 +- ext/session/mod_serializer_user.c | 140 ++++++++++++++++++++++++++++++ ext/session/mod_serializer_user.h | 24 +++++ ext/session/php_session.h | 7 ++ ext/session/session.c | 5 +- 5 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 ext/session/mod_serializer_user.c create mode 100644 ext/session/mod_serializer_user.h diff --git a/ext/session/config.m4 b/ext/session/config.m4 index 949306c026882..4b91391ccd7da 100644 --- a/ext/session/config.m4 +++ b/ext/session/config.m4 @@ -11,11 +11,11 @@ PHP_ARG_WITH(mm,for mm support, if test "$PHP_SESSION" != "no"; then PHP_PWRITE_TEST PHP_PREAD_TEST - PHP_NEW_EXTENSION(session, mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + PHP_NEW_EXTENSION(session, mod_serializer_user.c mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_EXTENSION_DEP(session, hash, true) PHP_ADD_EXTENSION_DEP(session, spl) PHP_SUBST(SESSION_SHARED_LIBADD) - PHP_INSTALL_HEADERS(ext/session, [php_session.h mod_files.h mod_user.h]) + PHP_INSTALL_HEADERS(ext/session, [php_session.h mod_serialiser_user.h mod_files.h mod_user.h]) AC_DEFINE(HAVE_PHP_SESSION,1,[ ]) fi diff --git a/ext/session/mod_serializer_user.c b/ext/session/mod_serializer_user.c new file mode 100644 index 0000000000000..d36331d6ac598 --- /dev/null +++ b/ext/session/mod_serializer_user.c @@ -0,0 +1,140 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Yasuo Ohgaki | + +----------------------------------------------------------------------+ + */ + + +#include "php.h" +#include "php_session.h" + + +static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval) +{ + int i; + if (call_user_function(EG(function_table), NULL, func, retval, argc, argv) == FAILURE) { + zval_ptr_dtor(retval); + ZVAL_UNDEF(retval); + } else if (Z_ISUNDEF_P(retval)) { + ZVAL_NULL(retval); + } + for (i = 0; i < argc; i++) { + zval_ptr_dtor(&argv[i]); + } +} + + +#define FINISH \ + if (Z_TYPE(retval) != IS_UNDEF) { \ + if (Z_TYPE(retval) == IS_TRUE) { \ + ret = SUCCESS; \ + } else if (Z_TYPE(retval) == IS_FALSE) { \ + ret = FAILURE; \ + } else { \ + if (!EG(exception)) { \ + php_error_docref(NULL, E_WARNING, \ + "Session callback expects true/false return value"); \ + } \ + ret = FAILURE; \ + zval_ptr_dtor(&retval); \ + } \ + } \ + return ret \ +} + + +#define PSF(a) PS(serializer_user_names).name.ps_##a + +/* {{{ PS_SERIALIZER_ENCODE_FUNC + */ +PS_SERIALIZER_ENCODE_FUNC(user) +{ + zval args[1], retval; + + if (Z_ISUNDEF(PSF(encode))) { + php_error_docref(NULL, E_WARNING, + "User decode function is not defined"); + return NULL; + } + + ZVAL_UNDEF(&retval); + args[0] = PS(http_session_vars); + ps_call_handler(&PSF(encode), 1, args, &retval); + + if (Z_TYPE(retval) == IS_STRING) { + zend_string *tmp; + tmp = zend_string_copy(Z_STR(retval)); + zval_ptr_dtor(&retval); + return tmp; + } else if (Z_TYPE(retval) == IS_FALSE) { + return NULL; + } else { + if (!Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); + } + if (!EG(exception)) { + php_error_docref(NULL, E_WARNING, + "Session decode callback expects string or FALSE return value"); + } + } + return NULL; +} +/* }}} */ + +/* {{{ PS_SERIALIZER_DECODE_FUNC + */ +PS_SERIALIZER_DECODE_FUNC(user) +{ + zval retval; + zval args[1]; + zend_string *data; + zend_bool bailout = 0; + + if (vallen == 0) { + return SUCCESS; + } + + data = zend_string_init(val, vallen, 0); + ZVAL_STR_COPY(&args[0], data); + ZVAL_UNDEF(&retval); + zend_try { + ps_call_handler(&PSF(decode), 1, args, &retval); + } zend_catch { + bailout = 1; + } zend_end_try(); + + + if (bailout) { + zend_string_release(data); + if (!Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); + } + return FAILURE; + } + + zend_string_release(data); + return SUCCESS; +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ + diff --git a/ext/session/mod_serializer_user.h b/ext/session/mod_serializer_user.h new file mode 100644 index 0000000000000..3333adb560cfd --- /dev/null +++ b/ext/session/mod_serializer_user.h @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Yasuo Ohgaki | + +----------------------------------------------------------------------+ + */ + +#ifndef MOD_SERIALIZER_USER_H +#define MOD_SERIALIZER_USER_H + +PS_SERIALIZER_FUNCS(user); + +#endif diff --git a/ext/session/php_session.h b/ext/session/php_session.h index b2ddef901dd98..fc4f648a425ae 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -185,6 +185,13 @@ typedef struct _php_ps_globals { int mod_user_implemented; int mod_user_is_open; const struct ps_serializer_struct *serializer; + union { + zval names[2]; + struct { + zval ps_encode; + zval ps_decode; + } name; + } serializer_user_names; zval http_session_vars; zend_bool auto_start; zend_bool use_cookies; diff --git a/ext/session/session.c b/ext/session/session.c index 52ba7e300ab41..8fc2dc35acda0 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -56,6 +56,8 @@ #include "mod_files.h" #include "mod_user.h" +#include "mod_serializer_user.h" + #ifdef HAVE_LIBMM #include "mod_mm.h" #endif @@ -1092,10 +1094,11 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ /* }}} */ #define MAX_SERIALIZERS 32 -#define PREDEFINED_SERIALIZERS 3 +#define PREDEFINED_SERIALIZERS 4 static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { PS_SERIALIZER_ENTRY(php_serialize), + PS_SERIALIZER_ENTRY(user), PS_SERIALIZER_ENTRY(php), PS_SERIALIZER_ENTRY(php_binary) }; From b063473116d65efe4b1ace4293ad3979d15b2222 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Mon, 18 Jan 2016 16:43:16 +0900 Subject: [PATCH 2/9] Rename files --- ext/session/config.m4 | 4 ++-- ext/session/{mod_serializer_user.c => serializer_user.c} | 0 ext/session/{mod_serializer_user.h => serializer_user.h} | 0 ext/session/session.c | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename ext/session/{mod_serializer_user.c => serializer_user.c} (100%) rename ext/session/{mod_serializer_user.h => serializer_user.h} (100%) diff --git a/ext/session/config.m4 b/ext/session/config.m4 index 4b91391ccd7da..2de0492ccc67e 100644 --- a/ext/session/config.m4 +++ b/ext/session/config.m4 @@ -11,11 +11,11 @@ PHP_ARG_WITH(mm,for mm support, if test "$PHP_SESSION" != "no"; then PHP_PWRITE_TEST PHP_PREAD_TEST - PHP_NEW_EXTENSION(session, mod_serializer_user.c mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + PHP_NEW_EXTENSION(session, serializer_user.c mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_EXTENSION_DEP(session, hash, true) PHP_ADD_EXTENSION_DEP(session, spl) PHP_SUBST(SESSION_SHARED_LIBADD) - PHP_INSTALL_HEADERS(ext/session, [php_session.h mod_serialiser_user.h mod_files.h mod_user.h]) + PHP_INSTALL_HEADERS(ext/session, [php_session.h mod_serializer.h mod_files.h mod_user.h]) AC_DEFINE(HAVE_PHP_SESSION,1,[ ]) fi diff --git a/ext/session/mod_serializer_user.c b/ext/session/serializer_user.c similarity index 100% rename from ext/session/mod_serializer_user.c rename to ext/session/serializer_user.c diff --git a/ext/session/mod_serializer_user.h b/ext/session/serializer_user.h similarity index 100% rename from ext/session/mod_serializer_user.h rename to ext/session/serializer_user.h diff --git a/ext/session/session.c b/ext/session/session.c index a072df9940e4e..1a5d202515858 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -56,7 +56,7 @@ #include "mod_files.h" #include "mod_user.h" -#include "mod_serializer_user.h" +#include "serializer_user.h" #ifdef HAVE_LIBMM #include "mod_mm.h" From 64c4255e84073623ea04f9fb4fdbe3d1bba7a337 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Mon, 18 Jan 2016 19:25:55 +0900 Subject: [PATCH 3/9] WIP: user serializer --- ext/session/serializer_user.c | 61 ++++++------ ext/session/serializer_user.h | 3 + ext/session/session.c | 79 ++++++++++++++- .../tests/session_set_serializer_basic.phpt | 96 +++++++++++++++++++ .../session_set_serializer_variation1.phpt | 57 +++++++++++ .../session_set_serializer_variation2.phpt | 57 +++++++++++ .../session_set_serializer_variation3.phpt | 68 +++++++++++++ .../session_set_serializer_variation4.phpt | 61 ++++++++++++ .../session_set_serializer_variation5.phpt | 68 +++++++++++++ .../session_set_serializer_variation6.phpt | 61 ++++++++++++ 10 files changed, 578 insertions(+), 33 deletions(-) create mode 100644 ext/session/tests/session_set_serializer_basic.phpt create mode 100644 ext/session/tests/session_set_serializer_variation1.phpt create mode 100644 ext/session/tests/session_set_serializer_variation2.phpt create mode 100644 ext/session/tests/session_set_serializer_variation3.phpt create mode 100644 ext/session/tests/session_set_serializer_variation4.phpt create mode 100644 ext/session/tests/session_set_serializer_variation5.phpt create mode 100644 ext/session/tests/session_set_serializer_variation6.phpt diff --git a/ext/session/serializer_user.c b/ext/session/serializer_user.c index d36331d6ac598..aa6121fc71931 100644 --- a/ext/session/serializer_user.c +++ b/ext/session/serializer_user.c @@ -20,6 +20,11 @@ #include "php.h" #include "php_session.h" +PS_SERIALIZER_ENCODE_FUNC(user); +PS_SERIALIZER_DECODE_FUNC(user); + +ps_serializer ps_serializer_user = PS_SERIALIZER_ENTRY(user); + static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval) { @@ -36,27 +41,9 @@ static void ps_call_handler(zval *func, int argc, zval *argv, zval *retval) } -#define FINISH \ - if (Z_TYPE(retval) != IS_UNDEF) { \ - if (Z_TYPE(retval) == IS_TRUE) { \ - ret = SUCCESS; \ - } else if (Z_TYPE(retval) == IS_FALSE) { \ - ret = FAILURE; \ - } else { \ - if (!EG(exception)) { \ - php_error_docref(NULL, E_WARNING, \ - "Session callback expects true/false return value"); \ - } \ - ret = FAILURE; \ - zval_ptr_dtor(&retval); \ - } \ - } \ - return ret \ -} - - #define PSF(a) PS(serializer_user_names).name.ps_##a + /* {{{ PS_SERIALIZER_ENCODE_FUNC */ PS_SERIALIZER_ENCODE_FUNC(user) @@ -65,12 +52,13 @@ PS_SERIALIZER_ENCODE_FUNC(user) if (Z_ISUNDEF(PSF(encode))) { php_error_docref(NULL, E_WARNING, - "User decode function is not defined"); + "User session encode function is not defined"); return NULL; } ZVAL_UNDEF(&retval); args[0] = PS(http_session_vars); + Z_ADDREF(args[0]); ps_call_handler(&PSF(encode), 1, args, &retval); if (Z_TYPE(retval) == IS_STRING) { @@ -85,7 +73,7 @@ PS_SERIALIZER_ENCODE_FUNC(user) zval_ptr_dtor(&retval); } if (!EG(exception)) { - php_error_docref(NULL, E_WARNING, + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Session decode callback expects string or FALSE return value"); } } @@ -93,21 +81,24 @@ PS_SERIALIZER_ENCODE_FUNC(user) } /* }}} */ + /* {{{ PS_SERIALIZER_DECODE_FUNC */ PS_SERIALIZER_DECODE_FUNC(user) { - zval retval; - zval args[1]; - zend_string *data; + zval args[1], retval; zend_bool bailout = 0; + zend_string *data; + zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0); - if (vallen == 0) { - return SUCCESS; + if (Z_ISUNDEF(PSF(encode))) { + php_error_docref(NULL, E_RECOVERABLE_ERROR, + "User session decode function is not defined"); + return FAILURE; } data = zend_string_init(val, vallen, 0); - ZVAL_STR_COPY(&args[0], data); + ZVAL_STR(&args[0], data); ZVAL_UNDEF(&retval); zend_try { ps_call_handler(&PSF(decode), 1, args, &retval); @@ -117,14 +108,26 @@ PS_SERIALIZER_DECODE_FUNC(user) if (bailout) { - zend_string_release(data); if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } + zend_bailout(); + } + + if (Z_TYPE(retval) != IS_ARRAY) { + zval_ptr_dtor(&retval); + php_error_docref(NULL, E_RECOVERABLE_ERROR, + "User session decode function must return array"); return FAILURE; } - zend_string_release(data); + if (!Z_ISUNDEF(PS(http_session_vars))) { + zval_ptr_dtor(&PS(http_session_vars)); + } + ZVAL_NEW_REF(&PS(http_session_vars), &retval); + Z_ADDREF_P(&PS(http_session_vars)); + zend_hash_update_ind(&EG(symbol_table), var_name, &PS(http_session_vars)); + zend_string_release(var_name); return SUCCESS; } /* }}} */ diff --git a/ext/session/serializer_user.h b/ext/session/serializer_user.h index 3333adb560cfd..1451ddf261847 100644 --- a/ext/session/serializer_user.h +++ b/ext/session/serializer_user.h @@ -19,6 +19,9 @@ #ifndef MOD_SERIALIZER_USER_H #define MOD_SERIALIZER_USER_H +extern ps_serializer ps_serializer_user; +#define ps_serializer_user_ptr &ps_serializer_user + PS_SERIALIZER_FUNCS(user); #endif diff --git a/ext/session/session.c b/ext/session/session.c index 1a5d202515858..79e18fe921d46 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -104,7 +104,7 @@ static void php_session_abort(void); /* Dispatched by RINIT and by php_session_destroy */ static inline void php_rinit_session_globals(void) /* {{{ */ { - /* Do NOT init PS(mod_user_names) here! */ + /* Do NOT init PS(mod_user_names)/PS(serializer_user_names) here! */ /* TODO: These could be moved to MINIT and removed. These should be initialized by php_rshutdown_session_globals() always when execution is finished. */ PS(id) = NULL; PS(session_status) = php_session_none; @@ -119,7 +119,7 @@ static inline void php_rinit_session_globals(void) /* {{{ */ /* Dispatched by RSHUTDOWN and by php_session_destroy */ static inline void php_rshutdown_session_globals(void) /* {{{ */ { - /* Do NOT destroy PS(mod_user_names) here! */ + /* Do NOT destroy PS(mod_user_names)/PS(serializer_user_names) here! */ if (!Z_ISUNDEF(PS(http_session_vars))) { zval_ptr_dtor(&PS(http_session_vars)); ZVAL_UNDEF(&PS(http_session_vars)); @@ -579,7 +579,14 @@ static void php_session_initialize(void) /* {{{ */ if (PS(lazy_write)) { PS(session_vars) = zend_string_copy(val); } - php_session_decode(val); + if (php_session_decode(val) == FAILURE) { + zend_string_release(val); + php_session_abort(); + php_error_docref(NULL, E_WARNING, + "Failed to decode session data (serializer: %s)", + zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler")-1, 0)); + return; + } zend_string_release(val); } } @@ -1669,7 +1676,9 @@ PHPAPI void php_session_start(void) /* {{{ */ } php_session_initialize(); - php_session_cache_limiter(); + if (PS(session_status) == php_session_active) { + php_session_cache_limiter(); + } } /* }}} */ @@ -1993,6 +2002,53 @@ static PHP_FUNCTION(session_set_save_handler) } /* }}} */ +/* {{{ proto void session_set_serializer(string encode, string decode) + Sets user-level serializer functions */ +static PHP_FUNCTION(session_set_serializer) +{ + zval *args[2]; + zend_string *name, *ini_name, *ini_val; + int i; + + if (PS(session_status) == php_session_active) { + php_error_docref(NULL, E_WARNING, "Cannot change session serializer while session is active"); + RETURN_FALSE; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &args[0], &args[1]) == FAILURE) { + RETURN_FALSE; + } + + for (i = 0; i < 2; i++) { + if (!zend_is_callable(args[i], 0, &name)) { + zend_string_release(name); + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Argument %d is not a valid callback", i+1); + RETURN_FALSE; + } + zend_string_release(name); + } + + if (PS(serializer) && PS(serializer) != &ps_serializer_user) { + ini_name = zend_string_init("session.serialize_handler", sizeof("session.serialize_handler") - 1, 0); + ini_val = zend_string_init("user", sizeof("user") - 1, 0); + zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_string_release(ini_val); + zend_string_release(ini_name); + } + + for (i = 0; i < 2; i++) { + if (!Z_ISUNDEF(PS(serializer_user_names).names[i])) { + zval_ptr_dtor(&PS(serializer_user_names).names[i]); + } + ZVAL_COPY(&PS(serializer_user_names).names[i], args[i]); + } + + + RETURN_TRUE; +} +/* }}} */ + + /* {{{ proto string session_save_path([string newname]) Return the current save path passed to module_name. If newname is given, the save path is replaced with newname */ static PHP_FUNCTION(session_save_path) @@ -2482,6 +2538,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_save_handler, 0, 0, 1) ZEND_ARG_INFO(0, update_timestamp) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_serializer, 0, 0, 2) + ZEND_ARG_INFO(0, encode) + ZEND_ARG_INFO(0, decode) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_session_cache_limiter, 0, 0, 0) ZEND_ARG_INFO(0, cache_limiter) ZEND_END_ARG_INFO() @@ -2550,6 +2611,7 @@ static const zend_function_entry session_functions[] = { PHP_FE(session_destroy, arginfo_session_void) PHP_FE(session_unset, arginfo_session_void) PHP_FE(session_set_save_handler, arginfo_session_set_save_handler) + PHP_FE(session_set_serializer, arginfo_session_set_serializer) PHP_FE(session_cache_limiter, arginfo_session_cache_limiter) PHP_FE(session_cache_expire, arginfo_session_cache_expire) PHP_FE(session_set_cookie_params, arginfo_session_set_cookie_params) @@ -2669,6 +2731,12 @@ static PHP_RSHUTDOWN_FUNCTION(session) /* {{{ */ ZVAL_UNDEF(&PS(mod_user_names).names[i]); } } + for (i = 0; i < 2; i++) { + if (!Z_ISUNDEF(PS(serializer_user_names).names[i])) { + zval_ptr_dtor(&PS(serializer_user_names).names[i]); + ZVAL_UNDEF(&PS(serializer_user_names).names[i]); + } + } return SUCCESS; } @@ -2696,6 +2764,9 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */ for (i = 0; i < PS_NUM_APIS; i++) { ZVAL_UNDEF(&ps_globals->mod_user_names.names[i]); } + for (i = 0; i < 2; i++) { + ZVAL_UNDEF(&ps_globals->serializer_user_names.names[i]); + } ZVAL_UNDEF(&ps_globals->http_session_vars); } /* }}} */ diff --git a/ext/session/tests/session_set_serializer_basic.phpt b/ext/session/tests/session_set_serializer_basic.phpt new file mode 100644 index 0000000000000..51bc430560f5b --- /dev/null +++ b/ext/session/tests/session_set_serializer_basic.phpt @@ -0,0 +1,96 @@ +--TEST-- +Test session_set_serializer() function : basic functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** +bool(true) +decoding: +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +encoded: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Starting session again..! +decoding: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +encoded: a:4:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;s:3:"Bar";s:3:"Foo";} +Cleanup.. +decoding: a:4:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;s:3:"Bar";s:3:"Foo";} diff --git a/ext/session/tests/session_set_serializer_variation1.phpt b/ext/session/tests/session_set_serializer_variation1.phpt new file mode 100644 index 0000000000000..5b5037f776bd3 --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation1.phpt @@ -0,0 +1,57 @@ +--TEST-- +Test session_set_serializer() function : variation1 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** + +Catchable fatal error: session_set_serializer(): Argument 1 is not a valid callback in %s on line %d \ No newline at end of file diff --git a/ext/session/tests/session_set_serializer_variation2.phpt b/ext/session/tests/session_set_serializer_variation2.phpt new file mode 100644 index 0000000000000..122484a3651fb --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation2.phpt @@ -0,0 +1,57 @@ +--TEST-- +Test session_set_serializer() function : variation2 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** + +Catchable fatal error: session_set_serializer(): Argument 2 is not a valid callback in %s on line %d \ No newline at end of file diff --git a/ext/session/tests/session_set_serializer_variation3.phpt b/ext/session/tests/session_set_serializer_variation3.phpt new file mode 100644 index 0000000000000..31f4510f3306e --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation3.phpt @@ -0,0 +1,68 @@ +--TEST-- +Test session_set_serializer() function : variation3 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** +bool(true) +decoding: +bool(true) +encoded: a:0:{} +Died in encode() +encoded: a:0:{} +Died in encode() + diff --git a/ext/session/tests/session_set_serializer_variation4.phpt b/ext/session/tests/session_set_serializer_variation4.phpt new file mode 100644 index 0000000000000..06b265c605b4c --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation4.phpt @@ -0,0 +1,61 @@ +--TEST-- +Test session_set_serializer() function : variation4 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** +bool(true) +decoding: +Died in decode() +encoded: a:0:{} diff --git a/ext/session/tests/session_set_serializer_variation5.phpt b/ext/session/tests/session_set_serializer_variation5.phpt new file mode 100644 index 0000000000000..f9d4314fba865 --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation5.phpt @@ -0,0 +1,68 @@ +--TEST-- +Test session_set_serializer() function : variation5 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** +bool(true) +decoding: +bool(true) +encoded: a:0:{} + +Catchable fatal error: session_commit(): Session decode callback expects string or FALSE return value in %s on line %d +encoded: a:0:{} + +Catchable fatal error: Unknown: Session decode callback expects string or FALSE return value in Unknown on line 0 diff --git a/ext/session/tests/session_set_serializer_variation6.phpt b/ext/session/tests/session_set_serializer_variation6.phpt new file mode 100644 index 0000000000000..d917b6d92a66f --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation6.phpt @@ -0,0 +1,61 @@ +--TEST-- +Test session_set_serializer() function : variation6 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** +bool(true) +decoding: + +Catchable fatal error: session_start(): User session decode function must return array in %s on line %d +encoded: a:0:{} From a07747dcfbb6bdc9d3d539db6e90731741d5b7de Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Tue, 19 Jan 2016 05:31:25 +0900 Subject: [PATCH 4/9] Remove unneeded codes --- ext/session/serializer_user.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/ext/session/serializer_user.c b/ext/session/serializer_user.c index aa6121fc71931..106a39b133872 100644 --- a/ext/session/serializer_user.c +++ b/ext/session/serializer_user.c @@ -69,9 +69,6 @@ PS_SERIALIZER_ENCODE_FUNC(user) } else if (Z_TYPE(retval) == IS_FALSE) { return NULL; } else { - if (!Z_ISUNDEF(retval)) { - zval_ptr_dtor(&retval); - } if (!EG(exception)) { php_error_docref(NULL, E_RECOVERABLE_ERROR, "Session decode callback expects string or FALSE return value"); @@ -87,7 +84,6 @@ PS_SERIALIZER_ENCODE_FUNC(user) PS_SERIALIZER_DECODE_FUNC(user) { zval args[1], retval; - zend_bool bailout = 0; zend_string *data; zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0); @@ -100,22 +96,12 @@ PS_SERIALIZER_DECODE_FUNC(user) data = zend_string_init(val, vallen, 0); ZVAL_STR(&args[0], data); ZVAL_UNDEF(&retval); - zend_try { - ps_call_handler(&PSF(decode), 1, args, &retval); - } zend_catch { - bailout = 1; - } zend_end_try(); - - - if (bailout) { + ps_call_handler(&PSF(decode), 1, args, &retval); + + if (Z_TYPE(retval) != IS_ARRAY) { if (!Z_ISUNDEF(retval)) { zval_ptr_dtor(&retval); } - zend_bailout(); - } - - if (Z_TYPE(retval) != IS_ARRAY) { - zval_ptr_dtor(&retval); php_error_docref(NULL, E_RECOVERABLE_ERROR, "User session decode function must return array"); return FAILURE; From 3fc608eb57f0f01a893ce9046b199924b5ab95d4 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Tue, 19 Jan 2016 05:34:45 +0900 Subject: [PATCH 5/9] Do no leave garbages in test dir --- ext/session/tests/session_set_serializer_variation3.phpt | 2 -- ext/session/tests/session_set_serializer_variation4.phpt | 2 -- ext/session/tests/session_set_serializer_variation5.phpt | 2 -- ext/session/tests/session_set_serializer_variation6.phpt | 3 --- 4 files changed, 9 deletions(-) diff --git a/ext/session/tests/session_set_serializer_variation3.phpt b/ext/session/tests/session_set_serializer_variation3.phpt index 31f4510f3306e..f1e60b946991e 100644 --- a/ext/session/tests/session_set_serializer_variation3.phpt +++ b/ext/session/tests/session_set_serializer_variation3.phpt @@ -32,8 +32,6 @@ function decode($string) { } -$path = dirname(__FILE__); -session_save_path($path); var_dump(session_set_serializer("encode", "decode")); var_dump(session_start()); diff --git a/ext/session/tests/session_set_serializer_variation4.phpt b/ext/session/tests/session_set_serializer_variation4.phpt index 06b265c605b4c..c6924dcdfd42f 100644 --- a/ext/session/tests/session_set_serializer_variation4.phpt +++ b/ext/session/tests/session_set_serializer_variation4.phpt @@ -32,8 +32,6 @@ function decode($string) { } -$path = dirname(__FILE__); -session_save_path($path); var_dump(session_set_serializer("encode", "decode")); // Shouldn't reach here diff --git a/ext/session/tests/session_set_serializer_variation5.phpt b/ext/session/tests/session_set_serializer_variation5.phpt index f9d4314fba865..4c0df47710e77 100644 --- a/ext/session/tests/session_set_serializer_variation5.phpt +++ b/ext/session/tests/session_set_serializer_variation5.phpt @@ -31,8 +31,6 @@ function decode($string) { } -$path = dirname(__FILE__); -session_save_path($path); var_dump(session_set_serializer("encode", "decode")); var_dump(session_start()); diff --git a/ext/session/tests/session_set_serializer_variation6.phpt b/ext/session/tests/session_set_serializer_variation6.phpt index d917b6d92a66f..4d76c934cf10b 100644 --- a/ext/session/tests/session_set_serializer_variation6.phpt +++ b/ext/session/tests/session_set_serializer_variation6.phpt @@ -30,9 +30,6 @@ function decode($string) { return TRUE; } - -$path = dirname(__FILE__); -session_save_path($path); var_dump(session_set_serializer("encode", "decode")); var_dump(session_start()); From a3831444056526630ff30e639ab0eec3ed9b8f63 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Tue, 19 Jan 2016 05:38:41 +0900 Subject: [PATCH 6/9] Clean up, typo fix --- ext/session/tests/session_set_serializer_basic.phpt | 2 -- ext/session/tests/session_set_serializer_variation2.phpt | 1 - ext/session/tests/session_set_serializer_variation5.phpt | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ext/session/tests/session_set_serializer_basic.phpt b/ext/session/tests/session_set_serializer_basic.phpt index 51bc430560f5b..ea9bc0eb7787f 100644 --- a/ext/session/tests/session_set_serializer_basic.phpt +++ b/ext/session/tests/session_set_serializer_basic.phpt @@ -19,7 +19,6 @@ ob_start(); echo "*** Testing session_set_serializer() : basic functionality ***\n"; - function encode($array) { echo "encoded: ". serialize($array) ."\n"; return serialize($array); @@ -30,7 +29,6 @@ function decode($string) { return unserialize($string) ?: array(); } - $path = dirname(__FILE__); session_save_path($path); var_dump(session_set_serializer("encode", "decode")); diff --git a/ext/session/tests/session_set_serializer_variation2.phpt b/ext/session/tests/session_set_serializer_variation2.phpt index 122484a3651fb..761c63eb9d54e 100644 --- a/ext/session/tests/session_set_serializer_variation2.phpt +++ b/ext/session/tests/session_set_serializer_variation2.phpt @@ -30,7 +30,6 @@ function decode($string) { return unserialize($string) ?: array(); } - $path = dirname(__FILE__); session_save_path($path); var_dump(session_set_serializer("encode", "no_decode")); diff --git a/ext/session/tests/session_set_serializer_variation5.phpt b/ext/session/tests/session_set_serializer_variation5.phpt index 4c0df47710e77..a21af6fb7408c 100644 --- a/ext/session/tests/session_set_serializer_variation5.phpt +++ b/ext/session/tests/session_set_serializer_variation5.phpt @@ -36,7 +36,7 @@ var_dump(session_set_serializer("encode", "decode")); var_dump(session_start()); $session_id = session_id(); // encode() is executed by session_commit(). -// encode() returns invalid type and RSHUTDON try to finish session. +// encode() returns invalid type and RSHUTDOWN tries to finish session. // Therefore, ecode() is called twice. var_dump($session_id, session_commit()); From ffdbafd8e8c86c09ea0d87c85db78d261aae3711 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Tue, 19 Jan 2016 07:26:33 +0900 Subject: [PATCH 7/9] Add session_set_serializer() object handler support --- ext/session/php_session.h | 4 + ext/session/session.c | 97 ++++++++++++++---- .../tests/session_set_serializer_iface.phpt | 99 +++++++++++++++++++ ...ssion_set_serializer_iface_variation1.phpt | 69 +++++++++++++ ...ssion_set_serializer_iface_variation2.phpt | 80 +++++++++++++++ ...ssion_set_serializer_iface_variation3.phpt | 70 +++++++++++++ ...ssion_set_serializer_iface_variation4.phpt | 81 +++++++++++++++ ...ssion_set_serializer_iface_variation5.phpt | 70 +++++++++++++ 8 files changed, 552 insertions(+), 18 deletions(-) create mode 100644 ext/session/tests/session_set_serializer_iface.phpt create mode 100644 ext/session/tests/session_set_serializer_iface_variation1.phpt create mode 100644 ext/session/tests/session_set_serializer_iface_variation2.phpt create mode 100644 ext/session/tests/session_set_serializer_iface_variation3.phpt create mode 100644 ext/session/tests/session_set_serializer_iface_variation4.phpt create mode 100644 ext/session/tests/session_set_serializer_iface_variation5.phpt diff --git a/ext/session/php_session.h b/ext/session/php_session.h index fc4f648a425ae..2ff2f0e32b121 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -342,4 +342,8 @@ extern PHP_METHOD(SessionHandler, create_sid); extern PHP_METHOD(SessionHandler, validateId); extern PHP_METHOD(SessionHandler, updateTimestamp); +#define PS_SERIALIZER_IFACE_NAME "SessionSerializerInterface" +extern zend_class_entry *php_session_serializer_iface_entry; + + #endif diff --git a/ext/session/session.c b/ext/session/session.c index 79e18fe921d46..248486c02db1b 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -83,6 +83,9 @@ zend_class_entry *php_session_update_timestamp_class_entry; /* SessionUpdateTimestampInterface */ zend_class_entry *php_session_update_timestamp_iface_entry; +/* SessionSerializerInterface */ +zend_class_entry *php_session_serializer_iface_entry; + /* *********** * Helpers * *********** */ @@ -1867,7 +1870,7 @@ static PHP_FUNCTION(session_set_save_handler) zend_bool register_shutdown = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &obj, php_session_iface_entry, ®ister_shutdown) == FAILURE) { - RETURN_FALSE; + return; } /* For compatibility reason, implemeted interface is not checked */ @@ -2008,41 +2011,76 @@ static PHP_FUNCTION(session_set_serializer) { zval *args[2]; zend_string *name, *ini_name, *ini_val; - int i; + int i, argc = ZEND_NUM_ARGS(); if (PS(session_status) == php_session_active) { php_error_docref(NULL, E_WARNING, "Cannot change session serializer while session is active"); RETURN_FALSE; } - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &args[0], &args[1]) == FAILURE) { - RETURN_FALSE; + if (argc > 2) { + php_error_docref(NULL, E_WARNING, "Accepts 1 or 2 paramters"); + return; } - for (i = 0; i < 2; i++) { - if (!zend_is_callable(args[i], 0, &name)) { - zend_string_release(name); - php_error_docref(NULL, E_RECOVERABLE_ERROR, "Argument %d is not a valid callback", i+1); + if (argc == 1) { + /* Object */ + zend_string *func_name; + zend_function *current_mptr; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &args[0], php_session_serializer_iface_entry) == FAILURE) { + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Only SessionSerializerInterface object can be used as session serializer object"); RETURN_FALSE; } - zend_string_release(name); + i = 0; + ZEND_HASH_FOREACH_STR_KEY(&php_session_serializer_iface_entry->function_table, func_name) { + if ((current_mptr = zend_hash_find_ptr(&Z_OBJCE_P(args[0])->function_table, func_name))) { + if (!Z_ISUNDEF(PS(serializer_user_names).names[i])) { + zval_ptr_dtor(&PS(serializer_user_names).names[i]); + } + array_init_size(&PS(serializer_user_names).names[i], 2); + Z_ADDREF_P(args[0]); + add_next_index_zval(&PS(serializer_user_names).names[i], args[0]); + add_next_index_str(&PS(serializer_user_names).names[i], zend_string_copy(func_name)); + } else { + php_error_docref(NULL, E_ERROR, "Session handler's function table is corrupt"); + RETURN_FALSE; + } + ++i; + } ZEND_HASH_FOREACH_END(); + } else { + /* Functions */ + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &args[0], &args[1]) == FAILURE) { + return; + } + for (i = 0; i < 2; i++) { + if (!zend_is_callable(args[i], 0, &name)) { + zend_string_release(name); + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Argument %d is not a valid callback", i+1); + RETURN_FALSE; + } + zend_string_release(name); + } + for (i = 0; i < 2; i++) { + if (!Z_ISUNDEF(PS(serializer_user_names).names[i])) { + zval_ptr_dtor(&PS(serializer_user_names).names[i]); + } + ZVAL_COPY(&PS(serializer_user_names).names[i], args[i]); + } } if (PS(serializer) && PS(serializer) != &ps_serializer_user) { + int ret; + ini_name = zend_string_init("session.serialize_handler", sizeof("session.serialize_handler") - 1, 0); ini_val = zend_string_init("user", sizeof("user") - 1, 0); - zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + ret = zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); zend_string_release(ini_val); zend_string_release(ini_name); - } - - for (i = 0; i < 2; i++) { - if (!Z_ISUNDEF(PS(serializer_user_names).names[i])) { - zval_ptr_dtor(&PS(serializer_user_names).names[i]); + if (ret == FAILURE) { + RETURN_FALSE; } - ZVAL_COPY(&PS(serializer_user_names).names[i], args[i]); } - RETURN_TRUE; } @@ -2595,6 +2633,15 @@ ZEND_BEGIN_ARG_INFO(arginfo_session_class_updateTimestamp, 0) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, val) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_session_serializer_encode, 0) + ZEND_ARG_INFO(0, raw_data) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_session_serializer_decode, 0) + ZEND_ARG_INFO(0, encoded_data) +ZEND_END_ARG_INFO() + /* }}} */ /* {{{ session_functions[] @@ -2647,7 +2694,7 @@ static const zend_function_entry php_session_id_iface_functions[] = { }; /* }}} */ -/* {{{ SessionUpdateTimestampHandler functions[] +/* {{{ SessionUpdateTimestampInterface functions[] */ static const zend_function_entry php_session_update_timestamp_iface_functions[] = { PHP_ABSTRACT_ME(SessionUpdateTimestampHandlerInterface, validateId, arginfo_session_class_validateId) @@ -2656,6 +2703,16 @@ static const zend_function_entry php_session_update_timestamp_iface_functions[] }; /* }}} */ +/* {{{ SessionSerializerInterface functions[] + */ +static const zend_function_entry php_session_serializer_iface_functions[] = { + PHP_ABSTRACT_ME(SessionSerializerInterface, encode, arginfo_session_serializer_encode) + PHP_ABSTRACT_ME(SessionSerializerInterface, decode, arginfo_session_serializer_decode) + { NULL, NULL, NULL } +}; +/* }}} */ + + /* {{{ SessionHandler functions[] */ static const zend_function_entry php_session_class_functions[] = { @@ -2801,6 +2858,10 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */ php_session_update_timestamp_iface_entry = zend_register_internal_class(&ce); php_session_update_timestamp_iface_entry->ce_flags |= ZEND_ACC_INTERFACE; + INIT_CLASS_ENTRY(ce, PS_SERIALIZER_IFACE_NAME, php_session_serializer_iface_functions); + php_session_serializer_iface_entry = zend_register_internal_class(&ce); + php_session_serializer_iface_entry->ce_flags |= ZEND_ACC_INTERFACE; + /* Register base class */ INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions); php_session_class_entry = zend_register_internal_class(&ce); diff --git a/ext/session/tests/session_set_serializer_iface.phpt b/ext/session/tests/session_set_serializer_iface.phpt new file mode 100644 index 0000000000000..22c1eba7f5dda --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface.phpt @@ -0,0 +1,99 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** +bool(true) +decoding: +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +encoded: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +Starting session again..! +decoding: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +encoded: a:4:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;s:3:"Bar";s:3:"Foo";} +Cleanup.. +decoding: a:4:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;s:3:"Bar";s:3:"Foo";} diff --git a/ext/session/tests/session_set_serializer_iface_variation1.phpt b/ext/session/tests/session_set_serializer_iface_variation1.phpt new file mode 100644 index 0000000000000..50f4dc28d0301 --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface_variation1.phpt @@ -0,0 +1,69 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** + +Warning: session_set_serializer() expects parameter 1 to be SessionSerializerInterface, object given in %s on line %d + +Catchable fatal error: session_set_serializer(): Only SessionSerializerInterface object can be used as session serializer object in %s on line %d diff --git a/ext/session/tests/session_set_serializer_iface_variation2.phpt b/ext/session/tests/session_set_serializer_iface_variation2.phpt new file mode 100644 index 0000000000000..dc6bd9c9ecd39 --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface_variation2.phpt @@ -0,0 +1,80 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** +bool(true) +decoding: +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +encoded: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} +Died in encode() +encoded: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} +Died in encode() diff --git a/ext/session/tests/session_set_serializer_iface_variation3.phpt b/ext/session/tests/session_set_serializer_iface_variation3.phpt new file mode 100644 index 0000000000000..df94bdcca88a0 --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface_variation3.phpt @@ -0,0 +1,70 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** +bool(true) +decoding: +Died in decode() +encoded: a:0:{} diff --git a/ext/session/tests/session_set_serializer_iface_variation4.phpt b/ext/session/tests/session_set_serializer_iface_variation4.phpt new file mode 100644 index 0000000000000..1a28d6002e1a8 --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface_variation4.phpt @@ -0,0 +1,81 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** +bool(true) +decoding: +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) +} +encoded: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} + +Catchable fatal error: session_write_close(): Session decode callback expects string or FALSE return value in %s on line %d +encoded: a:3:{s:4:"Blah";s:12:"Hello World!";s:3:"Foo";b:0;s:4:"Guff";i:1234567890;} + +Catchable fatal error: Unknown: Session decode callback expects string or FALSE return value in Unknown on line 0 diff --git a/ext/session/tests/session_set_serializer_iface_variation5.phpt b/ext/session/tests/session_set_serializer_iface_variation5.phpt new file mode 100644 index 0000000000000..e49aacade420c --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface_variation5.phpt @@ -0,0 +1,70 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** +bool(true) +decoding: + +Catchable fatal error: session_start(): User session decode function must return array in %s on line %d +encoded: a:0:{} From 2ea2ff1fcbf95de2eae6ca85e2d417c53b659713 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Tue, 19 Jan 2016 09:39:12 +0900 Subject: [PATCH 8/9] Add more tests --- ext/session/serializer_user.c | 2 +- ...ssion_set_serializer_iface_variation1.phpt | 2 +- ...ssion_set_serializer_iface_variation2.phpt | 1 + ...ssion_set_serializer_iface_variation3.phpt | 1 + ...ssion_set_serializer_iface_variation4.phpt | 1 + ...ssion_set_serializer_iface_variation6.phpt | 55 ++++++++++++++ .../session_set_serializer_variation7.phpt | 71 +++++++++++++++++++ 7 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 ext/session/tests/session_set_serializer_iface_variation6.phpt create mode 100644 ext/session/tests/session_set_serializer_variation7.phpt diff --git a/ext/session/serializer_user.c b/ext/session/serializer_user.c index 106a39b133872..45fad17491546 100644 --- a/ext/session/serializer_user.c +++ b/ext/session/serializer_user.c @@ -51,7 +51,7 @@ PS_SERIALIZER_ENCODE_FUNC(user) zval args[1], retval; if (Z_ISUNDEF(PSF(encode))) { - php_error_docref(NULL, E_WARNING, + php_error_docref(NULL, E_RECOVERABLE_ERROR, "User session encode function is not defined"); return NULL; } diff --git a/ext/session/tests/session_set_serializer_iface_variation1.phpt b/ext/session/tests/session_set_serializer_iface_variation1.phpt index 50f4dc28d0301..ac234ba2da1c0 100644 --- a/ext/session/tests/session_set_serializer_iface_variation1.phpt +++ b/ext/session/tests/session_set_serializer_iface_variation1.phpt @@ -35,7 +35,7 @@ class MySerializer { $handler = new MySerializer; var_dump(session_set_serializer($handler)); - +// Shound't reach here session_start(); $session_id = session_id(); $_SESSION["Blah"] = "Hello World!"; diff --git a/ext/session/tests/session_set_serializer_iface_variation2.phpt b/ext/session/tests/session_set_serializer_iface_variation2.phpt index dc6bd9c9ecd39..2b7e90956a353 100644 --- a/ext/session/tests/session_set_serializer_iface_variation2.phpt +++ b/ext/session/tests/session_set_serializer_iface_variation2.phpt @@ -45,6 +45,7 @@ $_SESSION["Guff"] = 1234567890; var_dump($_SESSION); session_write_close(); +// Shouldn't reach here session_unset(); var_dump($_SESSION); diff --git a/ext/session/tests/session_set_serializer_iface_variation3.phpt b/ext/session/tests/session_set_serializer_iface_variation3.phpt index df94bdcca88a0..5f0a2f5ff6823 100644 --- a/ext/session/tests/session_set_serializer_iface_variation3.phpt +++ b/ext/session/tests/session_set_serializer_iface_variation3.phpt @@ -38,6 +38,7 @@ $handler = new MySerializer; var_dump(session_set_serializer($handler)); session_start(); +// Shouldn't reach here $session_id = session_id(); $_SESSION["Blah"] = "Hello World!"; $_SESSION["Foo"] = FALSE; diff --git a/ext/session/tests/session_set_serializer_iface_variation4.phpt b/ext/session/tests/session_set_serializer_iface_variation4.phpt index 1a28d6002e1a8..96f8bd01fa0d2 100644 --- a/ext/session/tests/session_set_serializer_iface_variation4.phpt +++ b/ext/session/tests/session_set_serializer_iface_variation4.phpt @@ -44,6 +44,7 @@ $_SESSION["Guff"] = 1234567890; var_dump($_SESSION); session_write_close(); +// Shouldn't reach here session_unset(); var_dump($_SESSION); diff --git a/ext/session/tests/session_set_serializer_iface_variation6.phpt b/ext/session/tests/session_set_serializer_iface_variation6.phpt new file mode 100644 index 0000000000000..9ae945f7817bc --- /dev/null +++ b/ext/session/tests/session_set_serializer_iface_variation6.phpt @@ -0,0 +1,55 @@ +--TEST-- +Test session_set_serializer() function : interface functionality +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- +'bar'); +$encoded = $handler->encode($data); +$decoded = $handler->decode($encoded); +var_dump($encoded, $decoded); + +ob_end_flush(); +?> +--EXPECTF-- +*** Testing session_set_serializer() : interface functionality *** +bool(true) +encoded: a:1:{s:3:"foo";s:3:"bar";} +decoding: a:1:{s:3:"foo";s:3:"bar";} +string(26) "a:1:{s:3:"foo";s:3:"bar";}" +array(1) { + ["foo"]=> + string(3) "bar" +} \ No newline at end of file diff --git a/ext/session/tests/session_set_serializer_variation7.phpt b/ext/session/tests/session_set_serializer_variation7.phpt new file mode 100644 index 0000000000000..f4262f36c7276 --- /dev/null +++ b/ext/session/tests/session_set_serializer_variation7.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test session_set_serializer() function : variation7 +--INI-- +session.use_strict_mode=0 +session.save_path= +session.name=PHPSESSID +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing session_set_serializer() : basic functionality *** +bool(true) +decoding: +bool(true) +bool(true) + +Warning: session_set_serializer(): Cannot change session serializer while session is active in /home/yohgaki/workspace/ext/git/oss/php.net/github-php-src/ext/session/tests/session_set_serializer_variation7.php on line 29 +bool(false) +encoded: a:0:{} +Starting session again..! +decoding: a:0:{} +bool(true) +encoded: a:0:{} +NULL +Cleanup.. +decoding: a:0:{} +bool(true) From d83a82a97d5a41d768461785112a4f56a8943861 Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Tue, 19 Jan 2016 09:40:32 +0900 Subject: [PATCH 9/9] Cosmetic changes --- ext/session/php_session.h | 7 ++++--- .../tests/session_set_serializer_iface_variation5.phpt | 1 + ext/session/tests/session_set_serializer_variation1.phpt | 1 - ext/session/tests/session_set_serializer_variation4.phpt | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/session/php_session.h b/ext/session/php_session.h index 2ff2f0e32b121..0099ff619f416 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -332,6 +332,10 @@ extern zend_class_entry *php_session_id_iface_entry; #define PS_UPDATE_TIMESTAMP_IFACE_NAME "SessionUpdateTimestampHandlerInterface" extern zend_class_entry *php_session_update_timestamp_iface_entry; +#define PS_SERIALIZER_IFACE_NAME "SessionSerializerInterface" +extern zend_class_entry *php_session_serializer_iface_entry; + + extern PHP_METHOD(SessionHandler, open); extern PHP_METHOD(SessionHandler, close); extern PHP_METHOD(SessionHandler, read); @@ -342,8 +346,5 @@ extern PHP_METHOD(SessionHandler, create_sid); extern PHP_METHOD(SessionHandler, validateId); extern PHP_METHOD(SessionHandler, updateTimestamp); -#define PS_SERIALIZER_IFACE_NAME "SessionSerializerInterface" -extern zend_class_entry *php_session_serializer_iface_entry; - #endif diff --git a/ext/session/tests/session_set_serializer_iface_variation5.phpt b/ext/session/tests/session_set_serializer_iface_variation5.phpt index e49aacade420c..11231cfbf9dcc 100644 --- a/ext/session/tests/session_set_serializer_iface_variation5.phpt +++ b/ext/session/tests/session_set_serializer_iface_variation5.phpt @@ -37,6 +37,7 @@ $handler = new MySerializer; var_dump(session_set_serializer($handler)); session_start(); +// Should not reach here $session_id = session_id(); $_SESSION["Blah"] = "Hello World!"; $_SESSION["Foo"] = FALSE; diff --git a/ext/session/tests/session_set_serializer_variation1.phpt b/ext/session/tests/session_set_serializer_variation1.phpt index 5b5037f776bd3..0208d564f9813 100644 --- a/ext/session/tests/session_set_serializer_variation1.phpt +++ b/ext/session/tests/session_set_serializer_variation1.phpt @@ -30,7 +30,6 @@ function decode($string) { return unserialize($string) ?: array(); } - $path = dirname(__FILE__); session_save_path($path); var_dump(session_set_serializer("no_encode", "decode")); diff --git a/ext/session/tests/session_set_serializer_variation4.phpt b/ext/session/tests/session_set_serializer_variation4.phpt index c6924dcdfd42f..0cff745c403bf 100644 --- a/ext/session/tests/session_set_serializer_variation4.phpt +++ b/ext/session/tests/session_set_serializer_variation4.phpt @@ -31,7 +31,6 @@ function decode($string) { return unserialize($string) ?: array(); } - var_dump(session_set_serializer("encode", "decode")); // Shouldn't reach here