Skip to content

Commit c51f77f

Browse files
author
Yasuo Ohgaki
committed
Add php_serialize session.serialize_handler. This patch closes
Request #25630 Request #43980 Request #54383 Bug #65359 and many others similar to these that are closed as "wont fix" or "not a bug". Current serializers have limitations due to register_globals support that are no longer supported. Changing existing serializer may cause compatibility issue. Therefore, new handler is needed to remove needless limitations. php_serialize does not have special characters and allow numerical index in $_SESSION. $_SESSION can be used as ordinary array.
1 parent 7318b85 commit c51f77f

File tree

3 files changed

+346
-2
lines changed

3 files changed

+346
-2
lines changed

ext/session/session.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,51 @@ PHP_INI_END()
827827
/* ***************
828828
* Serializers *
829829
*************** */
830+
PS_SERIALIZER_ENCODE_FUNC(php_serialize) /* {{{ */
831+
{
832+
smart_str buf = {0};
833+
php_serialize_data_t var_hash;
834+
HashTable *_ht = Z_ARRVAL_P(PS(http_session_vars));
835+
int key_type;
836+
PS_ENCODE_VARS;
837+
838+
PHP_VAR_SERIALIZE_INIT(var_hash);
839+
php_var_serialize(&buf, &PS(http_session_vars), &var_hash TSRMLS_CC);
840+
PHP_VAR_SERIALIZE_DESTROY(var_hash);
841+
if (newlen) {
842+
*newlen = buf.len;
843+
}
844+
smart_str_0(&buf);
845+
*newstr = buf.c;
846+
return SUCCESS;
847+
}
848+
/* }}} */
849+
850+
PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */
851+
{
852+
const char *p;
853+
char *name;
854+
const char *endptr = val + vallen;
855+
zval *session_vars;
856+
int namelen;
857+
int has_value;
858+
php_unserialize_data_t var_hash;
859+
860+
PHP_VAR_UNSERIALIZE_INIT(var_hash);
861+
ALLOC_INIT_ZVAL(session_vars);
862+
php_var_unserialize(&session_vars, &val, endptr, &var_hash TSRMLS_CC);
863+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
864+
if (PS(http_session_vars)) {
865+
zval_ptr_dtor(&PS(http_session_vars));
866+
}
867+
if (Z_TYPE_P(session_vars) == IS_NULL) {
868+
array_init(session_vars);
869+
}
870+
PS(http_session_vars) = session_vars;
871+
ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1);
872+
return SUCCESS;
873+
}
874+
/* }}} */
830875

831876
#define PS_BIN_NR_OF_BITS 8
832877
#define PS_BIN_UNDEF (1<<(PS_BIN_NR_OF_BITS-1))
@@ -1008,10 +1053,11 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
10081053
}
10091054
/* }}} */
10101055

1011-
#define MAX_SERIALIZERS 10
1012-
#define PREDEFINED_SERIALIZERS 2
1056+
#define MAX_SERIALIZERS 32
1057+
#define PREDEFINED_SERIALIZERS 3
10131058

