summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--php_suhosin.h1
-rw-r--r--session.c11
-rw-r--r--tests/session/session_recursive_crash.phpt25
3 files changed, 35 insertions, 2 deletions
diff --git a/php_suhosin.h b/php_suhosin.h
index 152fe43..3454f5d 100644
--- a/php_suhosin.h
+++ b/php_suhosin.h
@@ -192,6 +192,7 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin)
192 192
193/* session */ 193/* session */
194 void *s_module; 194 void *s_module;
195 void *s_original_mod;
195 int (*old_s_read)(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC); 196 int (*old_s_read)(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC);
196 int (*old_s_write)(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC); 197 int (*old_s_write)(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC);
197 int (*old_s_destroy)(void **mod_data, const char *key TSRMLS_DC); 198 int (*old_s_destroy)(void **mod_data, const char *key TSRMLS_DC);
diff --git a/session.c b/session.c
index f6cff15..306da60 100644
--- a/session.c
+++ b/session.c
@@ -986,16 +986,20 @@ static int suhosin_hook_s_destroy(void **mod_data, const char *key TSRMLS_DC)
986static void suhosin_hook_session_module(TSRMLS_D) 986static void suhosin_hook_session_module(TSRMLS_D)
987{ 987{
988 ps_module *old_mod = SESSION_G(mod), *mod; 988 ps_module *old_mod = SESSION_G(mod), *mod;
989 989
990 if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) { 990 if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) {
991 return; 991 return;
992 } 992 }
993
993 if (SUHOSIN_G(s_module) == NULL) { 994 if (SUHOSIN_G(s_module) == NULL) {
994 SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module)); 995 SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module));
995 if (mod == NULL) { 996 if (mod == NULL) {
996 return; 997 return;
997 } 998 }
998 } 999 }
1000
1001 SUHOSIN_G(s_original_mod) = old_mod;
1002
999 mod = SUHOSIN_G(s_module); 1003 mod = SUHOSIN_G(s_module);
1000 memcpy(mod, old_mod, sizeof(ps_module)); 1004 memcpy(mod, old_mod, sizeof(ps_module));
1001 1005
@@ -1012,11 +1016,14 @@ static void suhosin_hook_session_module(TSRMLS_D)
1012static PHP_INI_MH(suhosin_OnUpdateSaveHandler) 1016static PHP_INI_MH(suhosin_OnUpdateSaveHandler)
1013{ 1017{
1014 int r; 1018 int r;
1019 char *tmp;
1015 1020
1021 SESSION_G(mod) = SUHOSIN_G(s_original_mod);
1022
1016 r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); 1023 r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
1017 1024
1018 suhosin_hook_session_module(TSRMLS_C); 1025 suhosin_hook_session_module(TSRMLS_C);
1019 1026
1020 return r; 1027 return r;
1021} 1028}
1022 1029
diff --git a/tests/session/session_recursive_crash.phpt b/tests/session/session_recursive_crash.phpt
new file mode 100644
index 0000000..62cb9cd
--- /dev/null
+++ b/tests/session/session_recursive_crash.phpt
@@ -0,0 +1,25 @@
1--TEST--
2session SessionHandler() recursive crash
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--ENV--
6return <<<END
7HTTP_USER_AGENT=test
8END;
9--INI--
10suhosin.session.encrypt=On
11suhosin.session.cryptkey=D3F4UL7
12suhosin.session.cryptua=On
13suhosin.session.cryptdocroot=Off
14suhosin.session.cryptraddr=0
15suhosin.session.checkraddr=0
16--FILE--
17<?php
18session_set_save_handler(new SessionHandler(), true);
19$_SESSION['a'] = 'b';
20var_dump($_SESSION);
21--EXPECTF--
22array(1) {
23 ["a"]=>
24 string(1) "b"
25}