Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: php/php-src
base: master
...
head fork: bukka/php-src
compare: serialize_internal_api
Checking mergeability… Don't worry, you can still create the pull request.
  • 17 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on Aug 11, 2013
@bukka bukka Add new PHPAPI functions for serializing object and its properties e6a3ff0
Commits on Sep 01, 2013
@bukka bukka Call unserialize for non-custom object 172d862
Commits on Sep 07, 2013
@bukka bukka Add new PHPAPI functions for unserializing object properties 1402ce2
Commits on Sep 08, 2013
@bukka bukka Use int when serialize bool ef668e8
Commits on Sep 11, 2013
@bukka bukka Change vah_hash type for zval and ht serialization 0d81fba
Commits on Sep 14, 2013
@bukka bukka Use unserialize callback only for internal classes 1b793d6
Commits on Sep 15, 2013
@bukka bukka Add new internal serialize API 472e085
Commits on Oct 05, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api
Conflicts:
	ext/standard/var_unserializer.c
2e34d01
@bukka bukka Merge branch 'internal_serialize_api' into serialize_internal_api 9494a48
@bukka bukka Add php_var_unserialize_has_properties to find out the end of unseria…
…lized string
825f7f3
Commits on Oct 12, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api a5e630c
Commits on Oct 13, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api 0aa46a4
Commits on Oct 18, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api 0f9d71f
Commits on Oct 19, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api d2e34d3
Commits on Oct 30, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api 35e04a0
@bukka bukka Set uninitialized rval as NULL before passed to unserialize 13f54c1
Commits on Dec 15, 2013
@bukka bukka Merge branch 'master' into serialize_internal_api 1c9c604
View
50 ext/standard/php_var.h
@@ -38,8 +38,47 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC);
+
+#define PHP_SERIALIZE_FAILURE (FAILURE)
+#define PHP_SERIALIZE_CUSTOM (SUCCESS)
+#define PHP_SERIALIZE_OBJECT (SUCCESS + 1)
+
typedef HashTable* php_serialize_data_t;
+/* serialize variable */
+PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC);
+
+/* add object serialization string prefix */
+PHPAPI void php_var_serialize_object_start(smart_str *buf, zval *object, zend_uint nprops TSRMLS_DC);
+
+/* append string that ends the object definition */
+PHPAPI void php_var_serialize_object_end(smart_str *buf);
+
+/* append null property */
+PHPAPI void php_var_serialize_property_null(smart_str *buf, const char *key);
+
+/* append boolean property */
+PHPAPI void php_var_serialize_property_bool(smart_str *buf, const char *key, int value);
+
+/* append long property */
+PHPAPI void php_var_serialize_property_long(smart_str *buf, const char *key, long value);
+
+/* append double property */
+PHPAPI void php_var_serialize_property_double(smart_str *buf, const char *key, double value TSRMLS_DC);
+
+/* append string property */
+PHPAPI void php_var_serialize_property_string(smart_str *buf, const char *key, const char *value);
+
+/* append string property */
+PHPAPI void php_var_serialize_property_stringl(smart_str *buf, const char *key, const char *value, int value_len);
+
+/* append string property zval */
+PHPAPI void php_var_serialize_property_zval(smart_str *buf, const char *key, zval *value, zend_serialize_data *data TSRMLS_DC);
+
+/* append properties taken from HashTable */
+PHPAPI void php_var_serialize_properties(smart_str *buf, HashTable *properties, zend_serialize_data *data TSRMLS_DC);
+
+
struct php_unserialize_data {
void *first;
void *last;
@@ -49,9 +88,18 @@ struct php_unserialize_data {
typedef struct php_unserialize_data* php_unserialize_data_t;
-PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC);
+/* unserialize variable */
PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC);
+/* whether unserialization finished */
+PHPAPI int php_var_unserialize_has_properties(const unsigned char *buf, zend_uint buf_len);
+
+/* unserialize all properties of the serialized object and save them to ht */
+PHPAPI int php_var_unserialize_properties(HashTable *ht, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC);
+
+/* unserialize one property (key and value) of the serialized object */
+PHPAPI int php_var_unserialize_property(zval *key, zval *value, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC);
+
#define PHP_VAR_SERIALIZE_INIT(var_hash_ptr) \
do { \
/* fprintf(stderr, "SERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
View
219 ext/standard/var.c
@@ -582,6 +582,20 @@ static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old
}
/* }}} */
+static inline void php_var_serialize_null(smart_str *buf) /* {{{ */
+{
+ smart_str_appendl(buf, "N;", 2);
+}
+/* }}} */
+
+static inline void php_var_serialize_bool(smart_str *buf, long val) /* {{{ */
+{
+ smart_str_appendl(buf, "b:", 2);
+ smart_str_append_long(buf, val);
+ smart_str_appendc(buf, ';');
+}
+/* }}} */
+
static inline void php_var_serialize_long(smart_str *buf, long val) /* {{{ */
{
smart_str_appendl(buf, "i:", 2);
@@ -590,7 +604,21 @@ static inline void php_var_serialize_long(smart_str *buf, long val) /* {{{ */
}
/* }}} */
-static inline void php_var_serialize_string(smart_str *buf, char *str, int len) /* {{{ */
+static inline void php_var_serialize_double(smart_str *buf, double val TSRMLS_DC) /* {{{ */
+{
+ char *s;
+
+ smart_str_appendl(buf, "d:", 2);
+ s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
+ php_gcvt(val, PG(serialize_precision), '.', 'E', s);
+ smart_str_appends(buf, s);
+ smart_str_appendc(buf, ';');
+ efree(s);
+ return;
+}
+/* }}} */
+
+static inline void php_var_serialize_string(smart_str *buf, const char *str, int len) /* {{{ */
{
smart_str_appendl(buf, "s:", 2);
smart_str_append_long(buf, len);
@@ -600,6 +628,55 @@ static inline void php_var_serialize_string(smart_str *buf, char *str, int len)
}
/* }}} */
+static inline void php_var_serialize_hash_table(smart_str *buf, HashTable *myht, zval **pstruc, zend_bool incomplete_class, HashTable *var_hash TSRMLS_DC) /* {{{ */
+{
+ int i;
+ char *key;
+ zval **data;
+ ulong index;
+ uint key_len;
+ HashPosition pos;
+
+ zend_hash_internal_pointer_reset_ex(myht, &pos);
+ for (;; zend_hash_move_forward_ex(myht, &pos)) {
+ i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
+ if (i == HASH_KEY_NON_EXISTENT) {
+ break;
+ }
+ if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
+ continue;
+ }
+
+ switch (i) {
+ case HASH_KEY_IS_LONG:
+ php_var_serialize_long(buf, index);
+ break;
+ case HASH_KEY_IS_STRING:
+ php_var_serialize_string(buf, key, key_len - 1);
+ break;
+ }
+
+ /* we should still add element even if it's not OK,
+ * since we already wrote the length of the array before */
+ if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) != SUCCESS
+ || !data
+ || data == pstruc
+ || (Z_TYPE_PP(data) == IS_ARRAY && Z_ARRVAL_PP(data)->nApplyCount > 1)
+ ) {
+ smart_str_appendl(buf, "N;", 2);
+ } else {
+ if (Z_TYPE_PP(data) == IS_ARRAY) {
+ Z_ARRVAL_PP(data)->nApplyCount++;
+ }
+ php_var_serialize_intern(buf, *data, var_hash TSRMLS_CC);
+ if (Z_TYPE_PP(data) == IS_ARRAY) {
+ Z_ARRVAL_PP(data)->nApplyCount--;
+ }
+ }
+ }
+}
+/* }}} */
+
static inline zend_bool php_var_serialize_class_name(smart_str *buf, zval *struc TSRMLS_DC) /* {{{ */
{
PHP_CLASS_ATTRIBUTES;
@@ -732,30 +809,20 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
switch (Z_TYPE_P(struc)) {
case IS_BOOL:
- smart_str_appendl(buf, "b:", 2);
- smart_str_append_long(buf, Z_LVAL_P(struc));
- smart_str_appendc(buf, ';');
+ php_var_serialize_bool(buf, Z_LVAL_P(struc));
return;
case IS_NULL:
- smart_str_appendl(buf, "N;", 2);
+ php_var_serialize_null(buf);
return;
case IS_LONG:
php_var_serialize_long(buf, Z_LVAL_P(struc));
return;
- case IS_DOUBLE: {
- char *s;
-
- smart_str_appendl(buf, "d:", 2);
- s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
- php_gcvt(Z_DVAL_P(struc), PG(serialize_precision), '.', 'E', s);
- smart_str_appends(buf, s);
- smart_str_appendc(buf, ';');
- efree(s);
- return;
- }
+ case IS_DOUBLE:
+ php_var_serialize_double(buf, Z_DVAL_P(struc) TSRMLS_CC);
+ return;
case IS_STRING:
php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc));
@@ -764,7 +831,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
case IS_OBJECT: {
zval *retval_ptr = NULL;
zval fname;
- int res;
+ int res, serialize_rc;
zend_class_entry *ce = NULL;
if (Z_OBJ_HT_P(struc)->get_class_entry) {
@@ -776,7 +843,8 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
unsigned char *serialized_data = NULL;
zend_uint serialized_length;
- if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS) {
+ serialize_rc = ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC);
+ if (serialize_rc == PHP_SERIALIZE_CUSTOM) {
smart_str_appendl(buf, "C:", 2);
smart_str_append_long(buf, (int)Z_OBJCE_P(struc)->name_length);
smart_str_appendl(buf, ":\"", 2);
@@ -787,6 +855,8 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
smart_str_appendl(buf, ":{", 2);
smart_str_appendl(buf, serialized_data, serialized_length);
smart_str_appendc(buf, '}');
+ } else if (serialize_rc == PHP_SERIALIZE_OBJECT) {
+ smart_str_appendl(buf, serialized_data, serialized_length);
} else {
smart_str_appendl(buf, "N;", 2);
}
@@ -849,49 +919,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
smart_str_append_long(buf, i);
smart_str_appendl(buf, ":{", 2);
if (i > 0) {
- char *key;
- zval **data;
- ulong index;
- uint key_len;
- HashPosition pos;
-
- zend_hash_internal_pointer_reset_ex(myht, &pos);
- for (;; zend_hash_move_forward_ex(myht, &pos)) {
- i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
- if (i == HASH_KEY_NON_EXISTENT) {
- break;
- }
- if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) {
- continue;
- }
-
- switch (i) {
- case HASH_KEY_IS_LONG:
- php_var_serialize_long(buf, index);
- break;
- case HASH_KEY_IS_STRING:
- php_var_serialize_string(buf, key, key_len - 1);
- break;
- }
-
- /* we should still add element even if it's not OK,
- * since we already wrote the length of the array before */
- if (zend_hash_get_current_data_ex(myht, (void **) &data, &pos) != SUCCESS
- || !data
- || data == &struc
- || (Z_TYPE_PP(data) == IS_ARRAY && Z_ARRVAL_PP(data)->nApplyCount > 1)
- ) {
- smart_str_appendl(buf, "N;", 2);
- } else {
- if (Z_TYPE_PP(data) == IS_ARRAY) {
- Z_ARRVAL_PP(data)->nApplyCount++;
- }
- php_var_serialize_intern(buf, *data, var_hash TSRMLS_CC);
- if (Z_TYPE_PP(data) == IS_ARRAY) {
- Z_ARRVAL_PP(data)->nApplyCount--;
- }
- }
- }
+ php_var_serialize_hash_table(buf, myht, &struc, incomplete_class, var_hash TSRMLS_CC);
}
smart_str_appendc(buf, '}');
return;
@@ -910,6 +938,75 @@ PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t
}
/* }}} */
+PHPAPI void php_var_serialize_object_start(smart_str *buf, zval *object, zend_uint nprops TSRMLS_DC) /* {{{ */
+{
+ php_var_serialize_class_name(buf, object TSRMLS_CC);
+ smart_str_append_long(buf, nprops);
+ smart_str_appendl(buf, ":{", 2);
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_object_end(smart_str *buf) /* {{{ */
+{
+ smart_str_appendc(buf, '}');
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_null(smart_str *buf, const char *key) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_bool(smart_str *buf, const char *key, int value) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+ php_var_serialize_bool(buf, (long) value);
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_long(smart_str *buf, const char *key, long value) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+ php_var_serialize_long(buf, value);
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_double(smart_str *buf, const char *key, double value TSRMLS_DC) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+ php_var_serialize_double(buf, value TSRMLS_CC);
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_string(smart_str *buf, const char *key, const char *value) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+ php_var_serialize_string(buf, value, strlen(value));
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_stringl(smart_str *buf, const char *key, const char *value, int value_len) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+ php_var_serialize_string(buf, value, value_len);
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_property_zval(smart_str *buf, const char *key, zval *value, zend_serialize_data *data TSRMLS_DC) /* {{{ */
+{
+ php_var_serialize_string(buf, key, strlen(key));
+ php_var_serialize_intern(buf, value, (HashTable *) data TSRMLS_CC);
+}
+/* }}} */
+
+PHPAPI void php_var_serialize_properties(smart_str *buf, HashTable *properties, zend_serialize_data *data TSRMLS_DC) /* {{{ */
+{
+ php_var_serialize_hash_table(buf, properties, NULL, 0, (HashTable *) data TSRMLS_CC);
+}
+/* }}} */
+
+
/* {{{ proto string serialize(mixed variable)
Returns a string representation of variable (which can later be unserialized) */
PHP_FUNCTION(serialize)
View
157 ext/standard/var_unserializer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 */
+/* Generated by re2c 0.13.6 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
@@ -23,6 +23,7 @@
#include "php.h"
#include "ext/standard/php_var.h"
#include "php_incomplete_class.h"
+#include "zend_interfaces.h"
/* {{{ reference-handling for unserializer: var_* */
#define VAR_ENTRIES_MAX 1024
@@ -226,7 +227,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 235 "ext/standard/var_unserializer.re"
@@ -376,10 +377,11 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
return 0;
}
+ ZVAL_NULL(*rval);
if (ce->unserialize == NULL) {
zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
object_init_ex(*rval, ce);
- } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
+ } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) < 0) {
return 0;
}
@@ -436,6 +438,78 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
# pragma optimize("", on)
#endif
+PHPAPI int php_var_unserialize_has_properties(const unsigned char *buf, zend_uint buf_len)
+{
+ return buf_len && *buf != '}';
+}
+
+PHPAPI int php_var_unserialize_properties(HashTable *ht, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC)
+{
+ const unsigned char *max;
+
+ max = *buf + *buf_len;
+
+ while (php_var_unserialize_has_properties(*buf, *buf_len)) {
+ zval *key, *value;
+
+ ALLOC_INIT_ZVAL(key);
+
+ if (!php_var_unserialize(&key, buf, max, NULL TSRMLS_CC)) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ return 0;
+ }
+
+ if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ return 0;
+ }
+
+ ALLOC_INIT_ZVAL(value);
+
+ if (!php_var_unserialize(&value, buf, max, (php_unserialize_data_t *) data TSRMLS_CC)) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ zval_dtor(value);
+ FREE_ZVAL(value);
+ return 0;
+ }
+
+ zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof value, NULL);
+
+ zval_dtor(key);
+ FREE_ZVAL(key);
+
+ if (php_var_unserialize_has_properties(*buf, *buf_len) && *(*buf-1) != ';' && *(*buf-1) != '}') {
+ (*buf)--;
+ return 0;
+ }
+ }
+
+ *buf_len = max - *buf;
+ return 1;
+}
+
+PHPAPI int php_var_unserialize_property(zval *key, zval *value, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC)
+{
+ const unsigned char *max;
+
+ max = *buf + *buf_len;
+
+ if (!php_var_unserialize(&key, buf, max, NULL TSRMLS_CC) || Z_TYPE_P(key) != IS_STRING) {
+ zval_dtor(key);
+ return 0;
+ }
+ if (!php_var_unserialize(&value, buf, max, (php_unserialize_data_t *) data TSRMLS_CC)) {
+ zval_dtor(key);
+ zval_dtor(value);
+ return 0;
+ }
+ *buf_len = max - *buf;
+ return 1;
+}
+
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
@@ -457,7 +531,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
-#line 461 "ext/standard/var_unserializer.c"
+#line 535 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
@@ -517,9 +591,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy95;
yy3:
-#line 812 "ext/standard/var_unserializer.re"
+#line 897 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 523 "ext/standard/var_unserializer.c"
+#line 597 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy89;
@@ -562,13 +636,13 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
goto yy3;
yy14:
++YYCURSOR;
-#line 806 "ext/standard/var_unserializer.re"
+#line 891 "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 572 "ext/standard/var_unserializer.c"
+#line 646 "ext/standard/var_unserializer.c"
yy16:
yych = *++YYCURSOR;
goto yy3;
@@ -598,7 +672,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 660 "ext/standard/var_unserializer.re"
+#line 734 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
long elements;
@@ -742,9 +816,20 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
}
efree(class_name);
+ /* custom unserialization for objects that are not custom (C: prefix) */
+ if (ce->unserialize && ce->unserialize != zend_user_unserialize) {
+ int ret = ce->unserialize(rval, ce, (const unsigned char*)*p, max - *p, (zend_unserialize_data *)var_hash TSRMLS_CC);
+ if (ret < 0) {
+ return 0;
+ }
+ /* In this case the return value from unserialize callback is the number of character left in the buffer */
+ (*p) = max - ret;
+ return finish_nested_data(UNSERIALIZE_PASSTHRU);
+ }
+
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 748 "ext/standard/var_unserializer.c"
+#line 833 "ext/standard/var_unserializer.c"
yy25:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -769,7 +854,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 652 "ext/standard/var_unserializer.re"
+#line 726 "ext/standard/var_unserializer.re"
{
INIT_PZVAL(*rval);
@@ -777,7 +862,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 781 "ext/standard/var_unserializer.c"
+#line 866 "ext/standard/var_unserializer.c"
yy32:
yych = *++YYCURSOR;
if (yych == '+') goto yy33;
@@ -798,7 +883,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '{') goto yy18;
++YYCURSOR;
-#line 632 "ext/standard/var_unserializer.re"
+#line 706 "ext/standard/var_unserializer.re"
{
long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
@@ -818,7 +903,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 822 "ext/standard/var_unserializer.c"
+#line 907 "ext/standard/var_unserializer.c"
yy39:
yych = *++YYCURSOR;
if (yych == '+') goto yy40;
@@ -839,7 +924,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 603 "ext/standard/var_unserializer.re"
+#line 677 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -868,7 +953,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_STRINGL(*rval, str, len, 0);
return 1;
}
-#line 872 "ext/standard/var_unserializer.c"
+#line 957 "ext/standard/var_unserializer.c"
yy46:
yych = *++YYCURSOR;
if (yych == '+') goto yy47;
@@ -889,7 +974,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 575 "ext/standard/var_unserializer.re"
+#line 649 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -917,7 +1002,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_STRINGL(*rval, str, len, 1);
return 1;
}
-#line 921 "ext/standard/var_unserializer.c"
+#line 1006 "ext/standard/var_unserializer.c"
yy53:
yych = *++YYCURSOR;
if (yych <= '/') {
@@ -1005,7 +1090,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
}
yy63:
++YYCURSOR;
-#line 565 "ext/standard/var_unserializer.re"
+#line 639 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
use_double:
@@ -1015,7 +1100,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
return 1;
}
-#line 1019 "ext/standard/var_unserializer.c"
+#line 1104 "ext/standard/var_unserializer.c"
yy65:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1074,22 +1159,22 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 550 "ext/standard/var_unserializer.re"
+#line 624 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
- if (!strncmp(start + 2, "NAN", 3)) {
+ if (!strncmp((const char *) (start + 2), "NAN", 3)) {
ZVAL_DOUBLE(*rval, php_get_nan());
- } else if (!strncmp(start + 2, "INF", 3)) {
+ } else if (!strncmp((const char *) (start + 2), "INF", 3)) {
ZVAL_DOUBLE(*rval, php_get_inf());
- } else if (!strncmp(start + 2, "-INF", 4)) {
+ } else if (!strncmp((const char *) (start + 2), "-INF", 4)) {
ZVAL_DOUBLE(*rval, -php_get_inf());
}
return 1;
}
-#line 1093 "ext/standard/var_unserializer.c"
+#line 1178 "ext/standard/var_unserializer.c"
yy76:
yych = *++YYCURSOR;
if (yych == 'N') goto yy73;
@@ -1116,7 +1201,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
if (yych <= '9') goto yy79;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 523 "ext/standard/var_unserializer.re"
+#line 597 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
int digits = YYCURSOR - start - 3;
@@ -1143,7 +1228,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
ZVAL_LONG(*rval, parse_iv(start + 2));
return 1;
}
-#line 1147 "ext/standard/var_unserializer.c"
+#line 1232 "ext/standard/var_unserializer.c"
yy83:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
@@ -1151,24 +1236,24 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 516 "ext/standard/var_unserializer.re"
+#line 590 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_BOOL(*rval, parse_iv(start + 2));
return 1;
}
-#line 1162 "ext/standard/var_unserializer.c"
+#line 1247 "ext/standard/var_unserializer.c"
yy87:
++YYCURSOR;
-#line 509 "ext/standard/var_unserializer.re"
+#line 583 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_NULL(*rval);
return 1;
}
-#line 1172 "ext/standard/var_unserializer.c"
+#line 1257 "ext/standard/var_unserializer.c"
yy89:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1191,7 +1276,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
if (yych <= '9') goto yy91;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 486 "ext/standard/var_unserializer.re"
+#line 560 "ext/standard/var_unserializer.re"
{
long id;
@@ -1214,7 +1299,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return 1;
}
-#line 1218 "ext/standard/var_unserializer.c"
+#line 1303 "ext/standard/var_unserializer.c"
yy95:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1237,7 +1322,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
if (yych <= '9') goto yy97;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 465 "ext/standard/var_unserializer.re"
+#line 539 "ext/standard/var_unserializer.re"
{
long id;
@@ -1258,9 +1343,9 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
return 1;
}
-#line 1262 "ext/standard/var_unserializer.c"
+#line 1347 "ext/standard/var_unserializer.c"
}
-#line 814 "ext/standard/var_unserializer.re"
+#line 899 "ext/standard/var_unserializer.re"
return 0;
View
93 ext/standard/var_unserializer.re
@@ -21,6 +21,7 @@
#include "php.h"
#include "ext/standard/php_var.h"
#include "php_incomplete_class.h"
+#include "zend_interfaces.h"
/* {{{ reference-handling for unserializer: var_* */
#define VAR_ENTRIES_MAX 1024
@@ -380,10 +381,11 @@ static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
return 0;
}
+ ZVAL_NULL(*rval);
if (ce->unserialize == NULL) {
zend_error(E_WARNING, "Class %s has no unserializer", ce->name);
object_init_ex(*rval, ce);
- } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) {
+ } else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) < 0) {
return 0;
}
@@ -440,6 +442,78 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
# pragma optimize("", on)
#endif
+PHPAPI int php_var_unserialize_has_properties(const unsigned char *buf, zend_uint buf_len)
+{
+ return buf_len && *buf != '}';
+}
+
+PHPAPI int php_var_unserialize_properties(HashTable *ht, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC)
+{
+ const unsigned char *max;
+
+ max = *buf + *buf_len;
+
+ while (php_var_unserialize_has_properties(*buf, *buf_len)) {
+ zval *key, *value;
+
+ ALLOC_INIT_ZVAL(key);
+
+ if (!php_var_unserialize(&key, buf, max, NULL TSRMLS_CC)) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ return 0;
+ }
+
+ if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ return 0;
+ }
+
+ ALLOC_INIT_ZVAL(value);
+
+ if (!php_var_unserialize(&value, buf, max, (php_unserialize_data_t *) data TSRMLS_CC)) {
+ zval_dtor(key);
+ FREE_ZVAL(key);
+ zval_dtor(value);
+ FREE_ZVAL(value);
+ return 0;
+ }
+
+ zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof value, NULL);
+
+ zval_dtor(key);
+ FREE_ZVAL(key);
+
+ if (php_var_unserialize_has_properties(*buf, *buf_len) && *(*buf-1) != ';' && *(*buf-1) != '}') {
+ (*buf)--;
+ return 0;
+ }
+ }
+
+ *buf_len = max - *buf;
+ return 1;
+}
+
+PHPAPI int php_var_unserialize_property(zval *key, zval *value, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC)
+{
+ const unsigned char *max;
+
+ max = *buf + *buf_len;
+
+ if (!php_var_unserialize(&key, buf, max, NULL TSRMLS_CC) || Z_TYPE_P(key) != IS_STRING) {
+ zval_dtor(key);
+ return 0;
+ }
+ if (!php_var_unserialize(&value, buf, max, (php_unserialize_data_t *) data TSRMLS_CC)) {
+ zval_dtor(key);
+ zval_dtor(value);
+ return 0;
+ }
+ *buf_len = max - *buf;
+ return 1;
+}
+
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
@@ -551,11 +625,11 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
*p = YYCURSOR;
INIT_PZVAL(*rval);
- if (!strncmp(start + 2, "NAN", 3)) {
+ if (!strncmp((const char *) (start + 2), "NAN", 3)) {
ZVAL_DOUBLE(*rval, php_get_nan());
- } else if (!strncmp(start + 2, "INF", 3)) {
+ } else if (!strncmp((const char *) (start + 2), "INF", 3)) {
ZVAL_DOUBLE(*rval, php_get_inf());
- } else if (!strncmp(start + 2, "-INF", 4)) {
+ } else if (!strncmp((const char *) (start + 2), "-INF", 4)) {
ZVAL_DOUBLE(*rval, -php_get_inf());
}
@@ -800,6 +874,17 @@ object ":" uiv ":" ["] {
}
efree(class_name);
+ /* custom unserialization for objects that are not custom (C: prefix) */
+ if (ce->unserialize && ce->unserialize != zend_user_unserialize) {
+ int ret = ce->unserialize(rval, ce, (const unsigned char*)*p, max - *p, (zend_unserialize_data *)var_hash TSRMLS_CC);
+ if (ret < 0) {
+ return 0;
+ }
+ /* In this case the return value from unserialize callback is the number of character left in the buffer */
+ (*p) = max - ret;
+ return finish_nested_data(UNSERIALIZE_PASSTHRU);
+ }
+
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}

No commit comments for this range

Something went wrong with that request. Please try again.