Skip to content

Commit

Permalink
Try to intern unserualized string keys
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Nov 29, 2017
1 parent f98721b commit 03da5f8
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 92 deletions.
128 changes: 66 additions & 62 deletions ext/standard/var_unserializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ static inline size_t parse_uiv(const unsigned char *p)
#define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash
#define UNSERIALIZE_PASSTHRU rval, p, max, var_hash

static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key);

static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
Expand All @@ -399,7 +399,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab

ZVAL_UNDEF(&key);

if (!php_var_unserialize_internal(&key, p, max, NULL)) {
if (!php_var_unserialize_internal(&key, p, max, NULL, 1)) {
zval_ptr_dtor(&key);
return 0;
}
Expand Down Expand Up @@ -438,7 +438,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
string_key:
{
zend_property_info *existing_propinfo;
zend_string *new_key, *unmangled;
zend_string *new_key;
const char *unmangled_class = NULL;
const char *unmangled_prop;
size_t unmangled_prop_len;
Expand All @@ -448,35 +448,37 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
return 0;
}

unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);
if (Z_TYPE_P(rval) == IS_OBJECT
&& ((existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled)) != NULL)
&& (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) {
if (existing_propinfo->flags & ZEND_ACC_PROTECTED) {
new_key = zend_mangle_property_name(
"*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0);
zend_string_release(unmangled);
} else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) {
if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) {
if (Z_TYPE_P(rval) == IS_OBJECT) {
zend_string *unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);

if (((existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled)) != NULL)
&& (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) {
if (existing_propinfo->flags & ZEND_ACC_PROTECTED) {
new_key = zend_mangle_property_name(
unmangled_class, strlen(unmangled_class),
ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
0);
"*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0);
zend_string_release(unmangled);
} else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) {
if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) {
new_key = zend_mangle_property_name(
unmangled_class, strlen(unmangled_class),
ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
0);
} else {
new_key = zend_mangle_property_name(
ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name),
ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
0);
}
zend_string_release(unmangled);
} else {
new_key = zend_mangle_property_name(
ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name),
ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
0);
ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
new_key = unmangled;
}
zend_string_release(unmangled);
zend_string_release(Z_STR(key));
ZVAL_STR(&key, new_key);
} else {
ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
new_key = unmangled;
zend_string_release(unmangled);
}
zend_string_release(Z_STR(key));
ZVAL_STR(&key, new_key);
} else {
zend_string_release(unmangled);
}

if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
Expand All @@ -499,7 +501,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
}
}

if (!php_var_unserialize_internal(data, p, max, var_hash)) {
if (!php_var_unserialize_internal(data, p, max, var_hash, 0)) {
zval_ptr_dtor(&key);
return 0;
}
Expand Down Expand Up @@ -625,7 +627,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
int result;

result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU, 0);

if (!result) {
/* If the unserialization failed, mark all elements that have been added to var_hash
Expand All @@ -646,7 +648,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return result;
}

static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key)
{
const unsigned char *cursor, *limit, *marker, *start;
zval *rval_ref;
Expand All @@ -665,7 +667,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
start = cursor;


#line 669 "ext/standard/var_unserializer.c"
#line 671 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
Expand Down Expand Up @@ -723,9 +725,9 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
yy2:
++YYCURSOR;
yy3:
#line 1066 "ext/standard/var_unserializer.re"
#line 1070 "ext/standard/var_unserializer.re"
{ return 0; }
#line 729 "ext/standard/var_unserializer.c"
#line 731 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy17;
Expand Down Expand Up @@ -772,13 +774,13 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
goto yy3;
yy15:
++YYCURSOR;
#line 1060 "ext/standard/var_unserializer.re"
#line 1064 "ext/standard/var_unserializer.re"
{
/* this is the case where we have less data than planned */
php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
return 0; /* not sure if it should be 0 or 1 here? */
}
#line 782 "ext/standard/var_unserializer.c"
#line 784 "ext/standard/var_unserializer.c"
yy17:
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
Expand All @@ -789,13 +791,13 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
goto yy3;
yy19:
++YYCURSOR;
#line 723 "ext/standard/var_unserializer.re"
#line 725 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_NULL(rval);
return 1;
}
#line 799 "ext/standard/var_unserializer.c"
#line 801 "ext/standard/var_unserializer.c"
yy21:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
Expand Down Expand Up @@ -999,7 +1001,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
goto yy18;
yy57:
++YYCURSOR;
#line 673 "ext/standard/var_unserializer.re"
#line 675 "ext/standard/var_unserializer.re"
{
zend_long id;

Expand All @@ -1024,7 +1026,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)

