summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-08-10 12:51:48 +0200
committerNikita Popov <nikic@php.net>2016-08-15 22:42:27 +0200
commitf7caa2bd8e72d51201b90158c34219d6feefb4ff (patch)
tree9c0b04e64fafa65e8ed91d73140d9dd3e683b6a6
parentc63260c088e57e17d2babc9c932deb234ebd7e99 (diff)
downloadphp-git-f7caa2bd8e72d51201b90158c34219d6feefb4ff.tar.gz
Hide (un)serialize data from ABI
The (UN)SERIALIZE_INIT/DESTROY macros now go through non-inlined functions, so any changes to them will apply to extensions without rebuilds. Additionally, the (un)serialize_data structures are now no longer exported. This means that we are allowed to change these structures in patch releases without breaking the ABI.
-rw-r--r--ext/standard/php_var.h69
-rw-r--r--ext/standard/var.c34
-rw-r--r--ext/standard/var_unserializer.c1023
-rw-r--r--ext/standard/var_unserializer.re35
4 files changed, 619 insertions, 542 deletions
diff --git a/ext/standard/php_var.h b/ext/standard/php_var.h
index 4afefbe95a..80208d29ee 100644
--- a/ext/standard/php_var.h
+++ b/ext/standard/php_var.h
@@ -38,18 +38,6 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf);
PHPAPI void php_debug_zval_dump(zval *struc, int level);
-struct php_serialize_data {
- HashTable ht;
- uint32_t n;
-};
-
-struct php_unserialize_data {
- void *first;
- void *last;
- void *first_dtor;
- void *last_dtor;
-};
-
typedef struct php_serialize_data *php_serialize_data_t;
typedef struct php_unserialize_data *php_unserialize_data_t;
@@ -59,61 +47,22 @@ PHPAPI int php_var_unserialize_ref(zval *rval, const unsigned char **p, const un
PHPAPI int php_var_unserialize_intern(zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash);
PHPAPI int php_var_unserialize_ex(zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes);
+PHPAPI php_serialize_data_t php_var_serialize_init(void);
+PHPAPI void php_var_serialize_destroy(php_serialize_data_t d);
+PHPAPI php_unserialize_data_t php_var_unserialize_init(void);
+PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d);
+
#define PHP_VAR_SERIALIZE_INIT(d) \
-do { \
- /* fprintf(stderr, "SERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
- if (BG(serialize_lock) || !BG(serialize).level) { \
- (d) = (php_serialize_data_t) emalloc(sizeof(struct php_serialize_data)); \
- zend_hash_init(&(d)->ht, 16, NULL, ZVAL_PTR_DTOR, 0); \
- (d)->n = 0; \
- if (!BG(serialize_lock)) { \
- BG(serialize).data = d; \
- BG(serialize).level = 1; \
- } \
- } else { \
- (d) = BG(serialize).data; \
- ++BG(serialize).level; \
- } \
-} while(0)
+ (d) = php_var_serialize_init()
#define PHP_VAR_SERIALIZE_DESTROY(d) \
-do { \
- /* fprintf(stderr, "SERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
- if (BG(serialize_lock) || BG(serialize).level == 1) { \
- zend_hash_destroy(&(d)->ht); \
- efree((d)); \
- } \
- if (!BG(serialize_lock) && !--BG(serialize).level) { \
- BG(serialize).data = NULL; \
- } \
-} while (0)
+ php_var_serialize_destroy(d)
#define PHP_VAR_UNSERIALIZE_INIT(d) \
-do { \
- /* fprintf(stderr, "UNSERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
- if (BG(serialize_lock) || !BG(unserialize).level) { \
- (d) = (php_unserialize_data_t)ecalloc(1, sizeof(struct php_unserialize_data)); \
- if (!BG(serialize_lock)) { \
- BG(unserialize).data = (d); \
- BG(unserialize).level = 1; \
- } \
- } else { \
- (d) = BG(unserialize).data; \
- ++BG(unserialize).level; \
- } \
-} while (0)
+ (d) = php_var_unserialize_init()
#define PHP_VAR_UNSERIALIZE_DESTROY(d) \
-do { \
- /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
- if (BG(serialize_lock) || BG(unserialize).level == 1) { \
- var_destroy(&(d)); \
- efree((d)); \
- } \
- if (!BG(serialize_lock) && !--BG(unserialize).level) { \
- BG(unserialize).data = NULL; \
- } \
-} while (0)
+ php_var_unserialize_destroy(d)
PHPAPI void var_replace(php_unserialize_data_t *var_hash, zval *ozval, zval *nzval);
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hash, zval *val);
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 809161afec..cc033aada7 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -33,6 +33,11 @@
#include "php_incomplete_class.h"
/* }}} */
+struct php_serialize_data {
+ HashTable ht;
+ uint32_t n;
+};
+
#define COMMON (is_ref ? "&" : "")
static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
@@ -993,6 +998,35 @@ PHPAPI void php_var_serialize(smart_str *buf, zval *struc, php_serialize_data_t
}
/* }}} */
+PHPAPI php_serialize_data_t php_var_serialize_init() {
+ struct php_serialize_data *d;
+ /* fprintf(stderr, "SERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */
+ if (BG(serialize_lock) || !BG(serialize).level) {
+ d = emalloc(sizeof(struct php_serialize_data));
+ zend_hash_init(&d->ht, 16, NULL, ZVAL_PTR_DTOR, 0);
+ d->n = 0;
+ if (!BG(serialize_lock)) {
+ BG(serialize).data = d;
+ BG(serialize).level = 1;
+ }
+ } else {
+ d = BG(serialize).data;
+ ++BG(serialize).level;
+ }
+ return d;
+}
+
+PHPAPI void php_var_serialize_destroy(php_serialize_data_t d) {
+ /* fprintf(stderr, "SERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */
+ if (BG(serialize_lock) || BG(serialize).level == 1) {
+ zend_hash_destroy(&d->ht);
+ efree(d);
+ }
+ if (!BG(serialize_lock) && !--BG(serialize).level) {
+ BG(serialize).data = NULL;
+ }
+}
+
/* {{{ proto string serialize(mixed variable)
Returns a string representation of variable (which can later be unserialized) */
PHP_FUNCTION(serialize)
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c
index e2b95174d7..f96fdb40d6 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 */
+/* Generated by re2c 0.16 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
@@ -24,6 +24,41 @@
#include "ext/standard/php_var.h"
#include "php_incomplete_class.h"
+struct php_unserialize_data {
+ void *first;
+ void *last;
+ void *first_dtor;
+ void *last_dtor;
+};
+
+PHPAPI php_unserialize_data_t php_var_unserialize_init() {
+ php_unserialize_data_t d;
+ /* fprintf(stderr, "UNSERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+ if (BG(serialize_lock) || !BG(unserialize).level) {
+ d = ecalloc(1, sizeof(struct php_unserialize_data));
+ if (!BG(serialize_lock)) {
+ BG(unserialize).data = d;
+ BG(unserialize).level = 1;
+ }
+ } else {
+ d = BG(unserialize).data;
+ ++BG(unserialize).level;
+ }
+ return d;
+}
+
+PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
+ /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+ if (BG(serialize_lock) || BG(unserialize).level == 1) {
+ var_destroy(&d);
+ efree(d);
+ }
+ if (!BG(serialize_lock) && !--BG(unserialize).level) {
+ BG(unserialize).data = NULL;
+ }
+}
+
+
/* {{{ reference-handling for unserializer: var_* */
#define VAR_ENTRIES_MAX 1024
#define VAR_ENTRIES_DBG 0
@@ -238,7 +273,7 @@ static inline int unserialize_allowed_class(zend_string *class_name, HashTable *
#define YYMARKER marker
-#line 246 "ext/standard/var_unserializer.re"
+#line 281 "ext/standard/var_unserializer.re"
@@ -514,7 +549,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
start = cursor;
-#line 518 "ext/standard/var_unserializer.c"
+#line 553 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
@@ -551,111 +586,510 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
-
if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
yych = *YYCURSOR;
switch (yych) {
case 'C':
- case 'O': goto yy13;
+ case 'O': goto yy4;
case 'N': goto yy5;
- case 'R': goto yy2;
- case 'S': goto yy10;
- case 'a': goto yy11;
- case 'b': goto yy6;
- case 'd': goto yy8;
- case 'i': goto yy7;
+ case 'R': goto yy6;
+ case 'S': goto yy7;
+ case 'a': goto yy8;
+ case 'b': goto yy9;
+ case 'd': goto yy10;
+ case 'i': goto yy11;
case 'o': goto yy12;
- case 'r': goto yy4;
- case 's': goto yy9;
- case '}': goto yy14;
- default: goto yy16;
+ case 'r': goto yy13;
+ case 's': goto yy14;
+ case '}': goto yy15;
+ default: goto yy2;
}
yy2:
- yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy95;
+ ++YYCURSOR;
yy3:
-#line 884 "ext/standard/var_unserializer.re"
+#line 919 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 580 "ext/standard/var_unserializer.c"
+#line 613 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy89;
+ if (yych == ':') goto yy17;
goto yy3;
yy5:
yych = *++YYCURSOR;
- if (yych == ';') goto yy87;
+ if (yych == ';') goto yy19;
goto yy3;
yy6:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy83;
+ if (yych == ':') goto yy21;
goto yy3;
yy7:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy77;
+ if (yych == ':') goto yy22;
goto yy3;
yy8:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy53;
+ if (yych == ':') goto yy23;
goto yy3;
yy9:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy46;
+ if (yych == ':') goto yy24;
goto yy3;
yy10:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy39;
+ if (yych == ':') goto yy25;
goto yy3;
yy11:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy32;
+ if (yych == ':') goto yy26;
goto yy3;
yy12:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy25;
+ if (yych == ':') goto yy27;
goto yy3;
yy13:
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == ':') goto yy17;
+ if (yych == ':') goto yy28;
goto yy3;
yy14:
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == ':') goto yy29;
+ goto yy3;
+yy15:
++YYCURSOR;
-#line 878 "ext/standard/var_unserializer.re"
+#line 913 "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 629 "ext/standard/var_unserializer.c"
-yy16:
- yych = *++YYCURSOR;
- goto yy3;
+#line 666 "ext/standard/var_unserializer.c"
yy17:
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy20;
+ goto yy31;
}
- if (yych == '+') goto yy19;
+ if (yych == '+') goto yy30;
yy18:
YYCURSOR = YYMARKER;
goto yy3;
yy19:
+ ++YYCURSOR;
+#line 608 "ext/standard/var_unserializer.re"
+ {
+ *p = YYCURSOR;
+ ZVAL_NULL(rval);
+ return 1;
+}
+#line 684 "ext/standard/var_unserializer.c"
+yy21:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych == '+') goto yy33;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy33;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy34;
+ goto yy18;
+ }
+yy22:
+ yych = *++YYCURSOR;
+ if (yych == '+') goto yy36;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy37;
+ goto yy18;
+yy23:
+ yych = *++YYCURSOR;
+ if (yych == '+') goto yy39;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy40;
+ goto yy18;
+yy24:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '1') goto yy42;
+ goto yy18;
+yy25:
+ yych = *++YYCURSOR;
+ if (yych <= '/') {
+ if (yych <= ',') {
+ if (yych == '+') goto yy43;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy44;
+ if (yych <= '.') goto yy45;
+ goto yy18;
+ }
+ } else {
+ if (yych <= 'I') {
+ if (yych <= '9') goto yy46;
+ if (yych <= 'H') goto yy18;
+ goto yy48;
+ } else {
+ if (yych == 'N') goto yy49;
+ goto yy18;
+ }
+ }
+yy26:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych == '+') goto yy50;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy50;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy51;
+ goto yy18;
+ }
+yy27:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych == '+') goto yy53;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy53;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy54;
+ goto yy18;
+ }
+yy28:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych == '+') goto yy56;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy56;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy57;
+ goto yy18;
+ }
+yy29:
+ yych = *++YYCURSOR;
+ if (yych == '+') goto yy59;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy60;
+ goto yy18;
+yy30:
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy20;
+ goto yy31;
}
goto yy18;
-yy20:
+yy31:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy20;
+ goto yy31;
+ }
+ if (yych <= '/') goto yy18;
+ if (yych <= ':') goto yy62;
+ goto yy18;
+yy33:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy34:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy34;
+ if (yych == ';') goto yy63;
+ goto yy18;
+yy36:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy37:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy37;
+ if (yych <= ':') goto yy65;
+ goto yy18;
+yy39:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy40:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy40;
+ if (yych <= ':') goto yy66;
+ goto yy18;
+yy42:
+ yych = *++YYCURSOR;
+ if (yych == ';') goto yy67;
+ goto yy18;
+yy43:
+ yych = *++YYCURSOR;
+ if (yych == '.') goto yy45;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy46;
+ goto yy18;
+yy44:
+ yych = *++YYCURSOR;
+ if (yych <= '/') {
+ if (yych != '.') goto yy18;
+ } else {
+ if (yych <= '9') goto yy46;
+ if (yych == 'I') goto yy48;
+ goto yy18;
+ }
+yy45:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy69;
+ goto yy18;
+yy46:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ if (yych <= ':') {
+ if (yych <= '.') {
+ if (yych <= '-') goto yy18;
+ goto yy69;
+ } else {
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy46;
+ goto yy18;
+ }
+ } else {
+ if (yych <= 'E') {
+ if (yych <= ';') goto yy71;
+ if (yych <= 'D') goto yy18;
+ goto yy73;
+ } else {
+ if (yych == 'e') goto yy73;
+ goto yy18;
+ }
+ }
+yy48:
+ yych = *++YYCURSOR;
+ if (yych == 'N') goto yy74;
+ goto yy18;
+yy49:
+ yych = *++YYCURSOR;
+ if (yych == 'A') goto yy75;
+ goto yy18;
+yy50:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy51:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy51;
+ if (yych == ';') goto yy76;
+ goto yy18;
+yy53:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy54:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy54;
+ if (yych <= ':') goto yy78;
+ goto yy18;
+yy56:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy57:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy57;
+ if (yych == ';') goto yy79;
+ goto yy18;
+yy59:
+ yych = *++YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych >= ':') goto yy18;
+yy60:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy60;
+ if (yych <= ':') goto yy81;
+ goto yy18;
+yy62:
+ yych = *++YYCURSOR;
+ if (yych == '"') goto yy82;
+ goto yy18;
+yy63:
+ ++YYCURSOR;
+#line 557 "ext/standard/var_unserializer.re"
+ {
+ zend_long id;
+
+ *p = YYCURSOR;
+ if (!var_hash) return 0;
+
+ id = parse_iv(start + 2) - 1;
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+ return 0;
+ }
+
+ zval_ptr_dtor(rval);
+ if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+ ZVAL_UNDEF(rval);
+ return 1;
+ }
+ if (Z_ISREF_P(rval_ref)) {
+ ZVAL_COPY(rval, rval_ref);
+ } else {
+ ZVAL_NEW_REF(rval_ref, rval_ref);
+ ZVAL_COPY(rval, rval_ref);
+ }
+
+ return 1;
+}
+#line 960 "ext/standard/var_unserializer.c"
+yy65:
+ yych = *++YYCURSOR;
+ if (yych == '"') goto yy84;
+ goto yy18;
+yy66:
+ yych = *++YYCURSOR;
+ if (yych == '{') goto yy86;
+ goto yy18;
+yy67:
+ ++YYCURSOR;
+#line 614 "ext/standard/var_unserializer.re"
+ {
+ *p = YYCURSOR;
+ ZVAL_BOOL(rval, parse_iv(start + 2));
+ return 1;
+}
+#line 977 "ext/standard/var_unserializer.c"
+yy69:
+ ++YYCURSOR;
+ if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ if (yych <= ';') {
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy69;
+ if (yych <= ':') goto yy18;
+ } else {
+ if (yych <= 'E') {
+ if (yych <= 'D') goto yy18;
+ goto yy73;
+ } else {
+ if (yych == 'e') goto yy73;
+ goto yy18;
+ }
+ }
+yy71:
+ ++YYCURSOR;
+#line 662 "ext/standard/var_unserializer.re"
+ {
+#if SIZEOF_ZEND_LONG == 4
+use_double:
+#endif
+ *p = YYCURSOR;
+ ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
+ return 1;
+}
+#line 1006 "ext/standard/var_unserializer.c"
+yy73:
+ yych = *++YYCURSOR;
+ if (yych <= ',') {
+ if (yych == '+') goto yy88;
+ goto yy18;
+ } else {
+ if (yych <= '-') goto yy88;
+ if (yych <= '/') goto yy18;
+ if (yych <= '9') goto yy89;
+ goto yy18;
+ }
+yy74:
+ yych = *++YYCURSOR;
+ if (yych == 'F') goto yy91;
+ goto yy18;
+yy75:
+ yych = *++YYCURSOR;
+ if (yych == 'N') goto yy91;
+ goto yy18;
+yy76:
+ ++YYCURSOR;
+#line 620 "ext/standard/var_unserializer.re"
+ {
+#if SIZEOF_ZEND_LONG == 4
+ int digits = YYCURSOR - start - 3;
+
+ if (start[2] == '-' || start[2] == '+') {
+ digits--;
+ }
+
+ /* Use double for large zend_long values that were serialized on a 64-bit system */
+ if (digits >= MAX_LENGTH_OF_LONG - 1) {
+ if (digits == MAX_LENGTH_OF_LONG - 1) {
+ int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
+
+ if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
+ goto use_double;
+ }
+ } else {
+ goto use_double;
+ }
+ }
+#endif
+ *p = YYCURSOR;
+ ZVAL_LONG(rval, parse_iv(start + 2));
+ return 1;
+}
+#line 1054 "ext/standard/var_unserializer.c"
+yy78:
+ yych = *++YYCURSOR;
+ if (yych == '"') goto yy92;
+ goto yy18;
+yy79:
+ ++YYCURSOR;
+#line 583 "ext/standard/var_unserializer.re"
+ {
+ zend_long id;
+
+ *p = YYCURSOR;
+ if (!var_hash) return 0;
+
+ id = parse_iv(start + 2) - 1;
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+ return 0;
+ }
+
+ if (rval_ref == rval) {
+ return 0;
}
- if (yych != ':') goto yy18;
+
+ if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
+ ZVAL_UNDEF(rval);
+ return 1;
+ }
+
+ ZVAL_COPY(rval, rval_ref);
+
+ return 1;
+}
+#line 1086 "ext/standard/var_unserializer.c"
+yy81:
yych = *++YYCURSOR;
- if (yych != '"') goto yy18;
+ if (yych == '"') goto yy94;
+ goto yy18;
+yy82:
++YYCURSOR;
-#line 733 "ext/standard/var_unserializer.re"
+#line 768 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
zend_long elements;
@@ -800,105 +1234,10 @@ yy20:
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 804 "ext/standard/var_unserializer.c"
-yy25:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych != '+') goto yy18;
- } else {
- if (yych <= '-') goto yy26;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy27;
- goto yy18;
- }
-yy26:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy27:
+#line 1238 "ext/standard/var_unserializer.c"
+yy84:
++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy27;
- if (yych >= ';') goto yy18;
- yych = *++YYCURSOR;
- if (yych != '"') goto yy18;
- ++YYCURSOR;
-#line 726 "ext/standard/var_unserializer.re"
- {
- if (!var_hash) return 0;
-
- return object_common2(UNSERIALIZE_PASSTHRU,
- object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
-}
-#line 836 "ext/standard/var_unserializer.c"
-yy32:
- yych = *++YYCURSOR;
- if (yych == '+') goto yy33;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy34;
- goto yy18;
-yy33:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy34:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy34;
- if (yych >= ';') goto yy18;
- yych = *++YYCURSOR;
- if (yych != '{') goto yy18;
- ++YYCURSOR;
-#line 702 "ext/standard/var_unserializer.re"
- {
- zend_long elements = parse_iv(start + 2);
- /* use iv() not uiv() in order to check data range */
- *p = YYCURSOR;
- if (!var_hash) return 0;
-
- if (elements < 0) {
- return 0;
- }
-
- array_init_size(rval, elements);
- if (elements) {
- /* we can't convert from packed to hash during unserialization, because
- reference to some zvals might be keept in var_hash (to support references) */
- zend_hash_real_init(Z_ARRVAL_P(rval), 0);
- }
-
- if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
- return 0;
- }
-
- return finish_nested_data(UNSERIALIZE_PASSTHRU);
-}
-#line 881 "ext/standard/var_unserializer.c"
-yy39:
- yych = *++YYCURSOR;
- if (yych == '+') goto yy40;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy41;
- goto yy18;
-yy40:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy41:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy41;
- if (yych >= ';') goto yy18;
- yych = *++YYCURSOR;
- if (yych != '"') goto yy18;
- ++YYCURSOR;
-#line 668 "ext/standard/var_unserializer.re"
+#line 703 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
zend_string *str;
@@ -932,407 +1271,127 @@ yy41:
ZVAL_STR(rval, str);
return 1;
}
-#line 936 "ext/standard/var_unserializer.c"
-yy46:
- yych = *++YYCURSOR;
- if (yych == '+') goto yy47;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy48;
- goto yy18;
-yy47:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy48:
+#line 1275 "ext/standard/var_unserializer.c"
+yy86:
++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy48;
- if (yych >= ';') goto yy18;
- yych = *++YYCURSOR;
- if (yych != '"') goto yy18;
- ++YYCURSOR;
-#line 636 "ext/standard/var_unserializer.re"
+#line 737 "ext/standard/var_unserializer.re"
{
- size_t len, maxlen;
- char *str;
+ zend_long elements = parse_iv(start + 2);
+ /* use iv() not uiv() in order to check data range */
+ *p = YYCURSOR;
+ if (!var_hash) return 0;
- len = parse_uiv(start + 2);
- maxlen = max - YYCURSOR;
- if (maxlen < len) {
- *p = start + 2;
+ if (elements < 0) {
return 0;
}
- str = (char*)YYCURSOR;
-
- YYCURSOR += len;
-
- if (*(YYCURSOR) != '"') {
- *p = YYCURSOR;
- return 0;
+ array_init_size(rval, elements);
+ if (elements) {
+ /* we can't convert from packed to hash during unserialization, because
+ reference to some zvals might be keept in var_hash (to support references) */
+ zend_hash_real_init(Z_ARRVAL_P(rval), 0);
}
- if (*(YYCURSOR + 1) != ';') {
- *p = YYCURSOR + 1;
+ if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
return 0;
}
- YYCURSOR += 2;
- *p = YYCURSOR;
-
- ZVAL_STRINGL(rval, str, len);
- return 1;
-}
-#line 989 "ext/standard/var_unserializer.c"
-yy53:
- yych = *++YYCURSOR;
- if (yych <= '/') {
- if (yych <= ',') {
- if (yych == '+') goto yy57;
- goto yy18;
- } else {
- if (yych <= '-') goto yy55;
- if (yych <= '.') goto yy60;
- goto yy18;
- }
- } else {
- if (yych <= 'I') {
- if (yych <= '9') goto yy58;
- if (yych <= 'H') goto yy18;
- goto yy56;
- } else {
- if (yych != 'N') goto yy18;
- }
- }
- yych = *++YYCURSOR;
- if (yych == 'A') goto yy76;
- goto yy18;
-yy55:
- yych = *++YYCURSOR;
- if (yych <= '/') {
- if (yych == '.') goto yy60;
- goto yy18;
- } else {
- if (yych <= '9') goto yy58;
- if (yych != 'I') goto yy18;
- }
-yy56:
- yych = *++YYCURSOR;
- if (yych == 'N') goto yy72;
- goto yy18;
-yy57:
- yych = *++YYCURSOR;
- if (yych == '.') goto yy60;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy58:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- if (yych <= ':') {
- if (yych <= '.') {
- if (yych <= '-') goto yy18;
- goto yy70;
- } else {
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy58;
- goto yy18;
- }
- } else {
- if (yych <= 'E') {
- if (yych <= ';') goto yy63;
- if (yych <= 'D') goto yy18;
- goto yy65;
- } else {
- if (yych == 'e') goto yy65;
- goto yy18;
- }
- }
-yy60:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy61:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- if (yych <= ';') {
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy61;
- if (yych <= ':') goto yy18;
- } else {
- if (yych <= 'E') {
- if (yych <= 'D') goto yy18;
- goto yy65;
- } else {
- if (yych == 'e') goto yy65;
- goto yy18;
- }
- }
-yy63:
- ++YYCURSOR;
-#line 627 "ext/standard/var_unserializer.re"
- {
-#if SIZEOF_ZEND_LONG == 4
-use_double:
-#endif
- *p = YYCURSOR;
- ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
- return 1;
+ return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 1086 "ext/standard/var_unserializer.c"
-yy65:
+#line 1302 "ext/standard/var_unserializer.c"
+yy88:
yych = *++YYCURSOR;
if (yych <= ',') {
- if (yych != '+') goto yy18;
- } else {
- if (yych <= '-') goto yy66;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy67;
- goto yy18;
- }
-yy66:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych == '+') goto yy69;
+ if (yych == '+') goto yy96;
goto yy18;
} else {
- if (yych <= '-') goto yy69;
+ if (yych <= '-') goto yy96;
if (yych <= '/') goto yy18;
if (yych >= ':') goto yy18;
}
-yy67:
+yy89:
++YYCURSOR;
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy67;
- if (yych == ';') goto yy63;
+ if (yych <= '9') goto yy89;
+ if (yych == ';') goto yy71;
goto yy18;
-yy69:
+yy91:
yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy67;
+ if (yych == ';') goto yy97;
goto yy18;
-yy70:
- ++YYCURSOR;
- if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
- yych = *YYCURSOR;
- if (yych <= ';') {
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy70;
- if (yych <= ':') goto yy18;
- goto yy63;
- } else {
- if (yych <= 'E') {
- if (yych <= 'D') goto yy18;
- goto yy65;
- } else {
- if (yych == 'e') goto yy65;
- goto yy18;
- }
- }
-yy72:
- yych = *++YYCURSOR;
- if (yych != 'F') goto yy18;
-yy73:
- yych = *++YYCURSOR;
- if (yych != ';') goto yy18;
+yy92:
++YYCURSOR;
-#line 611 "ext/standard/var_unserializer.re"
+#line 761 "ext/standard/var_unserializer.re"
{
- *p = YYCURSOR;
-
- if (!strncmp((char*)start + 2, "NAN", 3)) {
- ZVAL_DOUBLE(rval, php_get_nan());
- } else if (!strncmp((char*)start + 2, "INF", 3)) {
- ZVAL_DOUBLE(rval, php_get_inf());
- } else if (!strncmp((char*)start + 2, "-INF", 4)) {
- ZVAL_DOUBLE(rval, -php_get_inf());
- } else {
- ZVAL_NULL(rval);
- }
+ if (!var_hash) return 0;
- return 1;
+ return object_common2(UNSERIALIZE_PASSTHRU,
+ object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 1161 "ext/standard/var_unserializer.c"
-yy76:
- yych = *++YYCURSOR;
- if (yych == 'N') goto yy73;
- goto yy18;
-yy77:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych != '+') goto yy18;
- } else {
- if (yych <= '-') goto yy78;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy79;
- goto yy18;
- }
-yy78:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy79:
- ++YYCURSOR;
- if (YYLIMIT <= YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy79;
- if (yych != ';') goto yy18;
+#line 1334 "ext/standard/var_unserializer.c"
+yy94:
++YYCURSOR;
-#line 585 "ext/standard/var_unserializer.re"
+#line 671 "ext/standard/var_unserializer.re"
{
-#if SIZEOF_ZEND_LONG == 4
- int digits = YYCURSOR - start - 3;
+ size_t len, maxlen;
+ char *str;
- if (start[2] == '-' || start[2] == '+') {
- digits--;
+ len = parse_uiv(start + 2);
+ maxlen = max - YYCURSOR;
+ if (maxlen < len) {
+ *p = start + 2;
+ return 0;
}
- /* Use double for large zend_long values that were serialized on a 64-bit system */
- if (digits >= MAX_LENGTH_OF_LONG - 1) {
- if (digits == MAX_LENGTH_OF_LONG - 1) {
- int cmp = strncmp((char*)YYCURSOR - MAX_LENGTH_OF_LONG, long_min_digits, MAX_LENGTH_OF_LONG - 1);
-
- if (!(cmp < 0 || (cmp == 0 && start[2] == '-'))) {
- goto use_double;
- }
- } else {
- goto use_double;
- }
- }
-#endif
- *p = YYCURSOR;
- ZVAL_LONG(rval, parse_iv(start + 2));
- return 1;
-}
-#line 1214 "ext/standard/var_unserializer.c"
-yy83:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= '2') goto yy18;
- yych = *++YYCURSOR;
- if (yych != ';') goto yy18;
- ++YYCURSOR;
-#line 579 "ext/standard/var_unserializer.re"
- {
- *p = YYCURSOR;
- ZVAL_BOOL(rval, parse_iv(start + 2));
- return 1;
-}
-#line 1228 "ext/standard/var_unserializer.c"
-yy87:
- ++YYCURSOR;
-#line 573 "ext/standard/var_unserializer.re"
- {
- *p = YYCURSOR;
- ZVAL_NULL(rval);
- return 1;
-}
-#line 1237 "ext/standard/var_unserializer.c"
-yy89:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych != '+') goto yy18;
- } else {
- if (yych <= '-') goto yy90;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy91;
- goto yy18;
- }
-yy90:
- yych = *++YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
-yy91:
- ++YYCURSOR;
- if (YYLIMIT <= YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy91;
- if (yych != ';') goto yy18;
- ++YYCURSOR;
-#line 548 "ext/standard/var_unserializer.re"
- {
- zend_long id;
+ str = (char*)YYCURSOR;
- *p = YYCURSOR;
- if (!var_hash) return 0;
+ YYCURSOR += len;
- id = parse_iv(start + 2) - 1;
- if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
+ if (*(YYCURSOR) != '"') {
+ *p = YYCURSOR;
return 0;
}
- if (rval_ref == rval) {
+ if (*(YYCURSOR + 1) != ';') {
+ *p = YYCURSOR + 1;
return 0;
}
- if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
- ZVAL_UNDEF(rval);
- return 1;
- }
-
- ZVAL_COPY(rval, rval_ref);
+ YYCURSOR += 2;
+ *p = YYCURSOR;
+ ZVAL_STRINGL(rval, str, len);
return 1;
}
-#line 1285 "ext/standard/var_unserializer.c"
-yy95:
- yych = *++YYCURSOR;
- if (yych <= ',') {
- if (yych != '+') goto yy18;
- } else {
- if (yych <= '-') goto yy96;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy97;
- goto yy18;
- }
+#line 1369 "ext/standard/var_unserializer.c"
yy96:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
- if (yych >= ':') goto yy18;
+ if (yych <= '9') goto yy89;
+ goto yy18;
yy97:
++YYCURSOR;
- if (YYLIMIT <= YYCURSOR) YYFILL(1);
- yych = *YYCURSOR;
- if (yych <= '/') goto yy18;
- if (yych <= '9') goto yy97;
- if (yych != ';') goto yy18;
- ++YYCURSOR;
-#line 522 "ext/standard/var_unserializer.re"
+#line 646 "ext/standard/var_unserializer.re"
{
- zend_long id;
-
- *p = YYCURSOR;
- if (!var_hash) return 0;
-
- id = parse_iv(start + 2) - 1;
- if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
- return 0;
- }
+ *p = YYCURSOR;
- zval_ptr_dtor(rval);
- if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
- ZVAL_UNDEF(rval);
- return 1;
- }
- if (Z_ISREF_P(rval_ref)) {
- ZVAL_COPY(rval, rval_ref);
+ if (!strncmp((char*)start + 2, "NAN", 3)) {
+ ZVAL_DOUBLE(rval, php_get_nan());
+ } else if (!strncmp((char*)start + 2, "INF", 3)) {
+ ZVAL_DOUBLE(rval, php_get_inf());
+ } else if (!strncmp((char*)start + 2, "-INF", 4)) {
+ ZVAL_DOUBLE(rval, -php_get_inf());
} else {
- ZVAL_NEW_REF(rval_ref, rval_ref);
- ZVAL_COPY(rval, rval_ref);
+ ZVAL_NULL(rval);
}
return 1;
}
-#line 1334 "ext/standard/var_unserializer.c"
+#line 1393 "ext/standard/var_unserializer.c"
}
-#line 886 "ext/standard/var_unserializer.re"
+#line 921 "ext/standard/var_unserializer.re"
return 0;
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index 52e2cf3646..4ba8f75f3b 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -22,6 +22,41 @@
#include "ext/standard/php_var.h"
#include "php_incomplete_class.h"
+struct php_unserialize_data {
+ void *first;
+ void *last;
+ void *first_dtor;
+ void *last_dtor;
+};
+
+PHPAPI php_unserialize_data_t php_var_unserialize_init() {
+ php_unserialize_data_t d;
+ /* fprintf(stderr, "UNSERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+ if (BG(serialize_lock) || !BG(unserialize).level) {
+ d = ecalloc(1, sizeof(struct php_unserialize_data));
+ if (!BG(serialize_lock)) {
+ BG(unserialize).data = d;
+ BG(unserialize).level = 1;
+ }
+ } else {
+ d = BG(unserialize).data;
+ ++BG(unserialize).level;
+ }
+ return d;
+}
+
+PHPAPI void php_var_unserialize_destroy(php_unserialize_data_t d) {
+ /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
+ if (BG(serialize_lock) || BG(unserialize).level == 1) {
+ var_destroy(&d);
+ efree(d);
+ }
+ if (!BG(serialize_lock) && !--BG(unserialize).level) {
+ BG(unserialize).data = NULL;
+ }
+}
+
+
/* {{{ reference-handling for unserializer: var_* */
#define VAR_ENTRIES_MAX 1024
#define VAR_ENTRIES_DBG 0