10141059
static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = {
1060+
PS_SERIALIZER_ENTRY(php_serialize),
10151061
PS_SERIALIZER_ENTRY(php),
10161062
PS_SERIALIZER_ENTRY(php_binary)
10171063
};
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
--TEST--
2+
Test session_decode() function : basic functionality
3+
--SKIPIF--
4+
<?php include('skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
8+
ob_start();
9+
10+
/*
11+
* Prototype : string session_decode(void)
12+
* Description : Decodes session data from a string
13+
* Source code : ext/session/session.c
14+
*/
15+
16+
echo "*** Testing session_decode() : basic functionality ***\n";
17+
18+
// Get an unset variable
19+
$unset_var = 10;
20+
unset($unset_var);
21+
22+
class classA
23+
{
24+
public function __toString() {
25+
return "Hello World!";
26+
}
27+
}
28+
29+
$heredoc = <<<EOT
30+
Hello World!
31+
EOT;
32+
33+
$fp = fopen(__FILE__, "r");
34+
35+
// Unexpected values to be passed as arguments
36+
$inputs = array(
37+
38+
// Integer data
39+
/*1*/ 0,
40+
1,
41+
12345,
42+
-2345,
43+
44+
// Float data
45+
/*5*/ 10.5,
46+
-10.5,
47+
12.3456789000e10,
48+
12.3456789000E-10,
49+
.5,
50+
51+
// Null data
52+
/*10*/ NULL,
53+
null,
54+
55+
// Boolean data
56+
/*12*/ true,
57+
false,
58+
TRUE,
59+
FALSE,
60+
61+
// Empty strings
62+
/*16*/ "",
63+
'',
64+
65+
// Invalid string data
66+
/*18*/ "Nothing",
67+
'Nothing',
68+
$heredoc,
69+
70+
// Object data
71+
/*21*/ new classA(),
72+
73+
// Undefined data
74+
/*22*/ @$undefined_var,
75+
76+
// Unset data
77+
/*23*/ @$unset_var,
78+
79+
// Resource variable
80+
/*24*/ $fp
81+
);
82+
83+
ini_set('session.serialize_handler', 'php_serialize');
84+
var_dump(session_start());
85+
$iterator = 1;
86+
foreach($inputs as $input) {
87+
echo "\n-- Iteration $iterator --\n";
88+
$_SESSION["data"] = $input;
89+
$encoded = session_encode();
90+
var_dump(session_decode($encoded));
91+
var_dump($_SESSION);
92+
$iterator++;
93+
};
94+
95+
var_dump(session_destroy());
96+
fclose($fp);
97+
echo "Done";
98+
ob_end_flush();
99+
?>
100+
--EXPECTF--
101+
*** Testing session_decode() : basic functionality ***
102+
bool(true)
103+
104+
-- Iteration 1 --
105+
bool(true)
106+
array(1) {
107+
["data"]=>
108+
int(0)
109+
}
110+
111+
-- Iteration 2 --
112+
bool(true)
113+
array(1) {
114+
["data"]=>
115+
int(1)
116+
}
117+
118+
-- Iteration 3 --
119+
bool(true)
120+
array(1) {
121+
["data"]=>
122+
int(12345)
123+
}
124+
125+
-- Iteration 4 --
126+
bool(true)
127+
array(1) {
128+
["data"]=>
129+
int(-2345)
130+
}
131+
132+
-- Iteration 5 --
133+
bool(true)
134+
array(1) {
135+
["data"]=>
136+
float(10.5)
137+
}
138+
139+
-- Iteration 6 --
140+
bool(true)
141+
array(1) {
142+
["data"]=>
143+
float(-10.5)
144+
}
145+
146+
-- Iteration 7 --
147+
bool(true)
148+
array(1) {
149+
["data"]=>
150+
float(123456789000)
151+
}
152+
153+
-- Iteration 8 --
154+
bool(true)
155+
array(1) {
156+
["data"]=>
157+
float(1.23456789E-9)
158+
}
159+
160+
-- Iteration 9 --
161+
bool(true)
162+
array(1) {
163+
["data"]=>
164+
float(0.5)
165+
}
166+
167+
-- Iteration 10 --
168+
bool(true)
169+
array(1) {
170+
["data"]=>
171+
NULL
172+
}
173+
174+
-- Iteration 11 --
175+
bool(true)
176+
array(1) {
177+
["data"]=>
178+
NULL
179+
}
180+
181+
-- Iteration 12 --
182+
bool(true)
183+
array(1) {
184+
["data"]=>
185+
bool(true)
186+
}
187+
188+
-- Iteration 13 --
189+
bool(true)
190+
array(1) {
191+
["data"]=>
192+
bool(false)
193+
}
194+
195+
-- Iteration 14 --
196+
bool(true)
197+
array(1) {
198+
["data"]=>
199+
bool(true)
200+
}
201+
202+
-- Iteration 15 --
203+
bool(true)
204+
array(1) {
205+
["data"]=>
206+
bool(false)
207+
}
208+
209+
-- Iteration 16 --
210+
bool(true)
211+
array(1) {
212+
["data"]=>
213+
string(0) ""
214+
}
215+
216+
-- Iteration 17 --
217+
bool(true)
218+
array(1) {
219+
["data"]=>
220+
string(0) ""
221+
}
222+
223+
-- Iteration 18 --
224+
bool(true)
225+
array(1) {
226+
["data"]=>
227+
string(7) "Nothing"
228+
}
229+
230+
-- Iteration 19 --
231+
bool(true)
232+
array(1) {
233+
["data"]=>
234+
string(7) "Nothing"
235+
}
236+
237+
-- Iteration 20 --
238+
bool(true)
239+
array(1) {
240+
["data"]=>
241+
string(12) "Hello World!"
242+
}
243+
244+
-- Iteration 21 --
245+
bool(true)
246+
array(1) {
247+
["data"]=>
248+
object(classA)#2 (0) {
249+
}
250+
}
251+
252+
-- Iteration 22 --
253+
bool(true)
254+
array(1) {
255+
["data"]=>
256+
NULL
257+
}
258+
259+
-- Iteration 23 --
260+
bool(true)
261+
array(1) {
262+
["data"]=>
263+
NULL
264+
}
265+
266+
-- Iteration 24 --
267+
bool(true)
268+
array(1) {
269+
["data"]=>
270+
int(0)
271+
}
272+
bool(true)
273+
Done
274+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Test session_encode() function : Numeric key raise error. bug65359
3+
--SKIPIF--
4+
<?php include('skipif.inc'); ?>
5+
--FILE--
6+
<?php
7+
ob_start();
8+
9+
ini_set('session.serialize_handler', 'php_serialize');
10+
var_dump(session_start());
11+
$_SESSION[-3] = 'foo';
12+
$_SESSION[3] = 'bar';
13+
$_SESSION['var'] = 123;
14+
var_dump(session_encode());
15+
session_write_close();
16+
17+
// Should finish without errors
18+
echo 'Done'.PHP_EOL;
19+
?>
20+
--EXPECTF--
21+
bool(true)
22+
string(51) "a:3:{i:-3;s:3:"foo";i:3;s:3:"bar";s:3:"var";i:123;}"
23+
Done
24+

0 commit comments

Comments
 (0)