Skip to content

Commit caebb76

Browse files
committed
Fixed bug #69139 (Crash in gc_zval_possible_root on unserialize)
1 parent 55f7747 commit caebb76

File tree

4 files changed

+46
-37
lines changed

4 files changed

+46
-37
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ PHP NEWS
33
?? ??? 2015, PHP 5.5.23
44

55
- Core:
6+
. Fixed bug #69139 (Crash in gc_zval_possible_root on unserialize).
7+
(Laruence)
68
. Fixed bug #69121 (Segfault in get_current_user when script owner is not
79
in passwd with ZTS build). (dan at syneto dot net)
810
. Fixed bug #65593 (Segfault when calling ob_start from output buffering
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Bug #69139 (Crash in gc_zval_possible_root on unserialize)
3+
--FILE--
4+
<?php
5+
$str = 'a:1126666:{i:0;r:1;i:-09610;r:1;i:-0;i:0;i:0;O:1:"A":2119X:i:0;i:0;i:0;i:0;i:0;O:1:"A":2116:{i:0;r:5;i:-096766610;r:1;i:-610;r:1;i:0;i:0;';
6+
@unserialize($str);
7+
echo "Alive";
8+
?>
9+
--EXPECT--
10+
Alive

ext/standard/var_unserializer.c

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Generated by re2c 0.13.7.5 on Thu Jan 1 14:43:18 2015 */
1+
/* Generated by re2c 0.13.5 */
22
#line 1 "ext/standard/var_unserializer.re"
33
/*
44
+----------------------------------------------------------------------+
@@ -320,8 +320,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
320320
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
321321
zval_dtor(key);
322322
FREE_ZVAL(key);
323-
zval_dtor(data);
324-
FREE_ZVAL(data);
323+
zval_ptr_dtor(&data);
325324
return 0;
326325
}
327326

@@ -483,7 +482,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
483482

484483

485484

486-
#line 487 "ext/standard/var_unserializer.c"
485+
#line 486 "ext/standard/var_unserializer.c"
487486
{
488487
YYCTYPE yych;
489488
static const unsigned char yybm[] = {
@@ -543,9 +542,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
543542
yych = *(YYMARKER = ++YYCURSOR);
544543
if (yych == ':') goto yy95;
545544
yy3:
546-
#line 838 "ext/standard/var_unserializer.re"
545+
#line 837 "ext/standard/var_unserializer.re"
547546
{ return 0; }
548-
#line 549 "ext/standard/var_unserializer.c"
547+
#line 548 "ext/standard/var_unserializer.c"
549548
yy4:
550549
yych = *(YYMARKER = ++YYCURSOR);
551550
if (yych == ':') goto yy89;
@@ -588,13 +587,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
588587
goto yy3;
589588
yy14:
590589
++YYCURSOR;
591-
#line 832 "ext/standard/var_unserializer.re"
590+
#line 831 "ext/standard/var_unserializer.re"
592591
{
593592
/* this is the case where we have less data than planned */
594593
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
595594
return 0; /* not sure if it should be 0 or 1 here? */
596595
}
597-
#line 598 "ext/standard/var_unserializer.c"
596+
#line 597 "ext/standard/var_unserializer.c"
598597
yy16:
599598
yych = *++YYCURSOR;
600599
goto yy3;
@@ -620,12 +619,11 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
620619
if (yybm[0+yych] & 128) {
621620
goto yy20;
622621
}
623-
if (yych <= '/') goto yy18;
624-
if (yych >= ';') goto yy18;
622+
if (yych != ':') goto yy18;
625623
yych = *++YYCURSOR;
626624
if (yych != '"') goto yy18;
627625
++YYCURSOR;
628-
#line 686 "ext/standard/var_unserializer.re"
626+
#line 685 "ext/standard/var_unserializer.re"
629627
{
630628
size_t len, len2, len3, maxlen;
631629
long elements;
@@ -771,7 +769,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
771769

772770
return object_common2(UNSERIALIZE_PASSTHRU, elements);
773771
}
774-
#line 775 "ext/standard/var_unserializer.c"
772+
#line 773 "ext/standard/var_unserializer.c"
775773
yy25:
776774
yych = *++YYCURSOR;
777775
if (yych <= ',') {
@@ -796,15 +794,15 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
796794
yych = *++YYCURSOR;
797795
if (yych != '"') goto yy18;
798796
++YYCURSOR;
799-
#line 678 "ext/standard/var_unserializer.re"
797+
#line 677 "ext/standard/var_unserializer.re"
800798
{
801799

802800
INIT_PZVAL(*rval);
803801

804802
return object_common2(UNSERIALIZE_PASSTHRU,
805803
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
806804
}
807-
#line 808 "ext/standard/var_unserializer.c"
805+
#line 806 "ext/standard/var_unserializer.c"
808806
yy32:
809807
yych = *++YYCURSOR;
810808
if (yych == '+') goto yy33;
@@ -825,7 +823,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
825823
yych = *++YYCURSOR;
826824
if (yych != '{') goto yy18;
827825
++YYCURSOR;
828-
#line 658 "ext/standard/var_unserializer.re"
826+
#line 657 "ext/standard/var_unserializer.re"
829827
{
830828
long elements = parse_iv(start + 2);
831829
/* use iv() not uiv() in order to check data range */
@@ -845,7 +843,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
845843

846844
return finish_nested_data(UNSERIALIZE_PASSTHRU);
847845
}
848-
#line 849 "ext/standard/var_unserializer.c"
846+
#line 847 "ext/standard/var_unserializer.c"
849847
yy39:
850848
yych = *++YYCURSOR;
851849
if (yych == '+') goto yy40;
@@ -866,7 +864,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
866864
yych = *++YYCURSOR;
867865
if (yych != '"') goto yy18;
868866
++YYCURSOR;
869-
#line 629 "ext/standard/var_unserializer.re"
867+
#line 628 "ext/standard/var_unserializer.re"
870868
{
871869
size_t len, maxlen;
872870
char *str;
@@ -895,7 +893,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
895893
ZVAL_STRINGL(*rval, str, len, 0);
896894
return 1;
897895
}
898-
#line 899 "ext/standard/var_unserializer.c"
896+
#line 897 "ext/standard/var_unserializer.c"
899897
yy46:
900898
yych = *++YYCURSOR;
901899
if (yych == '+') goto yy47;
@@ -916,7 +914,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
916914
yych = *++YYCURSOR;
917915
if (yych != '"') goto yy18;
918916
++YYCURSOR;
919-
#line 601 "ext/standard/var_unserializer.re"
917+
#line 600 "ext/standard/var_unserializer.re"
920918
{
921919
size_t len, maxlen;
922920
char *str;
@@ -944,7 +942,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
944942
ZVAL_STRINGL(*rval, str, len, 1);
945943
return 1;
946944
}
947-
#line 948 "ext/standard/var_unserializer.c"
945+
#line 946 "ext/standard/var_unserializer.c"
948946
yy53:
949947
yych = *++YYCURSOR;
950948
if (yych <= '/') {
@@ -1032,7 +1030,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10321030
}
10331031
yy63:
10341032
++YYCURSOR;
1035-
#line 591 "ext/standard/var_unserializer.re"
1033+
#line 590 "ext/standard/var_unserializer.re"
10361034
{
10371035
#if SIZEOF_LONG == 4
10381036
use_double:
@@ -1042,7 +1040,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10421040
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
10431041
return 1;
10441042
}
1045-
#line 1046 "ext/standard/var_unserializer.c"
1043+
#line 1044 "ext/standard/var_unserializer.c"
10461044
yy65:
10471045
yych = *++YYCURSOR;
10481046
if (yych <= ',') {
@@ -1101,7 +1099,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11011099
yych = *++YYCURSOR;
11021100
if (yych != ';') goto yy18;
11031101
++YYCURSOR;
1104-
#line 576 "ext/standard/var_unserializer.re"
1102+
#line 575 "ext/standard/var_unserializer.re"
11051103
{
11061104
*p = YYCURSOR;
11071105
INIT_PZVAL(*rval);
@@ -1116,7 +1114,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11161114

11171115
return 1;
11181116
}
1119-
#line 1120 "ext/standard/var_unserializer.c"
1117+
#line 1118 "ext/standard/var_unserializer.c"
11201118
yy76:
11211119
yych = *++YYCURSOR;
11221120
if (yych == 'N') goto yy73;
@@ -1143,7 +1141,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11431141
if (yych <= '9') goto yy79;
11441142
if (yych != ';') goto yy18;
11451143
++YYCURSOR;
1146-
#line 549 "ext/standard/var_unserializer.re"
1144+
#line 548 "ext/standard/var_unserializer.re"
11471145
{
11481146
#if SIZEOF_LONG == 4
11491147
int digits = YYCURSOR - start - 3;
@@ -1170,32 +1168,32 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11701168
ZVAL_LONG(*rval, parse_iv(start + 2));
11711169
return 1;
11721170
}
1173-
#line 1174 "ext/standard/var_unserializer.c"
1171+
#line 1172 "ext/standard/var_unserializer.c"
11741172
yy83:
11751173
yych = *++YYCURSOR;
11761174
if (yych <= '/') goto yy18;
11771175
if (yych >= '2') goto yy18;
11781176
yych = *++YYCURSOR;
11791177
if (yych != ';') goto yy18;
11801178
++YYCURSOR;
1181-
#line 542 "ext/standard/var_unserializer.re"
1179+
#line 541 "ext/standard/var_unserializer.re"
11821180
{
11831181
*p = YYCURSOR;
11841182
INIT_PZVAL(*rval);
11851183
ZVAL_BOOL(*rval, parse_iv(start + 2));
11861184
return 1;
11871185
}
1188-
#line 1189 "ext/standard/var_unserializer.c"
1186+
#line 1187 "ext/standard/var_unserializer.c"
11891187
yy87:
11901188
++YYCURSOR;
1191-
#line 535 "ext/standard/var_unserializer.re"
1189+
#line 534 "ext/standard/var_unserializer.re"
11921190
{
11931191
*p = YYCURSOR;
11941192
INIT_PZVAL(*rval);
11951193
ZVAL_NULL(*rval);
11961194
return 1;
11971195
}
1198-
#line 1199 "ext/standard/var_unserializer.c"
1196+
#line 1197 "ext/standard/var_unserializer.c"
11991197
yy89:
12001198
yych = *++YYCURSOR;
12011199
if (yych <= ',') {
@@ -1218,7 +1216,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12181216
if (yych <= '9') goto yy91;
12191217
if (yych != ';') goto yy18;
12201218
++YYCURSOR;
1221-
#line 512 "ext/standard/var_unserializer.re"
1219+
#line 511 "ext/standard/var_unserializer.re"
12221220
{
12231221
long id;
12241222

@@ -1241,7 +1239,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12411239

12421240
return 1;
12431241
}
1244-
#line 1245 "ext/standard/var_unserializer.c"
1242+
#line 1243 "ext/standard/var_unserializer.c"
12451243
yy95:
12461244
yych = *++YYCURSOR;
12471245
if (yych <= ',') {
@@ -1264,7 +1262,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12641262
if (yych <= '9') goto yy97;
12651263
if (yych != ';') goto yy18;
12661264
++YYCURSOR;
1267-
#line 491 "ext/standard/var_unserializer.re"
1265+
#line 490 "ext/standard/var_unserializer.re"
12681266
{
12691267
long id;
12701268

@@ -1285,9 +1283,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12851283

12861284
return 1;
12871285
}
1288-
#line 1289 "ext/standard/var_unserializer.c"
1286+
#line 1287 "ext/standard/var_unserializer.c"
12891287
}
1290-
#line 840 "ext/standard/var_unserializer.re"
1288+
#line 839 "ext/standard/var_unserializer.re"
12911289

12921290

12931291
return 0;

ext/standard/var_unserializer.re

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
324324
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
325325
zval_dtor(key);
326326
FREE_ZVAL(key);
327-
zval_dtor(data);
328-
FREE_ZVAL(data);
327+
zval_ptr_dtor(&data);
329328
return 0;
330329
}
331330

0 commit comments

Comments
 (0)