summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-11-29 19:00:57 +0300
committerDmitry Stogov <dmitry@zend.com>2017-11-29 19:00:57 +0300
commit03da5f8e30cc65584d38d478ea566062ff99579b (patch)
tree0dac21935650d3627133064a1002886ddc3d0181
parentf98721b4e085b02144bf43c7a6ad912b3f828829 (diff)
downloadphp-git-03da5f8e30cc65584d38d478ea566062ff99579b.tar.gz
Try to intern unserualized string keys
-rw-r--r--ext/standard/var_unserializer.c128
-rw-r--r--ext/standard/var_unserializer.re64
2 files changed, 100 insertions, 92 deletions
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c
index 34140a2bb2..42be189874 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -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)
{
@@ -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;
}
@@ -438,7 +438,7 @@ numeric_key:
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;
@@ -448,35 +448,37 @@ string_key:
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) {
@@ -499,7 +501,7 @@ string_key:
}
}
- 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;
}
@@ -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
@@ -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;
@@ -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[] = {
@@ -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;
@@ -772,13 +774,13 @@ yy14:
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) {
@@ -789,13 +791,13 @@ yy18:
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;
@@ -999,7 +1001,7 @@ yy56:
goto yy18;
yy57:
++YYCURSOR;
-#line 673 "ext/standard/var_unserializer.re"
+#line 675 "ext/standard/var_unserializer.re"
{
zend_long id;
@@ -1024,7 +1026,7 @@ yy57:
return 1;
}
-#line 1028 "ext/standard/var_unserializer.c"
+#line 1030 "ext/standard/var_unserializer.c"
yy59:
yych = *++YYCURSOR;
if (yych == '"') goto yy80;
@@ -1035,22 +1037,22 @@ yy60:
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);
@@ -1070,7 +1072,7 @@ yy65:
}
yy67:
++YYCURSOR;
-#line 783 "ext/standard/var_unserializer.re"
+#line 785 "ext/standard/var_unserializer.re"
{
#if SIZEOF_ZEND_LONG == 4
use_double:
@@ -1079,7 +1081,7 @@ use_double:
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 <= ',') {
@@ -1101,7 +1103,7 @@ yy71:
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;
@@ -1127,14 +1129,14 @@ yy72:
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;
@@ -1159,14 +1161,14 @@ yy75:
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;
@@ -1318,10 +1320,10 @@ yy78:
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;
@@ -1355,10 +1357,10 @@ yy80:
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 */
@@ -1391,7 +1393,7 @@ yy82:
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;
@@ -1410,7 +1412,7 @@ yy87:
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;
@@ -1421,10 +1423,10 @@ yy88:
}
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;
@@ -1457,15 +1459,17 @@ yy90:
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;
@@ -1481,9 +1485,9 @@ yy92:
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;
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index 86d3502746..6c9c36fec0 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -393,7 +393,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)
{
@@ -403,7 +403,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;
}
@@ -442,7 +442,7 @@ numeric_key:
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;
@@ -452,35 +452,37 @@ string_key:
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) {
@@ -503,7 +505,7 @@ string_key:
}
}
- 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;
}
@@ -629,7 +631,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
@@ -650,7 +652,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;
@@ -821,6 +823,8 @@ use_double:
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);
}