Skip to content

Commit 13f1c27

Browse files
weltlingsmalyshev
authored andcommitted
Fixed bug #68545 NULL pointer dereference in unserialize.c
1 parent dd791cd commit 13f1c27

File tree

3 files changed

+56
-33
lines changed

3 files changed

+56
-33
lines changed

ext/standard/var_unserializer.c

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
6161

6262
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
6363
{
64-
var_entries *var_hash = (*var_hashx)->last_dtor;
64+
var_entries *var_hash;
65+
66+
if (!var_hashx || !*var_hashx) {
67+
return;
68+
}
69+
70+
var_hash = (*var_hashx)->last_dtor;
6571
#if VAR_ENTRIES_DBG
6672
fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
6773
#endif
@@ -227,7 +233,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
227233
#define YYMARKER marker
228234

229235

230-
#line 235 "ext/standard/var_unserializer.re"
236+
#line 241 "ext/standard/var_unserializer.re"
231237

232238

233239

@@ -474,7 +480,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
474480

475481

476482

477-
#line 478 "ext/standard/var_unserializer.c"
483+
#line 484 "ext/standard/var_unserializer.c"
478484
{
479485
YYCTYPE yych;
480486
static const unsigned char yybm[] = {
@@ -534,9 +540,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
534540
yych = *(YYMARKER = ++YYCURSOR);
535541
if (yych == ':') goto yy95;
536542
yy3:
537-
#line 829 "ext/standard/var_unserializer.re"
543+
#line 835 "ext/standard/var_unserializer.re"
538544
{ return 0; }
539-
#line 540 "ext/standard/var_unserializer.c"
545+
#line 546 "ext/standard/var_unserializer.c"
540546
yy4:
541547
yych = *(YYMARKER = ++YYCURSOR);
542548
if (yych == ':') goto yy89;
@@ -579,13 +585,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
579585
goto yy3;
580586
yy14:
581587
++YYCURSOR;
582-
#line 823 "ext/standard/var_unserializer.re"
588+
#line 829 "ext/standard/var_unserializer.re"
583589
{
584590
/* this is the case where we have less data than planned */
585591
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
586592
return 0; /* not sure if it should be 0 or 1 here? */
587593
}
588-
#line 589 "ext/standard/var_unserializer.c"
594+
#line 595 "ext/standard/var_unserializer.c"
589595
yy16:
590596
yych = *++YYCURSOR;
591597
goto yy3;
@@ -615,7 +621,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
615621
yych = *++YYCURSOR;
616622
if (yych != '"') goto yy18;
617623
++YYCURSOR;
618-
#line 677 "ext/standard/var_unserializer.re"
624+
#line 683 "ext/standard/var_unserializer.re"
619625
{
620626
size_t len, len2, len3, maxlen;
621627
long elements;
@@ -761,7 +767,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
761767

762768
return object_common2(UNSERIALIZE_PASSTHRU, elements);
763769
}
764-
#line 765 "ext/standard/var_unserializer.c"
770+
#line 771 "ext/standard/var_unserializer.c"
765771
yy25:
766772
yych = *++YYCURSOR;
767773
if (yych <= ',') {
@@ -786,15 +792,15 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
786792
yych = *++YYCURSOR;
787793
if (yych != '"') goto yy18;
788794
++YYCURSOR;
789-
#line 669 "ext/standard/var_unserializer.re"
795+
#line 675 "ext/standard/var_unserializer.re"
790796
{
791797

792798
INIT_PZVAL(*rval);
793799

794800
return object_common2(UNSERIALIZE_PASSTHRU,
795801
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
796802
}
797-
#line 798 "ext/standard/var_unserializer.c"
803+
#line 804 "ext/standard/var_unserializer.c"
798804
yy32:
799805
yych = *++YYCURSOR;
800806
if (yych == '+') goto yy33;
@@ -815,7 +821,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
815821
yych = *++YYCURSOR;
816822
if (yych != '{') goto yy18;
817823
++YYCURSOR;
818-
#line 649 "ext/standard/var_unserializer.re"
824+
#line 655 "ext/standard/var_unserializer.re"
819825
{
820826
long elements = parse_iv(start + 2);
821827
/* use iv() not uiv() in order to check data range */
@@ -835,7 +841,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
835841

836842
return finish_nested_data(UNSERIALIZE_PASSTHRU);
837843
}
838-
#line 839 "ext/standard/var_unserializer.c"
844+
#line 845 "ext/standard/var_unserializer.c"
839845
yy39:
840846
yych = *++YYCURSOR;
841847
if (yych == '+') goto yy40;
@@ -856,7 +862,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
856862
yych = *++YYCURSOR;
857863
if (yych != '"') goto yy18;
858864
++YYCURSOR;
859-
#line 620 "ext/standard/var_unserializer.re"
865+
#line 626 "ext/standard/var_unserializer.re"
860866
{
861867
size_t len, maxlen;
862868
char *str;
@@ -885,7 +891,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
885891
ZVAL_STRINGL(*rval, str, len, 0);
886892
return 1;
887893
}
888-
#line 889 "ext/standard/var_unserializer.c"
894+
#line 895 "ext/standard/var_unserializer.c"
889895
yy46:
890896
yych = *++YYCURSOR;
891897
if (yych == '+') goto yy47;
@@ -906,7 +912,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
906912
yych = *++YYCURSOR;
907913
if (yych != '"') goto yy18;
908914
++YYCURSOR;
909-
#line 592 "ext/standard/var_unserializer.re"
915+
#line 598 "ext/standard/var_unserializer.re"
910916
{
911917
size_t len, maxlen;
912918
char *str;
@@ -934,7 +940,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
934940
ZVAL_STRINGL(*rval, str, len, 1);
935941
return 1;
936942
}
937-
#line 938 "ext/standard/var_unserializer.c"
943+
#line 944 "ext/standard/var_unserializer.c"
938944
yy53:
939945
yych = *++YYCURSOR;
940946
if (yych <= '/') {
@@ -1022,7 +1028,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10221028
}
10231029
yy63:
10241030
++YYCURSOR;
1025-
#line 582 "ext/standard/var_unserializer.re"
1031+
#line 588 "ext/standard/var_unserializer.re"
10261032
{
10271033
#if SIZEOF_LONG == 4
10281034
use_double:
@@ -1032,7 +1038,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10321038
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
10331039
return 1;
10341040
}
1035-
#line 1036 "ext/standard/var_unserializer.c"
1041+
#line 1042 "ext/standard/var_unserializer.c"
10361042
yy65:
10371043
yych = *++YYCURSOR;
10381044
if (yych <= ',') {
@@ -1091,7 +1097,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
10911097
yych = *++YYCURSOR;
10921098
if (yych != ';') goto yy18;
10931099
++YYCURSOR;
1094-
#line 567 "ext/standard/var_unserializer.re"
1100+
#line 573 "ext/standard/var_unserializer.re"
10951101
{
10961102
*p = YYCURSOR;
10971103
INIT_PZVAL(*rval);
@@ -1106,7 +1112,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11061112

11071113
return 1;
11081114
}
1109-
#line 1110 "ext/standard/var_unserializer.c"
1115+
#line 1116 "ext/standard/var_unserializer.c"
11101116
yy76:
11111117
yych = *++YYCURSOR;
11121118
if (yych == 'N') goto yy73;
@@ -1133,7 +1139,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11331139
if (yych <= '9') goto yy79;
11341140
if (yych != ';') goto yy18;
11351141
++YYCURSOR;
1136-
#line 540 "ext/standard/var_unserializer.re"
1142+
#line 546 "ext/standard/var_unserializer.re"
11371143
{
11381144
#if SIZEOF_LONG == 4
11391145
int digits = YYCURSOR - start - 3;
@@ -1160,32 +1166,32 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
11601166
ZVAL_LONG(*rval, parse_iv(start + 2));
11611167
return 1;
11621168
}
1163-
#line 1164 "ext/standard/var_unserializer.c"
1169+
#line 1170 "ext/standard/var_unserializer.c"
11641170
yy83:
11651171
yych = *++YYCURSOR;
11661172
if (yych <= '/') goto yy18;
11671173
if (yych >= '2') goto yy18;
11681174
yych = *++YYCURSOR;
11691175
if (yych != ';') goto yy18;
11701176
++YYCURSOR;
1171-
#line 533 "ext/standard/var_unserializer.re"
1177+
#line 539 "ext/standard/var_unserializer.re"
11721178
{
11731179
*p = YYCURSOR;
11741180
INIT_PZVAL(*rval);
11751181
ZVAL_BOOL(*rval, parse_iv(start + 2));
11761182
return 1;
11771183
}
1178-
#line 1179 "ext/standard/var_unserializer.c"
1184+
#line 1185 "ext/standard/var_unserializer.c"
11791185
yy87:
11801186
++YYCURSOR;
1181-
#line 526 "ext/standard/var_unserializer.re"
1187+
#line 532 "ext/standard/var_unserializer.re"
11821188
{
11831189
*p = YYCURSOR;
11841190
INIT_PZVAL(*rval);
11851191
ZVAL_NULL(*rval);
11861192
return 1;
11871193
}
1188-
#line 1189 "ext/standard/var_unserializer.c"
1194+
#line 1195 "ext/standard/var_unserializer.c"
11891195
yy89:
11901196
yych = *++YYCURSOR;
11911197
if (yych <= ',') {
@@ -1208,7 +1214,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12081214
if (yych <= '9') goto yy91;
12091215
if (yych != ';') goto yy18;
12101216
++YYCURSOR;
1211-
#line 503 "ext/standard/var_unserializer.re"
1217+
#line 509 "ext/standard/var_unserializer.re"
12121218
{
12131219
long id;
12141220

@@ -1231,7 +1237,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12311237

12321238
return 1;
12331239
}
1234-
#line 1235 "ext/standard/var_unserializer.c"
1240+
#line 1241 "ext/standard/var_unserializer.c"
12351241
yy95:
12361242
yych = *++YYCURSOR;
12371243
if (yych <= ',') {
@@ -1254,7 +1260,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12541260
if (yych <= '9') goto yy97;
12551261
if (yych != ';') goto yy18;
12561262
++YYCURSOR;
1257-
#line 482 "ext/standard/var_unserializer.re"
1263+
#line 488 "ext/standard/var_unserializer.re"
12581264
{
12591265
long id;
12601266

@@ -1275,9 +1281,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
12751281

12761282
return 1;
12771283
}
1278-
#line 1279 "ext/standard/var_unserializer.c"
1284+
#line 1285 "ext/standard/var_unserializer.c"
12791285
}
1280-
#line 831 "ext/standard/var_unserializer.re"
1286+
#line 837 "ext/standard/var_unserializer.re"
12811287

12821288

12831289
return 0;

ext/standard/var_unserializer.re

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,13 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
5959

6060
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
6161
{
62-
var_entries *var_hash = (*var_hashx)->last_dtor;
62+
var_entries *var_hash;
63+
64+
if (!var_hashx || !*var_hashx) {
65+
return;
66+
}
67+
68+
var_hash = (*var_hashx)->last_dtor;
6369
#if VAR_ENTRIES_DBG
6470
fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
6571
#endif
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Bug #68545 NULL pointer dereference in unserialize.c:var_push_dtor
3+
--FILE--
4+
<?php
5+
var_dump(unserialize('a:6:{a:6:{s:3:"322";s:3:"bar";s:3:"bar";s:3:"foo";a:6:{a:6:{s:3:"322";s:3:"bar";s:3:"bar";s:3:"foo";s:3:"bar";a:6:{a:6:{s:3:"322";s:3:"bar";s:3:"bar";s:3:"foo";a:6:{a:6:{s:3:"322";s:3:"bar";s:3:"b22";s:3:"bar";s:3:"bar";s:3:"foo";s:3:"bar";a:6:{a:6:{s:3:"322";s:3:"bar";s:3:"bar";s:3:"foo";s:3:"bar";s:3:"bar";'));
6+
?>
7+
===DONE===
8+
--EXPECTF--
9+
Notice: unserialize(): Error at offset %d of %d bytes in %sbug68545.php on line %d
10+
bool(false)
11+
===DONE===

0 commit comments

Comments
 (0)