From 239bfe29a1e50beeaf0f1c3db8b2d1385d53ad47 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 10 Dec 2014 11:43:33 +0100 Subject: Fixed bug #68545 NULL pointer dereference in unserialize.c Conflicts: ext/standard/var_unserializer.c --- ext/standard/var_unserializer.c | 70 ++++++++++++++++++---------------- ext/standard/var_unserializer.re | 8 +++- standard/tests/serialize/bug68545.phpt | 11 ++++++ 3 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 standard/tests/serialize/bug68545.phpt diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 8b51a20ace..88ba7e5fb8 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -60,7 +60,13 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval) PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) { - var_entries *var_hash = (*var_hashx)->last_dtor; + var_entries *var_hash; + + if (!var_hashx || !*var_hashx) { + return; + } + + var_hash = (*var_hashx)->last_dtor; #if VAR_ENTRIES_DBG fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval)); #endif @@ -226,7 +232,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen #define YYMARKER marker -#line 234 "ext/standard/var_unserializer.re" +#line 240 "ext/standard/var_unserializer.re" @@ -469,7 +475,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 473 "ext/standard/var_unserializer.c" +#line 479 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -529,9 +535,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 824 "ext/standard/var_unserializer.re" +#line 830 "ext/standard/var_unserializer.re" { return 0; } -#line 535 "ext/standard/var_unserializer.c" +#line 541 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -574,13 +580,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 818 "ext/standard/var_unserializer.re" +#line 824 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 584 "ext/standard/var_unserializer.c" +#line 590 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -610,7 +616,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 672 "ext/standard/var_unserializer.re" +#line 678 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -756,7 +762,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 760 "ext/standard/var_unserializer.c" +#line 766 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -781,7 +787,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 664 "ext/standard/var_unserializer.re" +#line 670 "ext/standard/var_unserializer.re" { INIT_PZVAL(*rval); @@ -789,7 +795,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 793 "ext/standard/var_unserializer.c" +#line 799 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -810,7 +816,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 644 "ext/standard/var_unserializer.re" +#line 650 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -830,7 +836,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 834 "ext/standard/var_unserializer.c" +#line 840 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -851,7 +857,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 615 "ext/standard/var_unserializer.re" +#line 621 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -880,7 +886,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 884 "ext/standard/var_unserializer.c" +#line 890 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -901,7 +907,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 587 "ext/standard/var_unserializer.re" +#line 593 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -929,7 +935,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 933 "ext/standard/var_unserializer.c" +#line 939 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1017,7 +1023,7 @@ yy61: } yy63: ++YYCURSOR; -#line 577 "ext/standard/var_unserializer.re" +#line 583 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1027,7 +1033,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1031 "ext/standard/var_unserializer.c" +#line 1037 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1086,7 +1092,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 562 "ext/standard/var_unserializer.re" +#line 568 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1101,7 +1107,7 @@ yy73: return 1; } -#line 1105 "ext/standard/var_unserializer.c" +#line 1111 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1128,7 +1134,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 535 "ext/standard/var_unserializer.re" +#line 541 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1155,7 +1161,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1159 "ext/standard/var_unserializer.c" +#line 1165 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1163,24 +1169,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 528 "ext/standard/var_unserializer.re" +#line 534 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1174 "ext/standard/var_unserializer.c" +#line 1180 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 521 "ext/standard/var_unserializer.re" +#line 527 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1184 "ext/standard/var_unserializer.c" +#line 1190 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1203,7 +1209,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 498 "ext/standard/var_unserializer.re" +#line 504 "ext/standard/var_unserializer.re" { long id; @@ -1226,7 +1232,7 @@ yy91: return 1; } -#line 1230 "ext/standard/var_unserializer.c" +#line 1236 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1249,7 +1255,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 477 "ext/standard/var_unserializer.re" +#line 483 "ext/standard/var_unserializer.re" { long id; @@ -1270,9 +1276,9 @@ yy97: return 1; } -#line 1274 "ext/standard/var_unserializer.c" +#line 1280 "ext/standard/var_unserializer.c" } -#line 826 "ext/standard/var_unserializer.re" +#line 832 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index ef553ffb53..5d9d83b677 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -58,7 +58,13 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval) PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval) { - var_entries *var_hash = (*var_hashx)->last_dtor; + var_entries *var_hash; + + if (!var_hashx || !*var_hashx) { + return; + } + + var_hash = (*var_hashx)->last_dtor; #if VAR_ENTRIES_DBG fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval)); #endif diff --git a/standard/tests/serialize/bug68545.phpt b/standard/tests/serialize/bug68545.phpt new file mode 100644 index 0000000000..e7250b37bc --- /dev/null +++ b/standard/tests/serialize/bug68545.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #68545 NULL pointer dereference in unserialize.c:var_push_dtor +--FILE-- + +===DONE=== +--EXPECTF-- +Notice: unserialize(): Error at offset %d of %d bytes in %sbug68545.php on line %d +bool(false) +===DONE=== -- cgit v1.2.1