Skip to content

Commit 622a346

Browse files
committed
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4: add CVE add missing test file Fix bug #68594 - Use after free vulnerability in unserialize()
2 parents 9c4de38 + 53f129a commit 622a346

File tree

3 files changed

+62
-32
lines changed

3 files changed

+62
-32
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Bug #68545 Use after free vulnerability in unserialize()
3+
--FILE--
4+
<?php
5+
for ($i=4; $i<100; $i++) {
6+
$m = new StdClass();
7+
8+
$u = array(1);
9+
10+
$m->aaa = array(1,2,&$u,4,5);
11+
$m->bbb = 1;
12+
$m->ccc = &$u;
13+
$m->ddd = str_repeat("A", $i);
14+
15+
$z = serialize($m);
16+
$z = str_replace("bbb", "aaa", $z);
17+
$y = unserialize($z);
18+
$z = serialize($y);
19+
}
20+
?>
21+
===DONE===
22+
--EXPECTF--
23+
===DONE===

ext/standard/var_unserializer.c

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Generated by re2c 0.13.5 */
1+
/* Generated by re2c 0.13.7.5 on Thu Dec 11 19:26:19 2014 */
22
#line 1 "ext/standard/var_unserializer.re"
33
/*
44
+----------------------------------------------------------------------+
@@ -343,6 +343,9 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
343343
} else {
344344
/* object properties should include no integers */
345345
convert_to_string(key);
346+
if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
347+
var_push_dtor(var_hash, old_data);
348+
}
346349
zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data,
347350
sizeof data, NULL);
348351
}
@@ -480,7 +483,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
480483

481484

482485

