diff options
| author | Anatol Belski <ab@php.net> | 2014-12-10 11:47:34 +0100 | 
|---|---|---|
| committer | Anatol Belski <ab@php.net> | 2014-12-10 11:47:34 +0100 | 
| commit | 4a82cdce6633ec8d7bb5ffdbe726e14e9d70e512 (patch) | |
| tree | 2b711f2b26c28082fa533213c66fa45a74d157d8 | |
| parent | e6f9059a8662c2e078371c7982d4711d8e51f83c (diff) | |
| parent | 20d93534d5de742fb156e922a5d01255a1f1256e (diff) | |
| download | php-git-4a82cdce6633ec8d7bb5ffdbe726e14e9d70e512.tar.gz | |
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5:
  Fixed bug #68545 NULL pointer dereference in unserialize.c
Conflicts:
	ext/standard/var_unserializer.c
| -rw-r--r-- | ext/standard/var_unserializer.c | 70 | ||||
| -rw-r--r-- | ext/standard/var_unserializer.re | 8 | ||||
| -rw-r--r-- | standard/tests/serialize/bug68545.phpt | 11 | 
3 files changed, 56 insertions, 33 deletions
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-- +<?php  +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";'));  +?> +===DONE=== +--EXPECTF-- +Notice: unserialize(): Error at offset %d of %d bytes in %sbug68545.php on line %d +bool(false) +===DONE===  | 
