php-src/ext/standard/var_unserializer.c
Peter Kokot 8d3f8ca12a Remove unused Git attributes ident
The $Id$ keywords were used in Subversion where they can be substituted
with filename, last revision number change, last changed date, and last
user who changed it.

In Git this functionality is different and can be done with Git attribute
ident. These need to be defined manually for each file in the
.gitattributes file and are afterwards replaced with 40-character
hexadecimal blob object name which is based only on the particular file
contents.

This patch simplifies handling of $Id$ keywords by removing them since
they are not used anymore.
2018-07-25 00:53:25 +02:00

1501 lines
35 KiB
C

/* Generated by re2c 1.0.3 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2018 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Sascha Schumann <sascha@schumann.cx> |
+----------------------------------------------------------------------+
*/
#include "php.h"
#include "ext/standard/php_var.h"
#include "php_incomplete_class.h"
#include "zend_portability.h"
struct php_unserialize_data {
void *first;
void *last;
void *first_dtor;
void *last_dtor;
HashTable *allowed_classes;
};
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;
}
}
PHPAPI HashTable *php_var_unserialize_get_allowed_classes(php_unserialize_data_t d) {
return d->allowed_classes;
}
PHPAPI void php_var_unserialize_set_allowed_classes(php_unserialize_data_t d, HashTable *classes) {
d->allowed_classes = classes;
}
/* {{{ reference-handling for unserializer: var_* */
#define VAR_ENTRIES_MAX 1024
#define VAR_ENTRIES_DBG 0
/* VAR_FLAG used in var_dtor entries to signify an entry on which __wakeup should be called */
#define VAR_WAKEUP_FLAG 1
typedef struct {
zval *data[VAR_ENTRIES_MAX];
zend_long used_slots;
void *next;
} var_entries;
typedef struct {
zval data[VAR_ENTRIES_MAX];
zend_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;
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_P(rval));
#endif
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = emalloc(sizeof(var_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
if (!(*var_hashx)->first) {
(*var_hashx)->first = var_hash;
} else {
((var_entries *) (*var_hashx)->last)->next = var_hash;
}
(*var_hashx)->last = var_hash;
}
var_hash->data[var_hash->used_slots++] = rval;
}
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
{
zval *tmp_var = var_tmp_var(var_hashx);
if (!tmp_var) {
return;
}
ZVAL_COPY(tmp_var, rval);
}
PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
{
var_dtor_entries *var_hash;
if (!var_hashx || !*var_hashx) {
return NULL;
}
var_hash = (*var_hashx)->last_dtor;
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = emalloc(sizeof(var_dtor_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
if (!(*var_hashx)->first_dtor) {
(*var_hashx)->first_dtor = var_hash;
} else {
((var_dtor_entries *) (*var_hashx)->last_dtor)->next = var_hash;
}
(*var_hashx)->last_dtor = var_hash;
}
ZVAL_UNDEF(&var_hash->data[var_hash->used_slots]);
Z_EXTRA(var_hash->data[var_hash->used_slots]) = 0;
return &var_hash->data[var_hash->used_slots++];
}
PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval *nzval)
{
zend_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_P(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, zend_long id)
{
var_entries *var_hash = (*var_hashx)->first;
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
#endif
while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = var_hash->next;
id -= VAR_ENTRIES_MAX;
}
if (!var_hash) return NULL;
if (id < 0 || id >= var_hash->used_slots) return NULL;
return var_hash->data[id];
}
PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
{
void *next;
zend_long i;
var_entries *var_hash = (*var_hashx)->first;
var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor;
zend_bool wakeup_failed = 0;
zval wakeup_name;
ZVAL_UNDEF(&wakeup_name);
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
#endif
while (var_hash) {
next = var_hash->next;
efree_size(var_hash, sizeof(var_entries));
var_hash = next;
}
while (var_dtor_hash) {
for (i = 0; i < var_dtor_hash->used_slots; i++) {
zval *zv = &var_dtor_hash->data[i];
#if VAR_ENTRIES_DBG
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
#endif
/* Perform delayed __wakeup calls */
if (Z_EXTRA_P(zv) == VAR_WAKEUP_FLAG) {
if (!wakeup_failed) {
zval retval;
if (Z_ISUNDEF(wakeup_name)) {
ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1);
}
BG(serialize_lock)++;
if (call_user_function(CG(function_table), zv, &wakeup_name, &retval, 0, 0) == FAILURE || Z_ISUNDEF(retval)) {
wakeup_failed = 1;
GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
}
BG(serialize_lock)--;
zval_ptr_dtor(&retval);
} else {
GC_ADD_FLAGS(Z_OBJ_P(zv), IS_OBJ_DESTRUCTOR_CALLED);
}
}
i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC);
}
next = var_dtor_hash->next;
efree_size(var_dtor_hash, sizeof(var_dtor_entries));
var_dtor_hash = next;
}
zval_ptr_dtor_nogc(&wakeup_name);
}
/* }}} */
static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen)
{
size_t i, j;
zend_string *str = zend_string_safe_alloc(1, len, 0, 0);
unsigned char *end = *(unsigned char **)p+maxlen;
if (end < *p) {
zend_string_efree(str);
return NULL;
}
for (i = 0; i < len; i++) {
if (*p >= end) {
zend_string_efree(str);
return NULL;
}
if (**p != '\\') {
ZSTR_VAL(str)[i] = (char)**p;
} else {
unsigned char ch = 0;
for (j = 0; j < 2; j++) {
(*p)++;
if (**p >= '0' && **p <= '9') {
ch = (ch << 4) + (**p -'0');
} else if (**p >= 'a' && **p <= 'f') {
ch = (ch << 4) + (**p -'a'+10);
} else if (**p >= 'A' && **p <= 'F') {
ch = (ch << 4) + (**p -'A'+10);
} else {
zend_string_efree(str);
return NULL;
}
}
ZSTR_VAL(str)[i] = (char)ch;
}
(*p)++;
}
ZSTR_VAL(str)[i] = 0;
ZSTR_LEN(str) = i;
return str;
}
static inline int unserialize_allowed_class(
zend_string *class_name, php_unserialize_data_t *var_hashx)
{
HashTable *classes = (*var_hashx)->allowed_classes;
zend_string *lcname;
int res;
ALLOCA_FLAG(use_heap)
if(classes == NULL) {
return 1;
}
if(!zend_hash_num_elements(classes)) {
return 0;
}
ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap);
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
res = zend_hash_exists(classes, lcname);
ZSTR_ALLOCA_FREE(lcname, use_heap);
return res;
}
#define YYFILL(n) do { } while (0)
#define YYCTYPE unsigned char
#define YYCURSOR cursor
#define YYLIMIT limit
#define YYMARKER marker
#line 325 "ext/standard/var_unserializer.re"
static inline zend_long parse_iv2(const unsigned char *p, const unsigned char **q)
{
zend_ulong result = 0;
zend_ulong neg = 0;
const unsigned char *start;
if (*p == '-') {
neg = 1;
p++;
} else if (UNEXPECTED(*p == '+')) {
p++;
}
while (UNEXPECTED(*p == '0')) {
p++;
}
start = p;
while (*p >= '0' && *p <= '9') {
result = result * 10 + ((zend_ulong)(*p) - '0');
p++;
}
if (q) {
*q = p;
}
/* number too long or overflow */
if (UNEXPECTED(p - start > MAX_LENGTH_OF_LONG - 1)
|| (SIZEOF_ZEND_LONG == 4
&& UNEXPECTED(p - start == MAX_LENGTH_OF_LONG - 1)
&& UNEXPECTED(*start > '2'))
|| UNEXPECTED(result - neg > ZEND_LONG_MAX)) {
php_error_docref(NULL, E_WARNING, "Numerical result out of range");
return (!neg) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
}
return (!neg) ? (zend_long)result : -(zend_long)result;
}
static inline zend_long parse_iv(const unsigned char *p)
{
return parse_iv2(p, NULL);
}
/* no need to check for length - re2c already did */
static inline size_t parse_uiv(const unsigned char *p)
{
unsigned char cursor;
size_t result = 0;
while (1) {
cursor = *p;
if (cursor >= '0' && cursor <= '9') {
result = result * 10 + (size_t)(cursor - (unsigned char)'0');
} else {
break;
}
p++;
}
return result;
}
#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, int as_key);
static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
{
while (elements-- > 0) {
zval key, *data, d, *old_data;
zend_ulong idx;
ZVAL_UNDEF(&key);
if (!php_var_unserialize_internal(&key, p, max, NULL, 1)) {
zval_ptr_dtor(&key);
return 0;
}
data = NULL;
ZVAL_UNDEF(&d);
if (!objprops) {
if (Z_TYPE(key) == IS_LONG) {
idx = Z_LVAL(key);
numeric_key:
if (UNEXPECTED((old_data = zend_hash_index_find(ht, idx)) != NULL)) {
//??? update hash
var_push_dtor(var_hash, old_data);
data = zend_hash_index_update(ht, idx, &d);
} else {
data = zend_hash_index_add_new(ht, idx, &d);
}
} else if (Z_TYPE(key) == IS_STRING) {
if (UNEXPECTED(ZEND_HANDLE_NUMERIC(Z_STR(key), idx))) {
goto numeric_key;
}
if (UNEXPECTED((old_data = zend_hash_find(ht, Z_STR(key))) != NULL)) {
//??? update hash
var_push_dtor(var_hash, old_data);
data = zend_hash_update(ht, Z_STR(key), &d);
} else {
data = zend_hash_add_new(ht, Z_STR(key), &d);
}
} else {
zval_ptr_dtor(&key);
return 0;
}
} else {
if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
string_key:
if (Z_TYPE_P(rval) == IS_OBJECT
&& zend_hash_num_elements(&Z_OBJCE_P(rval)->properties_info) > 0) {
zend_property_info *existing_propinfo;
zend_string *new_key;
const char *unmangled_class = NULL;
const char *unmangled_prop;
size_t unmangled_prop_len;
zend_string *unmangled;
if (UNEXPECTED(zend_unmangle_property_name_ex(Z_STR(key), &unmangled_class, &unmangled_prop, &unmangled_prop_len) == FAILURE)) {
zval_ptr_dtor(&key);
return 0;
}
unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);
existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled);
if ((unmangled_class == NULL || !strcmp(unmangled_class, "*") || !strcasecmp(unmangled_class, ZSTR_VAL(Z_OBJCE_P(rval)->name)))
&& (existing_propinfo != 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_ex(unmangled, 0);
} 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_ex(unmangled, 0);
} else {
ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
new_key = unmangled;
}
zval_ptr_dtor_str(&key);
ZVAL_STR(&key, new_key);
} else {
zend_string_release_ex(unmangled, 0);
}
}
if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
if (Z_TYPE_P(old_data) == IS_INDIRECT) {
old_data = Z_INDIRECT_P(old_data);
}
var_push_dtor(var_hash, old_data);
data = zend_hash_update_ind(ht, Z_STR(key), &d);
} else {
data = zend_hash_add_new(ht, Z_STR(key), &d);
}
} else if (Z_TYPE(key) == IS_LONG) {
/* object properties should include no integers */
convert_to_string(&key);
goto string_key;
} else {
zval_ptr_dtor(&key);
return 0;
}
}
if (!php_var_unserialize_internal(data, p, max, var_hash, 0)) {
zval_ptr_dtor(&key);
return 0;
}
var_push_dtor(var_hash, data);
zval_ptr_dtor_str(&key);
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
(*p)--;
return 0;
}
}
return 1;
}
static inline int finish_nested_data(UNSERIALIZE_PARAMETER)
{
if (*p >= max || **p != '}') {
return 0;
}
(*p)++;
return 1;
}
static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
{
zend_long datalen;
datalen = parse_iv2((*p) + 2, p);
(*p) += 2;
if (datalen < 0 || (max - (*p)) <= datalen) {
zend_error(E_WARNING, "Insufficient data for unserializing - " ZEND_LONG_FMT " required, " ZEND_LONG_FMT " present", datalen, (zend_long)(max - (*p)));
return 0;
}
/* Check that '}' is present before calling ce->unserialize() to mitigate issues
* with unserialize reading past the end of the passed buffer if the string is not
* appropriately terminated (usually NUL terminated, but '}' is also sufficient.) */
if ((*p)[datalen] != '}') {
return 0;
}
if (ce->unserialize == NULL) {
zend_error(E_WARNING, "Class %s has no unserializer", ZSTR_VAL(ce->name));
object_init_ex(rval, ce);
} else if (ce->unserialize(rval, ce, (const unsigned char*)*p, datalen, (zend_unserialize_data *)var_hash) != SUCCESS) {
return 0;
}
(*p) += datalen + 1; /* +1 for '}' */
return 1;
}
static inline zend_long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
{
zend_long elements;
if( *p >= max - 2) {
zend_error(E_WARNING, "Bad unserialize data");
return -1;
}
elements = parse_iv2((*p) + 2, p);
(*p) += 2;
if (ce->serialize == NULL) {
object_init_ex(rval, ce);
} else {
/* If this class implements Serializable, it should not land here but in object_custom(). The passed string
obviously doesn't descend from the regular serializer. */
zend_error(E_WARNING, "Erroneous data format for unserializing '%s'", ZSTR_VAL(ce->name));
return -1;
}
return elements;
}
#ifdef PHP_WIN32
# pragma optimize("", off)
#endif
static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
{
HashTable *ht;
zend_bool has_wakeup;
if (Z_TYPE_P(rval) != IS_OBJECT) {
return 0;
}
has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
&& zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
ht = Z_OBJPROP_P(rval);
if (elements >= (zend_long)(HT_MAX_SIZE - zend_hash_num_elements(ht))) {
return 0;
}
zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, HT_FLAGS(ht) & HASH_FLAG_PACKED);
if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
if (has_wakeup) {
ZVAL_DEREF(rval);
GC_ADD_FLAGS(Z_OBJ_P(rval), IS_OBJ_DESTRUCTOR_CALLED);
}
return 0;
}
ZVAL_DEREF(rval);
if (has_wakeup) {
/* Delay __wakeup call until end of serialization */
zval *wakeup_var = var_tmp_var(var_hash);
ZVAL_COPY(wakeup_var, rval);
Z_EXTRA_P(wakeup_var) = VAR_WAKEUP_FLAG;
}
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
#ifdef PHP_WIN32
# pragma optimize("", on)
#endif
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
var_entries *orig_var_entries = (*var_hash)->last;
zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
int result;
result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU, 0);
if (!result) {
/* If the unserialization failed, mark all elements that have been added to var_hash
* as NULL. This will forbid their use by other unserialize() calls in the same
* unserialization context. */
var_entries *e = orig_var_entries;
zend_long s = orig_used_slots;
while (e) {
for (; s < e->used_slots; s++) {
e->data[s] = NULL;
}
e = e->next;
s = 0;
}
}
return result;
}
static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key)
{
const unsigned char *cursor, *limit, *marker, *start;
zval *rval_ref;
limit = max;
cursor = *p;
if (YYCURSOR >= YYLIMIT) {
return 0;
}
if (var_hash && (*p)[0] != 'R') {
var_push(var_hash, rval);
}
start = cursor;
#line 679 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
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 yy4;
case 'N': goto yy5;
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 yy13;
case 's': goto yy14;
case '}': goto yy15;
default: goto yy2;
}
yy2:
++YYCURSOR;
yy3:
#line 1078 "ext/standard/var_unserializer.re"
{ return 0; }
#line 739 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy17;
goto yy3;
yy5:
yych = *++YYCURSOR;
if (yych == ';') goto yy19;
goto yy3;
yy6:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy21;
goto yy3;
yy7:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy22;
goto yy3;
yy8:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy23;
goto yy3;
yy9:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy24;
goto yy3;
yy10:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy25;
goto yy3;
yy11:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy26;
goto yy3;
yy12:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy27;
goto yy3;
yy13:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy28;
goto yy3;
yy14:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy29;
goto yy3;
yy15:
++YYCURSOR;
#line 1072 "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 792 "ext/standard/var_unserializer.c"
yy17:
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
goto yy30;
}
yy18:
YYCURSOR = YYMARKER;
goto yy3;
yy19:
++YYCURSOR;
#line 733 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_NULL(rval);
return 1;
}
#line 809 "ext/standard/var_unserializer.c"
yy21:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy32;
goto yy18;
yy22:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy34;
goto yy18;
yy23:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy36;
goto yy18;
yy24:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '0') goto yy38;
if (yych <= '1') goto yy39;
goto yy18;
yy25:
yych = *++YYCURSOR;
if (yych <= '/') {
if (yych <= ',') {
if (yych == '+') goto yy40;
goto yy18;
} else {
if (yych <= '-') goto yy41;
if (yych <= '.') goto yy42;
goto yy18;
}
} else {
if (yych <= 'I') {
if (yych <= '9') goto yy43;
if (yych <= 'H') goto yy18;
goto yy45;
} else {
if (yych == 'N') goto yy46;
goto yy18;
}
}
yy26:
yych = *++YYCURSOR;
if (yych <= ',') {
if (yych == '+') goto yy47;
goto yy18;
} else {
if (yych <= '-') goto yy47;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy48;
goto yy18;
}
yy27:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy50;
goto yy18;
yy28:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy52;
goto yy18;
yy29:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy54;
goto yy18;
yy30:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yybm[0+yych] & 128) {
goto yy30;
}
if (yych <= '/') goto yy18;
if (yych <= ':') goto yy56;
goto yy18;
yy32:
++YYCURSOR;
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy32;
if (yych == ';') goto yy57;
goto yy18;
yy34:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy34;
if (yych <= ':') goto yy59;
goto yy18;
yy36:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy36;
if (yych <= ':') goto yy60;
goto yy18;
yy38:
yych = *++YYCURSOR;
if (yych == ';') goto yy61;
goto yy18;
yy39:
yych = *++YYCURSOR;
if (yych == ';') goto yy63;
goto yy18;
yy40:
yych = *++YYCURSOR;
if (yych == '.') goto yy42;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy43;
goto yy18;
yy41:
yych = *++YYCURSOR;
if (yych <= '/') {
if (yych != '.') goto yy18;
} else {
if (yych <= '9') goto yy43;
if (yych == 'I') goto yy45;
goto yy18;
}
yy42:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy65;
goto yy18;
yy43:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
if (yych <= ':') {
if (yych <= '.') {
if (yych <= '-') goto yy18;
goto yy65;
} else {
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy43;
goto yy18;
}
} else {
if (yych <= 'E') {
if (yych <= ';') goto yy67;
if (yych <= 'D') goto yy18;
goto yy69;
} else {
if (yych == 'e') goto yy69;
goto yy18;
}
}
yy45:
yych = *++YYCURSOR;
if (yych == 'N') goto yy70;
goto yy18;
yy46:
yych = *++YYCURSOR;
if (yych == 'A') goto yy71;
goto yy18;
yy47:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych >= ':') goto yy18;
yy48:
++YYCURSOR;
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy48;
if (yych == ';') goto yy72;
goto yy18;
yy50:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy50;
if (yych <= ':') goto yy74;
goto yy18;
yy52:
++YYCURSOR;
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy52;
if (yych == ';') goto yy75;
goto yy18;
yy54:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy54;
if (yych <= ':') goto yy77;
goto yy18;
yy56:
yych = *++YYCURSOR;
if (yych == '"') goto yy78;
goto yy18;
yy57:
++YYCURSOR;
#line 683 "ext/standard/var_unserializer.re"
{
zend_long id;
*p = YYCURSOR;
if (!var_hash) return 0;
id = parse_uiv(start + 2) - 1;
if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}
if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) {
return 0;
}
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 1038 "ext/standard/var_unserializer.c"
yy59:
yych = *++YYCURSOR;
if (yych == '"') goto yy80;
goto yy18;
yy60:
yych = *++YYCURSOR;
if (yych == '{') goto yy82;
goto yy18;
yy61:
++YYCURSOR;
#line 739 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_FALSE(rval);
return 1;
}
#line 1055 "ext/standard/var_unserializer.c"
yy63:
++YYCURSOR;
#line 745 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
ZVAL_TRUE(rval);
return 1;
}
#line 1064 "ext/standard/var_unserializer.c"
yy65:
++YYCURSOR;
if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
yych = *YYCURSOR;
if (yych <= ';') {
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy65;
if (yych <= ':') goto yy18;
} else {
if (yych <= 'E') {
if (yych <= 'D') goto yy18;
goto yy69;
} else {
if (yych == 'e') goto yy69;
goto yy18;
}
}
yy67:
++YYCURSOR;
#line 793 "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 1093 "ext/standard/var_unserializer.c"
yy69:
yych = *++YYCURSOR;
if (yych <= ',') {
if (yych == '+') goto yy84;
goto yy18;
} else {
if (yych <= '-') goto yy84;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy85;
goto yy18;
}
yy70:
yych = *++YYCURSOR;
if (yych == 'F') goto yy87;
goto yy18;
yy71:
yych = *++YYCURSOR;
if (yych == 'N') goto yy87;
goto yy18;
yy72:
++YYCURSOR;
#line 751 "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 1141 "ext/standard/var_unserializer.c"
yy74:
yych = *++YYCURSOR;
if (yych == '"') goto yy88;
goto yy18;
yy75:
++YYCURSOR;
#line 708 "ext/standard/var_unserializer.re"
{
zend_long id;
*p = YYCURSOR;
if (!var_hash) return 0;
id = parse_uiv(start + 2) - 1;
if (id == -1 || (rval_ref = var_access(var_hash, id)) == NULL) {
return 0;
}
if (rval_ref == rval) {
return 0;
}
ZVAL_DEREF(rval_ref);
if (Z_TYPE_P(rval_ref) != IS_OBJECT) {
return 0;
}
ZVAL_COPY(rval, rval_ref);
return 1;
}
#line 1173 "ext/standard/var_unserializer.c"
yy77:
yych = *++YYCURSOR;
if (yych == '"') goto yy90;
goto yy18;
yy78:
++YYCURSOR;
#line 920 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
zend_long elements;
char *str;
zend_string *class_name;
zend_class_entry *ce;
int incomplete_class = 0;
int custom_object = 0;
zval user_func;
zval retval;
zval args[1];
if (!var_hash) return 0;
if (*start == 'C') {
custom_object = 1;
}
len2 = len = parse_uiv(start + 2);
maxlen = max - YYCURSOR;
if (maxlen < len || len == 0) {
*p = start + 2;
return 0;
}
str = (char*)YYCURSOR;
YYCURSOR += len;
if (*(YYCURSOR) != '"') {
*p = YYCURSOR;
return 0;
}
if (*(YYCURSOR+1) != ':') {
*p = YYCURSOR+1;
return 0;
}
len3 = strspn(str, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\\");
if (len3 != len)
{
*p = YYCURSOR + len3 - len;
return 0;
}
class_name = zend_string_init(str, len, 0);
do {
if(!unserialize_allowed_class(class_name, var_hash)) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
break;
}
/* Try to find class directly */
BG(serialize_lock)++;
ce = zend_lookup_class(class_name);
if (ce) {
BG(serialize_lock)--;
if (EG(exception)) {
zend_string_release_ex(class_name, 0);
return 0;
}
break;
}
BG(serialize_lock)--;
if (EG(exception)) {
zend_string_release_ex(class_name, 0);
return 0;
}
/* Check for unserialize callback */
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
break;
}
/* Call unserialize callback */
ZVAL_STRING(&user_func, PG(unserialize_callback_func));
ZVAL_STR_COPY(&args[0], class_name);
BG(serialize_lock)++;
if (call_user_function_ex(CG(function_table), NULL, &user_func, &retval, 1, args, 0, NULL) != SUCCESS) {
BG(serialize_lock)--;
if (EG(exception)) {
zend_string_release_ex(class_name, 0);
zval_ptr_dtor(&user_func);
zval_ptr_dtor(&args[0]);
return 0;
}
php_error_docref(NULL, E_WARNING, "defined (%s) but not found", Z_STRVAL(user_func));
incomplete_class = 1;
ce = PHP_IC_ENTRY;
zval_ptr_dtor(&user_func);
zval_ptr_dtor(&args[0]);
break;
}
BG(serialize_lock)--;
zval_ptr_dtor(&retval);
if (EG(exception)) {
zend_string_release_ex(class_name, 0);
zval_ptr_dtor(&user_func);
zval_ptr_dtor(&args[0]);
return 0;
}
/* The callback function may have defined the class */
BG(serialize_lock)++;
if ((ce = zend_lookup_class(class_name)) == NULL) {
php_error_docref(NULL, E_WARNING, "Function %s() hasn't defined the class it was called for", Z_STRVAL(user_func));
incomplete_class = 1;
ce = PHP_IC_ENTRY;
}
BG(serialize_lock)--;
zval_ptr_dtor(&user_func);
zval_ptr_dtor(&args[0]);
break;
} while (1);
*p = YYCURSOR;
if (custom_object) {
int ret;
ret = object_custom(UNSERIALIZE_PASSTHRU, ce);
if (ret && incomplete_class) {
php_store_class_name(rval, ZSTR_VAL(class_name), len2);
}
zend_string_release_ex(class_name, 0);
return ret;
}
elements = object_common1(UNSERIALIZE_PASSTHRU, ce);
if (elements < 0) {
zend_string_release_ex(class_name, 0);
return 0;
}
if (incomplete_class) {
php_store_class_name(rval, ZSTR_VAL(class_name), len2);
}
zend_string_release_ex(class_name, 0);
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
#line 1332 "ext/standard/var_unserializer.c"
yy80:
++YYCURSOR;
#line 842 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
zend_string *str;
len = parse_uiv(start + 2);
maxlen = max - YYCURSOR;
if (maxlen < len) {
*p = start + 2;
return 0;
}
if ((str = unserialize_str(&YYCURSOR, len, maxlen)) == NULL) {
return 0;
}
if (*(YYCURSOR) != '"') {
zend_string_efree(str);
*p = YYCURSOR;
return 0;
}
if (*(YYCURSOR + 1) != ';') {
efree(str);
*p = YYCURSOR + 1;
return 0;
}
YYCURSOR += 2;
*p = YYCURSOR;
ZVAL_STR(rval, str);
return 1;
}
#line 1369 "ext/standard/var_unserializer.c"
yy82:
++YYCURSOR;
#line 876 "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 || elements >= HT_MAX_SIZE) {
return 0;
}
if (elements) {
array_init_size(rval, 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_mixed(Z_ARRVAL_P(rval));
} else {
ZVAL_EMPTY_ARRAY(rval);
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
/* The array may contain references to itself, in which case we'll be modifying an
* rc>1 array. This is okay, since the array is, ostensibly, only visible to
* unserialize (in practice unserialization handlers also see it). Ideally we should
* prohibit "r:" references to non-objects, as we only generate them for objects. */
HT_ALLOW_COW_VIOLATION(Z_ARRVAL_P(rval));
if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
return 0;
}
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
#line 1405 "ext/standard/var_unserializer.c"
yy84:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
if (yych >= ':') goto yy18;
yy85:
++YYCURSOR;
if (YYLIMIT <= YYCURSOR) YYFILL(1);
yych = *YYCURSOR;
if (yych <= '/') goto yy18;
if (yych <= '9') goto yy85;
if (yych == ';') goto yy67;
goto yy18;
yy87:
yych = *++YYCURSOR;
if (yych == ';') goto yy92;
goto yy18;
yy88:
++YYCURSOR;
#line 909 "ext/standard/var_unserializer.re"
{
zend_long elements;
if (!var_hash) return 0;
elements = object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR);
if (elements < 0 || elements >= HT_MAX_SIZE) {
return 0;
}
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
#line 1435 "ext/standard/var_unserializer.c"
yy90:
++YYCURSOR;
#line 802 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
len = parse_uiv(start + 2);
maxlen = max - YYCURSOR;
if (maxlen < len) {
*p = start + 2;
return 0;
}
str = (char*)YYCURSOR;
YYCURSOR += len;
if (*(YYCURSOR) != '"') {
*p = YYCURSOR;
return 0;
}
if (*(YYCURSOR + 1) != ';') {
*p = YYCURSOR + 1;
return 0;
}
YYCURSOR += 2;
*p = YYCURSOR;
if (len == 0) {
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 1478 "ext/standard/var_unserializer.c"
yy92:
++YYCURSOR;
#line 777 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
if (!strncmp((char*)start + 2, "NAN", 3)) {
ZVAL_DOUBLE(rval, ZEND_NAN);
} else if (!strncmp((char*)start + 2, "INF", 3)) {
ZVAL_DOUBLE(rval, ZEND_INFINITY);
} else if (!strncmp((char*)start + 2, "-INF", 4)) {
ZVAL_DOUBLE(rval, -ZEND_INFINITY);
} else {
ZVAL_NULL(rval);
}
return 1;
}
#line 1497 "ext/standard/var_unserializer.c"
}
#line 1080 "ext/standard/var_unserializer.re"
return 0;
}