483-
#line 484 "ext/standard/var_unserializer.c"
486+
#line 487 "ext/standard/var_unserializer.c"
484487
{
485488
YYCTYPE yych;
486489
static const unsigned char yybm[] = {
@@ -540,9 +543,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
540543
yych = *(YYMARKER = ++YYCURSOR);
541544
if (yych == ':') goto yy95;
542545
yy3:
543-
#line 835 "ext/standard/var_unserializer.re"
546+
#line 838 "ext/standard/var_unserializer.re"
544547
{ return 0; }
545-
#line 546 "ext/standard/var_unserializer.c"
548+
#line 549 "ext/standard/var_unserializer.c"
546549
yy4:
547550
yych = *(YYMARKER = ++YYCURSOR);
548551
if (yych == ':') goto yy89;
@@ -585,13 +588,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
585588
goto yy3;
586589
yy14:
587590
++YYCURSOR;
588-
#line 829 "ext/standard/var_unserializer.re"
591+
#line 832 "ext/standard/var_unserializer.re"
589592
{
590593
/* this is the case where we have less data than planned */
591594
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
592595
return 0; /* not sure if it should be 0 or 1 here? */
593596
}
594-
#line 595 "ext/standard/var_unserializer.c"
597+
#line 598 "ext/standard/var_unserializer.c"
595598
yy16:
596599
yych = *++YYCURSOR;
597600
goto yy3;
@@ -617,11 +620,12 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
617620
if (yybm[0+yych] & 128) {
618621
goto yy20;
619622
}
620-
if (yych != ':') goto yy18;
623+
if (yych <= '/') goto yy18;
624+
if (yych >= ';') goto yy18;
621625
yych = *++YYCURSOR;
622626
if (yych != '"') goto yy18;
623627
++YYCURSOR;
624-
#line 683 "ext/standard/var_unserializer.re"
628+
#line 686 "ext/standard/var_unserializer.re"
625629
{
626630
size_t len, len2, len3, maxlen;
627631
long elements;
@@ -767,7 +771,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
767771

768772
return object_common2(UNSERIALIZE_PASSTHRU, elements);
769773
}
770-
#line 771 "ext/standard/var_unserializer.c"
774+
#line 775 "ext/standard/var_unserializer.c"
771775
yy25:
772776
yych = *++YYCURSOR;
773777
if (yych <= ',') {
@@ -792,15 +796,15 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
792796
yych = *++YYCURSOR;
793797
if (yych != '"') goto yy18;
794798
++YYCURSOR;
795-
#line 675 "ext/standard/var_unserializer.re"
799+
#line 678 "ext/standard/var_unserializer.re"
796800
{
797801

798802
INIT_PZVAL(*rval);
799803

800804
return object_common2(UNSERIALIZE_PASSTHRU,
801805
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
802806
}
803-
#line 804 "ext/standard/var_unserializer.c"
807+
#line 808 "ext/standard/var_unserializer.c"
804808
yy32:
805809
yych = *++YYCURSOR;
806810
if (yych == '+') goto yy33;
@@ -821,7 +825,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
821825
yych = *++YYCURSOR;
822826
if (yych != '{') goto yy18;
823827
++YYCURSOR;
824-
#line 655 "ext/standard/var_unserializer.re"
828+
#line 658 "ext/standard/var_unserializer.re"
825829
{
826830
long elements = parse_iv(start + 2);
827831
/* use iv() not uiv() in order to check data range */
@@ -841,7 +845,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
841845

842846
return finish_nested_data(UNSERIALIZE_PASSTHRU);
843847
}
844-
#line 845 "ext/standard/var_unserializer.c"
848+
#line 849 "ext/standard/var_unserializer.c"
845849
yy39:
846850
yych = *++YYCURSOR;
847851
if (yych == '+') goto yy40;
@@ -862,7 +866,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
862866
yych = *++YYCURSOR;
863867
if (yych != '"') goto yy18;
864868
++YYCURSOR;
865-
#line 626 "ext/standard/var_unserializer.re"
869+
#line 629 "ext/standard/var_unserializer.re"
866870
{
867871
size_t len, maxlen;
868872
char *str;
@@ -891,7 +895,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
891895
ZVAL_STRINGL(*rval, str, len, 0);
892896
return 1;
893897
}
894-
#line 895 "ext/standard/var_unserializer.c"
898+
#line 899 "ext/standard/var_unserializer.c"
895899
yy46:
896900
yych = *++YYCURSOR;
897901
if (yych == '+') goto yy47;
@@ -912,7 +916,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
912916
yych = *++YYCURSOR;
913917
if (yych != '"') goto yy18;
914918
++YYCURSOR;
915-
#line 598 "ext/standard/var_unserializer.re"
919+
#line 601 "ext/standard/var_unserializer.re"
916920
{
917921
size_t len, maxlen;
918922
char *str;
@@ -940,7 +944,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
940944
ZVAL_STRINGL(*rval, str, len, 1);
941945
return 1;
942946
}
943-
#line 944 "ext/standard/var_unserializer.c"
947+
#line 948 "ext/standard/var_unserializer.c"
944948
yy53:
945949
yych = *++YYCURSOR;
946950
if (yych <= '/') {
@@ -1028,7 +1032,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10281032
}
10291033
yy63:
10301034
++YYCURSOR;
1031-
#line 588 "ext/standard/var_unserializer.re"
1035+
#line 591 "ext/standard/var_unserializer.re"
10321036
{
10331037
#if SIZEOF_LONG == 4
10341038
use_double:
@@ -1038,7 +1042,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10381042
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
10391043
return 1;
10401044
}
1041-
#line 1042 "ext/standard/var_unserializer.c"
1045+
#line 1046 "ext/standard/var_unserializer.c"
10421046
yy65:
10431047
yych = *++YYCURSOR;
10441048
if (yych <= ',') {
@@ -1097,7 +1101,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10971101
yych = *++YYCURSOR;
10981102
if (yych != ';') goto yy18;
10991103
++YYCURSOR;
1100-
#line 573 "ext/standard/var_unserializer.re"
1104+
#line 576 "ext/standard/var_unserializer.re"
11011105
{
11021106
*p = YYCURSOR;
11031107
INIT_PZVAL(*rval);
@@ -1112,7 +1116,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11121116

11131117
return 1;
11141118
}
1115-
#line 1116 "ext/standard/var_unserializer.c"
1119+
#line 1120 "ext/standard/var_unserializer.c"
11161120
yy76:
11171121
yych = *++YYCURSOR;
11181122
if (yych == 'N') goto yy73;
@@ -1139,7 +1143,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11391143
if (yych <= '9') goto yy79;
11401144
if (yych != ';') goto yy18;
11411145
++YYCURSOR;
1142-
#line 546 "ext/standard/var_unserializer.re"
1146+
#line 549 "ext/standard/var_unserializer.re"
11431147
{
11441148
#if SIZEOF_LONG == 4
11451149
int digits = YYCURSOR - start - 3;
@@ -1166,32 +1170,32 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11661170
ZVAL_LONG(*rval, parse_iv(start + 2));
11671171
return 1;
11681172
}
1169-
#line 1170 "ext/standard/var_unserializer.c"
1173+
#line 1174 "ext/standard/var_unserializer.c"
11701174
yy83:
11711175
yych = *++YYCURSOR;
11721176
if (yych <= '/') goto yy18;
11731177
if (yych >= '2') goto yy18;
11741178
yych = *++YYCURSOR;
11751179
if (yych != ';') goto yy18;
11761180
++YYCURSOR;
1177-
#line 539 "ext/standard/var_unserializer.re"
1181+
#line 542 "ext/standard/var_unserializer.re"
11781182
{
11791183
*p = YYCURSOR;
11801184
INIT_PZVAL(*rval);
11811185
ZVAL_BOOL(*rval, parse_iv(start + 2));
11821186
return 1;
11831187
}
1184-
#line 1185 "ext/standard/var_unserializer.c"
1188+
#line 1189 "ext/standard/var_unserializer.c"
11851189
yy87:
11861190
++YYCURSOR;
1187-
#line 532 "ext/standard/var_unserializer.re"
1191+
#line 535 "ext/standard/var_unserializer.re"
11881192
{
11891193
*p = YYCURSOR;
11901194
INIT_PZVAL(*rval);
11911195
ZVAL_NULL(*rval);
11921196
return 1;
11931197
}
1194-
#line 1195 "ext/standard/var_unserializer.c"
1198+
#line 1199 "ext/standard/var_unserializer.c"
11951199
yy89:
11961200
yych = *++YYCURSOR;
11971201
if (yych <= ',') {
@@ -1214,7 +1218,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12141218
if (yych <= '9') goto yy91;
12151219
if (yych != ';') goto yy18;
12161220
++YYCURSOR;
1217-
#line 509 "ext/standard/var_unserializer.re"
1221+
#line 512 "ext/standard/var_unserializer.re"
12181222
{
12191223
long id;
12201224

@@ -1237,7 +1241,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12371241

12381242
return 1;
12391243
}
1240-
#line 1241 "ext/standard/var_unserializer.c"
1244+
#line 1245 "ext/standard/var_unserializer.c"
12411245
yy95:
12421246
yych = *++YYCURSOR;
12431247
if (yych <= ',') {
@@ -1260,7 +1264,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12601264
if (yych <= '9') goto yy97;
12611265
if (yych != ';') goto yy18;
12621266
++YYCURSOR;
1263-
#line 488 "ext/standard/var_unserializer.re"
1267+
#line 491 "ext/standard/var_unserializer.re"
12641268
{
12651269
long id;
12661270

@@ -1281,9 +1285,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12811285

12821286
return 1;
12831287
}
1284-
#line 1285 "ext/standard/var_unserializer.c"
1288+
#line 1289 "ext/standard/var_unserializer.c"
12851289
}
1286-
#line 837 "ext/standard/var_unserializer.re"
1290+
#line 840 "ext/standard/var_unserializer.re"
12871291

12881292

12891293
return 0;

ext/standard/var_unserializer.re

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
347347
} else {
348348
/* object properties should include no integers */
349349
convert_to_string(key);
350+
if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
351+
var_push_dtor(var_hash, old_data);
352+
}
350353
zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data,
351354
sizeof data, NULL);
352355
}

0 commit comments

Comments
 (0)