Skip to content

Commit 9152214

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

File tree

3 files changed

+72
-60
lines changed

3 files changed

+72
-60
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: 41 additions & 46 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 */
22
#line 1 "ext/standard/var_unserializer.re"
33
/*
44
+----------------------------------------------------------------------+
@@ -362,21 +362,15 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend
362362
} else {
363363
/* object properties should include no integers */
364364
convert_to_string(&key);
365-
//???
366-
#if 1
367-
data = zend_hash_update_ind(ht, Z_STR(key), &d);
368-
#else
369-
if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) {
370-
if (Z_TYPE_P(data) == IS_INDIRECT) {
371-
data = Z_INDIRECT_P(data);
365+
if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
366+
if (Z_TYPE_P(old_data) == IS_INDIRECT) {
367+
old_data = Z_INDIRECT_P(old_data);
372368
}
373-
zval_ptr_dtor(data);
374-
//??? var_push_dtor(var_hash, data);
375-
ZVAL_UNDEF(data);
376-
} else {
377-
data = zend_hash_update(ht, Z_STR(key), &d);
378-
}
379-
#endif
369+
zval_ptr_dtor(old_data);
370+
var_push_dtor(var_hash, old_data);
371+
ZVAL_UNDEF(old_data);
372+
}
373+
data = zend_hash_update(ht, Z_STR(key), &d);
380374
}
381375

382376
zval_dtor(&key);
@@ -515,7 +509,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
515509
start = cursor;
516510

517511