return 1;
}
#line 1028 "ext/standard/var_unserializer.c"
#line 1030 "ext/standard/var_unserializer.c"
yy59:
yych = *++YYCURSOR;
if (yych == '"') goto yy80;
Expand All @@ -1035,22 +1037,22 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
goto yy18;
yy61:
++YYCURSOR;
#line 729 "ext/standard/var_unserializer.re"
#line 731 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_FALSE(rval);
return 1;
}
#line 1045 "ext/standard/var_unserializer.c"
#line 1047 "ext/standard/var_unserializer.c"
yy63:
++YYCURSOR;
#line 735 "ext/standard/var_unserializer.re"
#line 737 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_TRUE(rval);
return 1;
}
#line 1054 "ext/standard/var_unserializer.c"
#line 1056 "ext/standard/var_unserializer.c"
yy65:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
Expand All @@ -1070,7 +1072,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
}
yy67:
++YYCURSOR;
#line 783 "ext/standard/var_unserializer.re"
#line 785 "ext/standard/var_unserializer.re"
{
#if SIZEOF_ZEND_LONG == 4
use_double:
Expand All @@ -1079,7 +1081,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
return 1;
}
#line 1083 "ext/standard/var_unserializer.c"
#line 1085 "ext/standard/var_unserializer.c"
yy69:
yych = *++YYCURSOR;
if (yych <= ',') {
Expand All @@ -1101,7 +1103,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
goto yy18;
yy72:
++YYCURSOR;
#line 741 "ext/standard/var_unserializer.re"
#line 743 "ext/standard/var_unserializer.re"
{
#if SIZEOF_ZEND_LONG == 4
int digits = YYCURSOR - start - 3;
Expand All @@ -1127,14 +1129,14 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
ZVAL_LONG(rval, parse_iv(start + 2));
return 1;
}
#line 1131 "ext/standard/var_unserializer.c"
#line 1133 "ext/standard/var_unserializer.c"
yy74:
yych = *++YYCURSOR;
if (yych == '"') goto yy88;
goto yy18;
yy75:
++YYCURSOR;
#line 698 "ext/standard/var_unserializer.re"
#line 700 "ext/standard/var_unserializer.re"
{
zend_long id;

Expand All @@ -1159,14 +1161,14 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)

return 1;
}
#line 1163 "ext/standard/var_unserializer.c"
#line 1165 "ext/standard/var_unserializer.c"
yy77:
yych = *++YYCURSOR;
if (yych == '"') goto yy90;
goto yy18;
yy78:
++YYCURSOR;
#line 908 "ext/standard/var_unserializer.re"
#line 912 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
zend_long elements;
Expand Down Expand Up @@ -1318,10 +1320,10 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)

return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
#line 1322 "ext/standard/var_unserializer.c"
#line 1324 "ext/standard/var_unserializer.c"
yy80:
++YYCURSOR;
#line 830 "ext/standard/var_unserializer.re"
#line 834 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
zend_string *str;
Expand Down Expand Up @@ -1355,10 +1357,10 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
ZVAL_STR(rval, str);
return 1;
}
#line 1359 "ext/standard/var_unserializer.c"
#line 1361 "ext/standard/var_unserializer.c"
yy82:
++YYCURSOR;
#line 864 "ext/standard/var_unserializer.re"
#line 868 "ext/standard/var_unserializer.re"
{
zend_long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
Expand Down Expand Up @@ -1391,7 +1393,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)

return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
#line 1395 "ext/standard/var_unserializer.c"
#line 1397 "ext/standard/var_unserializer.c"
yy84:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
Expand All @@ -1410,7 +1412,7 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
goto yy18;
yy88:
++YYCURSOR;
#line 897 "ext/standard/var_unserializer.re"
#line 901 "ext/standard/var_unserializer.re"
{
zend_long elements;
if (!var_hash) return 0;
Expand All @@ -1421,10 +1423,10 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
}
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
#line 1425 "ext/standard/var_unserializer.c"
#line 1427 "ext/standard/var_unserializer.c"
yy90:
++YYCURSOR;
#line 792 "ext/standard/var_unserializer.re"
#line 794 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
Expand Down Expand Up @@ -1457,15 +1459,17 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
ZVAL_EMPTY_STRING(rval);
} else if (len == 1) {
ZVAL_INTERNED_STR(rval, ZSTR_CHAR((zend_uchar)*str));
} else if (as_key) {
ZVAL_STR(rval, zend_string_init_interned(str, len, 0));
} else {
ZVAL_STRINGL(rval, str, len);
}
return 1;
}
#line 1466 "ext/standard/var_unserializer.c"
#line 1470 "ext/standard/var_unserializer.c"
yy92:
++YYCURSOR;
#line 767 "ext/standard/var_unserializer.re"
#line 769 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;

Expand All @@ -1481,9 +1485,9 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)

return 1;
}
#line 1485 "ext/standard/var_unserializer.c"
#line 1489 "ext/standard/var_unserializer.c"
}
#line 1068 "ext/standard/var_unserializer.re"
#line 1072 "ext/standard/var_unserializer.re"


return 0;
Expand Down
Loading

0 comments on commit 03da5f8

Please sign in to comment.