return (spl_SplObjectStorageElement*)zend_hash_find_ptr(&intern->storage, hash);
} /* }}} */
-void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
+spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
{
spl_SplObjectStorageElement *pelement, element;
zend_string *hash = spl_object_storage_get_hash(intern, this, obj TSRMLS_CC);
ZVAL_NULL(&pelement->inf);
}
spl_object_storage_free_hash(intern, hash);
- return;
+ return pelement;
}
ZVAL_COPY(&element.obj, obj);
} else {
ZVAL_NULL(&element.inf);
}
- zend_hash_update_mem(&intern->storage, hash, &element, sizeof(spl_SplObjectStorageElement));
+ pelement = zend_hash_update_mem(&intern->storage, hash, &element, sizeof(spl_SplObjectStorageElement));
spl_object_storage_free_hash(intern, hash);
+ return pelement;
} /* }}} */
int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *obj TSRMLS_DC) /* {{{ */
const unsigned char *p, *s;
php_unserialize_data_t var_hash;
zval entry, pmembers, pcount, inf;
+ spl_SplObjectStorageElement *element;
long count;
+ HashPosition pos;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
return;
if(*p != 'O' && *p != 'C' && *p != 'r') {
goto outexcept;
}
+ /* sore reference to allow cross-references between different elements */
if (!php_var_unserialize(&entry, &p, s + buf_len, &var_hash TSRMLS_CC)) {
goto outexcept;
}
var_push_dtor(&var_hash, &pelement->obj);
}
}
- spl_object_storage_attach(intern, getThis(), &entry, &inf TSRMLS_CC);
+ element = spl_object_storage_attach(intern, getThis(), &entry, &inf TSRMLS_CC);
+ var_replace(&var_hash, &entry, &element->obj);
+ var_replace(&var_hash, &inf, &element->inf);
zval_ptr_dtor(&entry);
zval_ptr_dtor(&inf);
}
void *next;
} var_entries;
+typedef struct {
+ zval data[VAR_ENTRIES_MAX];
+ long used_slots;
+ void *next;
+} var_dtor_entries;
+
static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
{
var_entries *var_hash = (*var_hashx)->last;
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
{
- var_entries *var_hash = (*var_hashx)->last_dtor;
+ var_dtor_entries *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
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
- var_hash = emalloc(sizeof(var_entries));
+ var_hash = emalloc(sizeof(var_dtor_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
(*var_hashx)->last_dtor = var_hash;
}
- if (Z_REFCOUNTED_P(rval)) Z_ADDREF_P(rval);
- var_hash->data[var_hash->used_slots++] = rval;
+ ZVAL_COPY(&var_hash->data[var_hash->used_slots], rval);
+ var_hash->used_slots++;
}
//???
#if 0
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval *rval)
{
- var_entries *var_hash = (*var_hashx)->last_dtor;
+ var_dtor_entries *var_hash = (*var_hashx)->last_dtor;
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
- var_hash = emalloc(sizeof(var_entries));
+ var_hash = emalloc(sizeof(var_dtor_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
(*var_hashx)->last_dtor = var_hash;
}
- var_hash->data[var_hash->used_slots++] = rval;
+ ZVAL_COPY_VALUE(&var_hash->data[var_hash->used_slots], rval);
+ var_hash->used_slots++;
}
#endif
-static int var_access(php_unserialize_data_t *var_hashx, long id, zval **store)
+PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
+{
+ long i;
+ var_entries *var_hash = (*var_hashx)->first;
+#if VAR_ENTRIES_DBG
+ fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
+#endif
+
+ while (var_hash) {
+ for (i = 0; i < var_hash->used_slots; i++) {
+ if (var_hash->data[i] == ozval) {
+ var_hash->data[i] = nzval;
+ /* do not break here */
+ }
+ }
+ var_hash = var_hash->next;
+ }
+}
+
+static zval *var_access(php_unserialize_data_t *var_hashx, long id)
{
var_entries *var_hash = (*var_hashx)->first;
#if VAR_ENTRIES_DBG
id -= VAR_ENTRIES_MAX;
}
- if (!var_hash) return !SUCCESS;
+ if (!var_hash) return NULL;
- if (id < 0 || id >= var_hash->used_slots) return !SUCCESS;
+ if (id < 0 || id >= var_hash->used_slots) return NULL;
- *store = var_hash->data[id];
-
- return SUCCESS;
+ return var_hash->data[id];
}
PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
void *next;
long i;
var_entries *var_hash = (*var_hashx)->first;
+ var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
#endif
var_hash = next;
}
- var_hash = (*var_hashx)->first_dtor;
-
- while (var_hash) {
- for (i = 0; i < var_hash->used_slots; i++) {
- zval_ptr_dtor(var_hash->data[i]);
+ while (var_dtor_hash) {
+ for (i = 0; i < var_dtor_hash->used_slots; i++) {
+ zval_ptr_dtor(&var_dtor_hash->data[i]);
}
- next = var_hash->next;
- efree(var_hash);
- var_hash = next;
+ next = var_dtor_hash->next;
+ efree(var_dtor_hash);
+ var_dtor_hash = next;
}
}
#define YYMARKER marker
-#line 218 "ext/standard/var_unserializer.re"
+#line 241 "ext/standard/var_unserializer.re"
switch (Z_TYPE(key)) {
case IS_LONG:
if ((old_data = zend_hash_index_find(ht, Z_LVAL(key))) != NULL) {
+ //??? update hash
var_push_dtor(var_hash, old_data);
}
data = zend_hash_index_update(ht, Z_LVAL(key), &d);
break;
case IS_STRING:
if ((old_data = zend_symtable_find(ht, Z_STR(key))) != NULL) {
+ //??? update hash
var_push_dtor(var_hash, old_data);
}
data = zend_symtable_update(ht, Z_STR(key), &d);
zval retval;
zval fname;
+ //??? TODO: resize before
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_P(rval), elements, 1)) {
return 0;
}
start = cursor;
-#line 447 "ext/standard/var_unserializer.c"
+#line 473 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy95;
yy3:
-#line 793 "ext/standard/var_unserializer.re"
+#line 817 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 509 "ext/standard/var_unserializer.c"
+#line 535 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy89;
goto yy3;
yy14:
++YYCURSOR;
-#line 787 "ext/standard/var_unserializer.re"
+#line 811 "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 558 "ext/standard/var_unserializer.c"
+#line 584 "ext/standard/var_unserializer.c"
yy16:
yych = *++YYCURSOR;
goto yy3;
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 648 "ext/standard/var_unserializer.re"
+#line 672 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
long elements;
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 727 "ext/standard/var_unserializer.c"
+#line 753 "ext/standard/var_unserializer.c"
yy25:
yych = *++YYCURSOR;
if (yych <= ',') {
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 640 "ext/standard/var_unserializer.re"
+#line 664 "ext/standard/var_unserializer.re"
{
//??? INIT_PZVAL(rval);
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 760 "ext/standard/var_unserializer.c"
+#line 786 "ext/standard/var_unserializer.c"
yy32:
yych = *++YYCURSOR;
if (yych == '+') goto yy33;
yych = *++YYCURSOR;
if (yych != '{') goto yy18;
++YYCURSOR;
-#line 619 "ext/standard/var_unserializer.re"
+#line 643 "ext/standard/var_unserializer.re"
{
long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 802 "ext/standard/var_unserializer.c"
+#line 828 "ext/standard/var_unserializer.c"
yy39:
yych = *++YYCURSOR;
if (yych == '+') goto yy40;
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 589 "ext/standard/var_unserializer.re"
+#line 613 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
//??? TODO: use zend_string* instead of char*
efree(str);
return 1;
}
-#line 853 "ext/standard/var_unserializer.c"
+#line 879 "ext/standard/var_unserializer.c"
yy46:
yych = *++YYCURSOR;
if (yych == '+') goto yy47;
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 562 "ext/standard/var_unserializer.re"
+#line 586 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
ZVAL_STRINGL(rval, str, len);
return 1;
}
-#line 901 "ext/standard/var_unserializer.c"
+#line 927 "ext/standard/var_unserializer.c"
yy53:
yych = *++YYCURSOR;
if (yych <= '/') {
}
yy63:
++YYCURSOR;
-#line 553 "ext/standard/var_unserializer.re"
+#line 577 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
use_double:
ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
return 1;
}
-#line 998 "ext/standard/var_unserializer.c"
+#line 1024 "ext/standard/var_unserializer.c"
yy65:
yych = *++YYCURSOR;
if (yych <= ',') {
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 537 "ext/standard/var_unserializer.re"
+#line 561 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
return 1;
}
-#line 1073 "ext/standard/var_unserializer.c"
+#line 1099 "ext/standard/var_unserializer.c"
yy76:
yych = *++YYCURSOR;
if (yych == 'N') goto yy73;
if (yych <= '9') goto yy79;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 511 "ext/standard/var_unserializer.re"
+#line 535 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
int digits = YYCURSOR - start - 3;
ZVAL_LONG(rval, parse_iv(start + 2));
return 1;
}
-#line 1126 "ext/standard/var_unserializer.c"
+#line 1152 "ext/standard/var_unserializer.c"
yy83:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 505 "ext/standard/var_unserializer.re"
+#line 529 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_BOOL(rval, parse_iv(start + 2));
return 1;
}
-#line 1140 "ext/standard/var_unserializer.c"
+#line 1166 "ext/standard/var_unserializer.c"
yy87:
++YYCURSOR;
-#line 499 "ext/standard/var_unserializer.re"
+#line 523 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_NULL(rval);
return 1;
}
-#line 1149 "ext/standard/var_unserializer.c"
+#line 1175 "ext/standard/var_unserializer.c"
yy89:
yych = *++YYCURSOR;
if (yych <= ',') {
if (yych <= '9') goto yy91;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 476 "ext/standard/var_unserializer.re"
+#line 500 "ext/standard/var_unserializer.re"
{
long id;
if (!var_hash) return 0;
id = parse_iv(start + 2) - 1;
- if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}
return 1;
}
-#line 1195 "ext/standard/var_unserializer.c"
+#line 1221 "ext/standard/var_unserializer.c"
yy95:
yych = *++YYCURSOR;
if (yych <= ',') {
if (yych <= '9') goto yy97;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 451 "ext/standard/var_unserializer.re"
+#line 477 "ext/standard/var_unserializer.re"
{
long id;
if (!var_hash) return 0;
id = parse_iv(start + 2) - 1;
- if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}
- if (!ZVAL_IS_UNDEF(rval)) {
- zval_ptr_dtor(rval);
- }
+ zval_ptr_dtor(rval);
if (Z_ISREF_P(rval_ref)) {
ZVAL_COPY(rval, rval_ref);
} else {
return 1;
}
-#line 1243 "ext/standard/var_unserializer.c"
+#line 1267 "ext/standard/var_unserializer.c"
}
-#line 795 "ext/standard/var_unserializer.re"
+#line 819 "ext/standard/var_unserializer.re"
return 0;
void *next;
} var_entries;
+typedef struct {
+ zval data[VAR_ENTRIES_MAX];
+ long used_slots;
+ void *next;
+} var_dtor_entries;
+
static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
{
var_entries *var_hash = (*var_hashx)->last;
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
{
- var_entries *var_hash = (*var_hashx)->last_dtor;
+ var_dtor_entries *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
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
- var_hash = emalloc(sizeof(var_entries));
+ var_hash = emalloc(sizeof(var_dtor_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
(*var_hashx)->last_dtor = var_hash;
}
- if (Z_REFCOUNTED_P(rval)) Z_ADDREF_P(rval);
- var_hash->data[var_hash->used_slots++] = rval;
+ ZVAL_COPY(&var_hash->data[var_hash->used_slots], rval);
+ var_hash->used_slots++;
}
//???
#if 0
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval *rval)
{
- var_entries *var_hash = (*var_hashx)->last_dtor;
+ var_dtor_entries *var_hash = (*var_hashx)->last_dtor;
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
- var_hash = emalloc(sizeof(var_entries));
+ var_hash = emalloc(sizeof(var_dtor_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
(*var_hashx)->last_dtor = var_hash;
}
- var_hash->data[var_hash->used_slots++] = rval;
+ ZVAL_COPY_VALUE(&var_hash->data[var_hash->used_slots], rval);
+ var_hash->used_slots++;
}
#endif
-static int var_access(php_unserialize_data_t *var_hashx, long id, zval **store)
+PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
+{
+ long i;
+ var_entries *var_hash = (*var_hashx)->first;
+#if VAR_ENTRIES_DBG
+ fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
+#endif
+
+ while (var_hash) {
+ for (i = 0; i < var_hash->used_slots; i++) {
+ if (var_hash->data[i] == ozval) {
+ var_hash->data[i] = nzval;
+ /* do not break here */
+ }
+ }
+ var_hash = var_hash->next;
+ }
+}
+
+static zval *var_access(php_unserialize_data_t *var_hashx, long id)
{
var_entries *var_hash = (*var_hashx)->first;
#if VAR_ENTRIES_DBG
id -= VAR_ENTRIES_MAX;
}
- if (!var_hash) return !SUCCESS;
+ if (!var_hash) return NULL;
- if (id < 0 || id >= var_hash->used_slots) return !SUCCESS;
+ if (id < 0 || id >= var_hash->used_slots) return NULL;
- *store = var_hash->data[id];
-
- return SUCCESS;
+ return var_hash->data[id];
}
PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
void *next;
long i;
var_entries *var_hash = (*var_hashx)->first;
+ var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
#endif
var_hash = next;
}
- var_hash = (*var_hashx)->first_dtor;
-
- while (var_hash) {
- for (i = 0; i < var_hash->used_slots; i++) {
- zval_ptr_dtor(var_hash->data[i]);
+ while (var_dtor_hash) {
+ for (i = 0; i < var_dtor_hash->used_slots; i++) {
+ zval_ptr_dtor(&var_dtor_hash->data[i]);
}
- next = var_hash->next;
- efree(var_hash);
- var_hash = next;
+ next = var_dtor_hash->next;
+ efree(var_dtor_hash);
+ var_dtor_hash = next;
}
}
switch (Z_TYPE(key)) {
case IS_LONG:
if ((old_data = zend_hash_index_find(ht, Z_LVAL(key))) != NULL) {
+ //??? update hash
var_push_dtor(var_hash, old_data);
}
data = zend_hash_index_update(ht, Z_LVAL(key), &d);
break;
case IS_STRING:
if ((old_data = zend_symtable_find(ht, Z_STR(key))) != NULL) {
+ //??? update hash
var_push_dtor(var_hash, old_data);
}
data = zend_symtable_update(ht, Z_STR(key), &d);
zval retval;
zval fname;
+ //??? TODO: resize before
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_P(rval), elements, 1)) {
return 0;
}
if (!var_hash) return 0;
id = parse_iv(start + 2) - 1;
- if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}
- if (!ZVAL_IS_UNDEF(rval)) {
- zval_ptr_dtor(rval);
- }
+ zval_ptr_dtor(rval);
if (Z_ISREF_P(rval_ref)) {
ZVAL_COPY(rval, rval_ref);
} else {
if (!var_hash) return 0;
id = parse_iv(start + 2) - 1;
- if (id == -1 || var_access(var_hash, id, &rval_ref) != SUCCESS) {
+ if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}