518-
#line 519 "ext/standard/var_unserializer.c"
512+
#line 513 "ext/standard/var_unserializer.c"
519513
{
520514
YYCTYPE yych;
521515
static const unsigned char yybm[] = {
@@ -575,9 +569,9 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
575569
yych = *(YYMARKER = ++YYCURSOR);
576570
if (yych == ':') goto yy95;
577571
yy3:
578-
#line 866 "ext/standard/var_unserializer.re"
572+
#line 860 "ext/standard/var_unserializer.re"
579573
{ return 0; }
580-
#line 581 "ext/standard/var_unserializer.c"
574+
#line 575 "ext/standard/var_unserializer.c"
581575
yy4:
582576
yych = *(YYMARKER = ++YYCURSOR);
583577
if (yych == ':') goto yy89;
@@ -620,13 +614,13 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
620614
goto yy3;
621615
yy14:
622616
++YYCURSOR;
623-
#line 860 "ext/standard/var_unserializer.re"
617+
#line 854 "ext/standard/var_unserializer.re"
624618
{
625619
/* this is the case where we have less data than planned */
626620
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
627621
return 0; /* not sure if it should be 0 or 1 here? */
628622
}
629-
#line 630 "ext/standard/var_unserializer.c"
623+
#line 624 "ext/standard/var_unserializer.c"
630624
yy16:
631625
yych = *++YYCURSOR;
632626
goto yy3;
@@ -652,11 +646,12 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
652646
if (yybm[0+yych] & 128) {
653647
goto yy20;
654648
}
655-
if (yych != ':') goto yy18;
649+
if (yych <= '/') goto yy18;
650+
if (yych >= ';') goto yy18;
656651
yych = *++YYCURSOR;
657652
if (yych != '"') goto yy18;
658653
++YYCURSOR;
659-
#line 715 "ext/standard/var_unserializer.re"
654+
#line 709 "ext/standard/var_unserializer.re"
660655
{
661656
size_t len, len2, len3, maxlen;
662657
zend_long elements;
@@ -801,7 +796,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
801796

802797
return object_common2(UNSERIALIZE_PASSTHRU, elements);
803798
}
804-
#line 805 "ext/standard/var_unserializer.c"
799+
#line 800 "ext/standard/var_unserializer.c"
805800
yy25:
806801
yych = *++YYCURSOR;
807802
if (yych <= ',') {
@@ -826,15 +821,15 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
826821
yych = *++YYCURSOR;
827822
if (yych != '"') goto yy18;
828823
++YYCURSOR;
829-
#line 707 "ext/standard/var_unserializer.re"
824+
#line 701 "ext/standard/var_unserializer.re"
830825
{
831826

832827
//??? INIT_PZVAL(rval);
833828

834829
return object_common2(UNSERIALIZE_PASSTHRU,
835830
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
836831
}
837-
#line 838 "ext/standard/var_unserializer.c"
832+
#line 833 "ext/standard/var_unserializer.c"
838833
yy32:
839834
yych = *++YYCURSOR;
840835
if (yych == '+') goto yy33;
@@ -855,7 +850,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
855850
yych = *++YYCURSOR;
856851
if (yych != '{') goto yy18;
857852
++YYCURSOR;
858-
#line 686 "ext/standard/var_unserializer.re"
853+
#line 680 "ext/standard/var_unserializer.re"
859854
{
860855
zend_long elements = parse_iv(start + 2);
861856
/* use iv() not uiv() in order to check data range */
@@ -876,7 +871,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
876871

877872
return finish_nested_data(UNSERIALIZE_PASSTHRU);
878873
}
879-
#line 880 "ext/standard/var_unserializer.c"
874+
#line 875 "ext/standard/var_unserializer.c"
880875
yy39:
881876
yych = *++YYCURSOR;
882877
if (yych == '+') goto yy40;
@@ -897,7 +892,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
897892
yych = *++YYCURSOR;
898893
if (yych != '"') goto yy18;
899894
++YYCURSOR;
900-
#line 658 "ext/standard/var_unserializer.re"
895+
#line 652 "ext/standard/var_unserializer.re"
901896
{
902897
size_t len, maxlen;
903898
zend_string *str;
@@ -925,7 +920,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
925920
ZVAL_STR(rval, str);
926921
return 1;
927922
}
928-
#line 929 "ext/standard/var_unserializer.c"
923+
#line 924 "ext/standard/var_unserializer.c"
929924
yy46:
930925
yych = *++YYCURSOR;
931926
if (yych == '+') goto yy47;
@@ -946,7 +941,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
946941
yych = *++YYCURSOR;
947942
if (yych != '"') goto yy18;
948943
++YYCURSOR;
949-
#line 631 "ext/standard/var_unserializer.re"
944+
#line 625 "ext/standard/var_unserializer.re"
950945
{
951946
size_t len, maxlen;
952947
char *str;
@@ -973,7 +968,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
973968
ZVAL_STRINGL(rval, str, len);
974969
return 1;
975970
}
976-
#line 977 "ext/standard/var_unserializer.c"
971+
#line 972 "ext/standard/var_unserializer.c"
977972
yy53:
978973
yych = *++YYCURSOR;
979974
if (yych <= '/') {
@@ -1061,7 +1056,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
10611056
}
10621057
yy63:
10631058
++YYCURSOR;
1064-
#line 622 "ext/standard/var_unserializer.re"
1059+
#line 616 "ext/standard/var_unserializer.re"
10651060
{
10661061
#if SIZEOF_ZEND_LONG == 4
10671062
use_double:
@@ -1070,7 +1065,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
10701065
ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
10711066
return 1;
10721067
}
1073-
#line 1074 "ext/standard/var_unserializer.c"
1068+
#line 1069 "ext/standard/var_unserializer.c"
10741069
yy65:
10751070
yych = *++YYCURSOR;
10761071
if (yych <= ',') {
@@ -1129,7 +1124,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
11291124
yych = *++YYCURSOR;
11301125
if (yych != ';') goto yy18;
11311126
++YYCURSOR;
1132-
#line 606 "ext/standard/var_unserializer.re"
1127+
#line 600 "ext/standard/var_unserializer.re"
11331128
{
11341129
*p = YYCURSOR;
11351130

@@ -1145,7 +1140,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
11451140

11461141
return 1;
11471142
}
1148-
#line 1149 "ext/standard/var_unserializer.c"
1143+
#line 1144 "ext/standard/var_unserializer.c"
11491144
yy76:
11501145
yych = *++YYCURSOR;
11511146
if (yych == 'N') goto yy73;
@@ -1172,7 +1167,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
11721167
if (yych <= '9') goto yy79;
11731168
if (yych != ';') goto yy18;
11741169
++YYCURSOR;
1175-
#line 580 "ext/standard/var_unserializer.re"
1170+
#line 574 "ext/standard/var_unserializer.re"
11761171
{
11771172
#if SIZEOF_ZEND_LONG == 4
11781173
int digits = YYCURSOR - start - 3;
@@ -1198,30 +1193,30 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
11981193
ZVAL_LONG(rval, parse_iv(start + 2));
11991194
return 1;
12001195
}
1201-
#line 1202 "ext/standard/var_unserializer.c"
1196+
#line 1197 "ext/standard/var_unserializer.c"
12021197
yy83:
12031198
yych = *++YYCURSOR;
12041199
if (yych <= '/') goto yy18;
12051200
if (yych >= '2') goto yy18;
12061201
yych = *++YYCURSOR;
12071202
if (yych != ';') goto yy18;
12081203
++YYCURSOR;
1209-
#line 574 "ext/standard/var_unserializer.re"
1204+
#line 568 "ext/standard/var_unserializer.re"
12101205
{
12111206
*p = YYCURSOR;
12121207
ZVAL_BOOL(rval, parse_iv(start + 2));
12131208
return 1;
12141209
}
1215-
#line 1216 "ext/standard/var_unserializer.c"
1210+
#line 1211 "ext/standard/var_unserializer.c"
12161211
yy87:
12171212
++YYCURSOR;
1218-
#line 568 "ext/standard/var_unserializer.re"
1213+
#line 562 "ext/standard/var_unserializer.re"
12191214
{
12201215
*p = YYCURSOR;
12211216
ZVAL_NULL(rval);
12221217
return 1;
12231218
}
1224-
#line 1225 "ext/standard/var_unserializer.c"
1219+
#line 1220 "ext/standard/var_unserializer.c"
12251220
yy89:
12261221
yych = *++YYCURSOR;
12271222
if (yych <= ',') {
@@ -1244,7 +1239,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
12441239
if (yych <= '9') goto yy91;
12451240
if (yych != ';') goto yy18;
12461241
++YYCURSOR;
1247-
#line 545 "ext/standard/var_unserializer.re"
1242+
#line 539 "ext/standard/var_unserializer.re"
12481243
{
12491244
zend_long id;
12501245

@@ -1267,7 +1262,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
12671262

12681263
return 1;
12691264
}
1270-
#line 1271 "ext/standard/var_unserializer.c"
1265+
#line 1266 "ext/standard/var_unserializer.c"
12711266
yy95:
12721267
yych = *++YYCURSOR;
12731268
if (yych <= ',') {
@@ -1290,7 +1285,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
12901285
if (yych <= '9') goto yy97;
12911286
if (yych != ';') goto yy18;
12921287
++YYCURSOR;
1293-
#line 523 "ext/standard/var_unserializer.re"
1288+
#line 517 "ext/standard/var_unserializer.re"
12941289
{
12951290
zend_long id;
12961291

@@ -1312,9 +1307,9 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
13121307

13131308
return 1;
13141309
}
1315-
#line 1316 "ext/standard/var_unserializer.c"
1310+
#line 1311 "ext/standard/var_unserializer.c"
13161311
}
1317-
#line 868 "ext/standard/var_unserializer.re"
1312+
#line 862 "ext/standard/var_unserializer.re"
13181313

13191314

13201315
return 0;

ext/standard/var_unserializer.re

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -366,21 +366,15 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend
366366
} else {
367367
/* object properties should include no integers */
368368
convert_to_string(&key);
369-
//???
370-
#if 1
371-
data = zend_hash_update_ind(ht, Z_STR(key), &d);
372-
#else
373-
if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) {
374-
if (Z_TYPE_P(data) == IS_INDIRECT) {
375-
data = Z_INDIRECT_P(data);
369+
if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
370+
if (Z_TYPE_P(old_data) == IS_INDIRECT) {
371+
old_data = Z_INDIRECT_P(old_data);
376372
}
377-
zval_ptr_dtor(data);
378-
//??? var_push_dtor(var_hash, data);
379-
ZVAL_UNDEF(data);
380-
} else {
381-
data = zend_hash_update(ht, Z_STR(key), &d);
382-
}
383-
#endif
373+
zval_ptr_dtor(old_data);
374+
var_push_dtor(var_hash, old_data);
375+
ZVAL_UNDEF(old_data);
376+
}
377+
data = zend_hash_update(ht, Z_STR(key), &d);
384378
}
385379

386380
zval_dtor(&key);

0 commit comments

Comments
 (0)