Skip to content

Commit 681a1af

Browse files
committed
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5: update news add CVE add missing test file Fix bug #68594 - Use after free vulnerability in unserialize() Conflicts: ext/standard/var_unserializer.c
2 parents 181f34f + 8efd73c commit 681a1af

File tree

3 files changed

+62
-32
lines changed

3 files changed

+62
-32
lines changed
+23
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

+36-32
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 */
22
#line 1 "ext/standard/var_unserializer.re"
33
/*
44
+----------------------------------------------------------------------+
@@ -342,6 +342,9 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
342342
} else {
343343
/* object properties should include no integers */
344344
convert_to_string(key);
345+
if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) {
346+
var_push_dtor(var_hash, old_data);
347+
}
345348
zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data,
346349
sizeof data, NULL);
347350
}
@@ -475,7 +478,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
475478

476479

477480

478-
#line 479 "ext/standard/var_unserializer.c"
481+
#line 482 "ext/standard/var_unserializer.c"
479482
{
480483
YYCTYPE yych;
481484
static const unsigned char yybm[] = {
@@ -535,9 +538,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
535538
yych = *(YYMARKER = ++YYCURSOR);
536539
if (yych == ':') goto yy95;
537540
yy3:
538-
#line 830 "ext/standard/var_unserializer.re"
541+
#line 833 "ext/standard/var_unserializer.re"
539542
{ return 0; }
540-
#line 541 "ext/standard/var_unserializer.c"
543+
#line 544 "ext/standard/var_unserializer.c"
541544
yy4:
542545
yych = *(YYMARKER = ++YYCURSOR);
543546
if (yych == ':') goto yy89;
@@ -580,13 +583,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
580583
goto yy3;
581584
yy14:
582585
++YYCURSOR;
583-
#line 824 "ext/standard/var_unserializer.re"
586+
#line 827 "ext/standard/var_unserializer.re"
584587
{
585588
/* this is the case where we have less data than planned */
586589
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
587590
return 0; /* not sure if it should be 0 or 1 here? */
588591
}
589-
#line 590 "ext/standard/var_unserializer.c"
592+
#line 593 "ext/standard/var_unserializer.c"
590593
yy16:
591594
yych = *++YYCURSOR;
592595
goto yy3;
@@ -612,11 +615,12 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
612615
if (yybm[0+yych] & 128) {
613616
goto yy20;
614617
}
615-
if (yych != ':') goto yy18;
618+
if (yych <= '/') goto yy18;
619+
if (yych >= ';') goto yy18;
616620
yych = *++YYCURSOR;
617621
if (yych != '"') goto yy18;
618622
++YYCURSOR;
619-
#line 678 "ext/standard/var_unserializer.re"
623+
#line 681 "ext/standard/var_unserializer.re"
620624
{
621625
size_t len, len2, len3, maxlen;
622626
long elements;
@@ -762,7 +766,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
762766

763767
return object_common2(UNSERIALIZE_PASSTHRU, elements);
764768
}
765-
#line 766 "ext/standard/var_unserializer.c"
769+
#line 770 "ext/standard/var_unserializer.c"
766770
yy25:
767771
yych = *++YYCURSOR;
768772
if (yych <= ',') {
@@ -787,15 +791,15 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
787791
yych = *++YYCURSOR;
788792
if (yych != '"') goto yy18;
789793
++YYCURSOR;
790-
#line 670 "ext/standard/var_unserializer.re"
794+
#line 673 "ext/standard/var_unserializer.re"
791795
{
792796

793797
INIT_PZVAL(*rval);
794798

795799
return object_common2(UNSERIALIZE_PASSTHRU,
796800
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
797801
}
798-
#line 799 "ext/standard/var_unserializer.c"
802+
#line 803 "ext/standard/var_unserializer.c"
799803
yy32:
800804
yych = *++YYCURSOR;
801805
if (yych == '+') goto yy33;
@@ -816,7 +820,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
816820
yych = *++YYCURSOR;
817821
if (yych != '{') goto yy18;
818822
++YYCURSOR;
819-
#line 650 "ext/standard/var_unserializer.re"
823+
#line 653 "ext/standard/var_unserializer.re"
820824
{
821825
long elements = parse_iv(start + 2);
822826
/* use iv() not uiv() in order to check data range */
@@ -836,7 +840,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
836840

837841
return finish_nested_data(UNSERIALIZE_PASSTHRU);
838842
}
839-
#line 840 "ext/standard/var_unserializer.c"
843+
#line 844 "ext/standard/var_unserializer.c"
840844
yy39:
841845
yych = *++YYCURSOR;
842846
if (yych == '+') goto yy40;
@@ -857,7 +861,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
857861
yych = *++YYCURSOR;
858862
if (yych != '"') goto yy18;
859863
++YYCURSOR;
860-
#line 621 "ext/standard/var_unserializer.re"
864+
#line 624 "ext/standard/var_unserializer.re"
861865
{
862866
size_t len, maxlen;
863867
char *str;
@@ -886,7 +890,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
886890
ZVAL_STRINGL(*rval, str, len, 0);
887891
return 1;
888892
}
889-
#line 890 "ext/standard/var_unserializer.c"
893+
#line 894 "ext/standard/var_unserializer.c"
890894
yy46:
891895
yych = *++YYCURSOR;
892896
if (yych == '+') goto yy47;
@@ -907,7 +911,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
907911
yych = *++YYCURSOR;
908912
if (yych != '"') goto yy18;
909913
++YYCURSOR;
910-
#line 593 "ext/standard/var_unserializer.re"
914+
#line 596 "ext/standard/var_unserializer.re"
911915
{
912916
size_t len, maxlen;
913917
char *str;
@@ -935,7 +939,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
935939
ZVAL_STRINGL(*rval, str, len, 1);
936940
return 1;
937941
}
938-
#line 939 "ext/standard/var_unserializer.c"
942+
#line 943 "ext/standard/var_unserializer.c"
939943
yy53:
940944
yych = *++YYCURSOR;
941945
if (yych <= '/') {
@@ -1023,7 +1027,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10231027
}
10241028
yy63:
10251029
++YYCURSOR;
1026-
#line 583 "ext/standard/var_unserializer.re"
1030+
#line 586 "ext/standard/var_unserializer.re"
10271031
{
10281032
#if SIZEOF_LONG == 4
10291033
use_double:
@@ -1033,7 +1037,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10331037
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
10341038
return 1;
10351039
}
1036-
#line 1037 "ext/standard/var_unserializer.c"
1040+
#line 1041 "ext/standard/var_unserializer.c"
10371041
yy65:
10381042
yych = *++YYCURSOR;
10391043
if (yych <= ',') {
@@ -1092,7 +1096,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10921096
yych = *++YYCURSOR;
10931097
if (yych != ';') goto yy18;
10941098
++YYCURSOR;
1095-
#line 568 "ext/standard/var_unserializer.re"
1099+
#line 571 "ext/standard/var_unserializer.re"
10961100
{
10971101
*p = YYCURSOR;
10981102
INIT_PZVAL(*rval);
@@ -1107,7 +1111,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11071111

11081112
return 1;
11091113
}
1110-
#line 1111 "ext/standard/var_unserializer.c"
1114+
#line 1115 "ext/standard/var_unserializer.c"
11111115
yy76:
11121116
yych = *++YYCURSOR;
11131117
if (yych == 'N') goto yy73;
@@ -1134,7 +1138,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11341138
if (yych <= '9') goto yy79;
11351139
if (yych != ';') goto yy18;
11361140
++YYCURSOR;
1137-
#line 541 "ext/standard/var_unserializer.re"
1141+
#line 544 "ext/standard/var_unserializer.re"
11381142
{
11391143
#if SIZEOF_LONG == 4
11401144
int digits = YYCURSOR - start - 3;
@@ -1161,32 +1165,32 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11611165
ZVAL_LONG(*rval, parse_iv(start + 2));
11621166
return 1;
11631167
}
1164-
#line 1165 "ext/standard/var_unserializer.c"
1168+
#line 1169 "ext/standard/var_unserializer.c"
11651169
yy83:
11661170
yych = *++YYCURSOR;
11671171
if (yych <= '/') goto yy18;
11681172
if (yych >= '2') goto yy18;
11691173
yych = *++YYCURSOR;
11701174
if (yych != ';') goto yy18;
11711175
++YYCURSOR;
1172-
#line 534 "ext/standard/var_unserializer.re"
1176+
#line 537 "ext/standard/var_unserializer.re"
11731177
{
11741178
*p = YYCURSOR;
11751179
INIT_PZVAL(*rval);
11761180
ZVAL_BOOL(*rval, parse_iv(start + 2));
11771181
return 1;
11781182
}
1179-
#line 1180 "ext/standard/var_unserializer.c"
1183+
#line 1184 "ext/standard/var_unserializer.c"
11801184
yy87:
11811185
++YYCURSOR;
1182-
#line 527 "ext/standard/var_unserializer.re"
1186+
#line 530 "ext/standard/var_unserializer.re"
11831187
{
11841188
*p = YYCURSOR;
11851189
INIT_PZVAL(*rval);
11861190
ZVAL_NULL(*rval);
11871191
return 1;
11881192
}
1189-
#line 1190 "ext/standard/var_unserializer.c"
1193+
#line 1194 "ext/standard/var_unserializer.c"
11901194
yy89:
11911195
yych = *++YYCURSOR;
11921196
if (yych <= ',') {
@@ -1209,7 +1213,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12091213
if (yych <= '9') goto yy91;
12101214
if (yych != ';') goto yy18;
12111215
++YYCURSOR;
1212-
#line 504 "ext/standard/var_unserializer.re"
1216+
#line 507 "ext/standard/var_unserializer.re"
12131217
{
12141218
long id;
12151219

@@ -1232,7 +1236,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12321236

12331237
return 1;
12341238
}
1235-
#line 1236 "ext/standard/var_unserializer.c"
1239+
#line 1240 "ext/standard/var_unserializer.c"
12361240
yy95:
12371241
yych = *++YYCURSOR;
12381242
if (yych <= ',') {
@@ -1255,7 +1259,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12551259
if (yych <= '9') goto yy97;
12561260
if (yych != ';') goto yy18;
12571261
++YYCURSOR;
1258-
#line 483 "ext/standard/var_unserializer.re"
1262+
#line 486 "ext/standard/var_unserializer.re"
12591263
{
12601264
long id;
12611265

@@ -1276,9 +1280,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12761280

12771281
return 1;
12781282
}
1279-
#line 1280 "ext/standard/var_unserializer.c"
1283+
#line 1284 "ext/standard/var_unserializer.c"
12801284
}
1281-
#line 832 "ext/standard/var_unserializer.re"
1285+
#line 835 "ext/standard/var_unserializer.re"
12821286

12831287

12841288
return 0;

ext/standard/var_unserializer.re

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

0 commit comments

Comments
 (0)