Skip to content

Commit db30e0c

Browse files
committed
Improve unserialize()
1 parent 71f430c commit db30e0c

File tree

1 file changed

+38
-38
lines changed

1 file changed

+38
-38
lines changed

ext/standard/var_unserializer.re

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,44 @@
2121
#include "php_incomplete_class.h"
2222
#include "zend_portability.h"
2323

24+
/* {{{ reference-handling for unserializer: var_* */
25+
#define VAR_ENTRIES_MAX 1018 /* 1024 - offsetof(php_unserialize_data, entries) / sizeof(void*) */
26+
#define VAR_DTOR_ENTRIES_MAX 255 /* 256 - offsetof(var_dtor_entries, data) / sizeof(zval) */
27+
#define VAR_ENTRIES_DBG 0
28+
29+
/* VAR_FLAG used in var_dtor entries to signify an entry on which __wakeup should be called */
30+
#define VAR_WAKEUP_FLAG 1
31+
32+
typedef struct {
33+
zend_long used_slots;
34+
void *next;
35+
zval *data[VAR_ENTRIES_MAX];
36+
} var_entries;
37+
38+
typedef struct {
39+
zend_long used_slots;
40+
void *next;
41+
zval data[VAR_ENTRIES_MAX];
42+
} var_dtor_entries;
43+
2444
struct php_unserialize_data {
25-
void *first;
26-
void *last;
27-
void *first_dtor;
28-
void *last_dtor;
29-
HashTable *allowed_classes;
45+
var_entries *last;
46+
var_dtor_entries *first_dtor;
47+
var_dtor_entries *last_dtor;
48+
HashTable *allowed_classes;
49+
var_entries entries;
3050
};
3151

3252
PHPAPI php_unserialize_data_t php_var_unserialize_init() {
3353
php_unserialize_data_t d;
3454
/* fprintf(stderr, "UNSERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */
3555
if (BG(serialize_lock) || !BG(unserialize).level) {
36-
d = ecalloc(1, sizeof(struct php_unserialize_data));
56+
d = emalloc(sizeof(struct php_unserialize_data));
57+
d->last = &d->entries;
58+
d->first_dtor = d->last_dtor = NULL;
59+
d->allowed_classes = NULL;
60+
d->entries.used_slots = 0;
61+
d->entries.next = NULL;
3762
if (!BG(serialize_lock)) {
3863
BG(unserialize).data = d;
3964
BG(unserialize).level = 1;
@@ -63,44 +88,19 @@ PHPAPI void php_var_unserialize_set_allowed_classes(php_unserialize_data_t d, Ha
6388
d->allowed_classes = classes;
6489
}
6590

66-
67-
/* {{{ reference-handling for unserializer: var_* */
68-
#define VAR_ENTRIES_MAX 1024
69-
#define VAR_ENTRIES_DBG 0
70-
71-
/* VAR_FLAG used in var_dtor entries to signify an entry on which __wakeup should be called */
72-
#define VAR_WAKEUP_FLAG 1
73-
74-
typedef struct {
75-
zval *data[VAR_ENTRIES_MAX];
76-
zend_long used_slots;
77-
void *next;
78-
} var_entries;
79-
80-
typedef struct {
81-
zval data[VAR_ENTRIES_MAX];
82-
zend_long used_slots;
83-
void *next;
84-
} var_dtor_entries;
85-
8691
static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
8792
{
8893
var_entries *var_hash = (*var_hashx)->last;
8994
#if VAR_ENTRIES_DBG
9095
fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval));
9196
#endif
9297

93-
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
98+
if (var_hash->used_slots == VAR_ENTRIES_MAX) {
9499
var_hash = emalloc(sizeof(var_entries));
95100
var_hash->used_slots = 0;
96101
var_hash->next = 0;
97102

98-
if (!(*var_hashx)->first) {
99-
(*var_hashx)->first = var_hash;
100-
} else {
101-
((var_entries *) (*var_hashx)->last)->next = var_hash;
102-
}
103-
103+
(*var_hashx)->last->next = var_hash;
104104
(*var_hashx)->last = var_hash;
105105
}
106106

@@ -127,15 +127,15 @@ PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
127127
}
128128

129129
var_hash = (*var_hashx)->last_dtor;
130-
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
130+
if (!var_hash || var_hash->used_slots == VAR_DTOR_ENTRIES_MAX) {
131131
var_hash = emalloc(sizeof(var_dtor_entries));
132132
var_hash->used_slots = 0;
133133
var_hash->next = 0;
134134

135135
if (!(*var_hashx)->first_dtor) {
136136
(*var_hashx)->first_dtor = var_hash;
137137
} else {
138-
((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
138+
(*var_hashx)->last_dtor->next = var_hash;
139139
}
140140

141141
(*var_hashx)->last_dtor = var_hash;
@@ -148,7 +148,7 @@ PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
148148
PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
149149
{
150150
zend_long i;
151-
var_entries *var_hash = (*var_hashx)->first;
151+
var_entries *var_hash = &(*var_hashx)->entries;
152152
#if VAR_ENTRIES_DBG
153153
fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(nzval));
154154
#endif
@@ -166,7 +166,7 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nz
166166

167167
static zval *var_access(php_unserialize_data_t *var_hashx, zend_long id)
168168
{
169-
var_entries *var_hash = (*var_hashx)->first;
169+
var_entries *var_hash = &(*var_hashx)->entries;
170170
#if VAR_ENTRIES_DBG
171171
fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
172172
#endif
@@ -187,7 +187,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
187187
{
188188
void *next;
189189
zend_long i;
190-
var_entries *var_hash = (*var_hashx)->first;
190+
var_entries *var_hash = (*var_hashx)->entries.next;
191191
var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
192192
zend_bool wakeup_failed = 0;
193193
zval wakeup_name;

0 commit comments

Comments
 (0)