2015-05-07 04:46:49 +08:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Zend OPcache |
|
|
|
|
+----------------------------------------------------------------------+
|
2019-02-05 15:33:28 +08:00
|
|
|
| Copyright (c) The PHP Group |
|
2015-05-07 04:46:49 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| 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. |
|
|
|
|
+----------------------------------------------------------------------+
|
2018-11-02 00:30:28 +08:00
|
|
|
| Authors: Dmitry Stogov <dmitry@php.net> |
|
2015-05-07 04:46:49 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zend.h"
|
|
|
|
#include "zend_virtual_cwd.h"
|
|
|
|
#include "zend_compile.h"
|
|
|
|
#include "zend_vm.h"
|
2015-11-04 18:59:30 +08:00
|
|
|
#include "zend_interfaces.h"
|
2020-05-25 02:57:00 +08:00
|
|
|
#include "zend_attributes.h"
|
2020-07-17 07:31:10 +08:00
|
|
|
#include "zend_system_id.h"
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
#include "php.h"
|
2018-03-05 22:16:55 +08:00
|
|
|
#ifdef ZEND_WIN32
|
|
|
|
#include "ext/standard/md5.h"
|
|
|
|
#endif
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
#include "ZendAccelerator.h"
|
|
|
|
#include "zend_file_cache.h"
|
|
|
|
#include "zend_shared_alloc.h"
|
|
|
|
#include "zend_accelerator_util_funcs.h"
|
|
|
|
#include "zend_accelerator_hash.h"
|
|
|
|
|
2020-05-18 15:23:06 +08:00
|
|
|
#if HAVE_JIT
|
|
|
|
#include "jit/zend_jit.h"
|
|
|
|
#endif
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2015-11-07 22:15:19 +08:00
|
|
|
#if HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
#ifdef HAVE_SYS_UIO_H
|
|
|
|
# include <sys/uio.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_FILE_H
|
|
|
|
# include <sys/file.h>
|
|
|
|
#endif
|
|
|
|
|
2019-07-01 17:02:31 +08:00
|
|
|
#if __has_feature(memory_sanitizer)
|
|
|
|
# include <sanitizer/msan_interface.h>
|
|
|
|
#endif
|
|
|
|
|
2018-07-14 18:51:37 +08:00
|
|
|
#ifndef ZEND_WIN32
|
|
|
|
#define zend_file_cache_unlink unlink
|
|
|
|
#define zend_file_cache_open open
|
|
|
|
#else
|
|
|
|
#define zend_file_cache_unlink php_win32_ioutil_unlink
|
|
|
|
#define zend_file_cache_open php_win32_ioutil_open
|
|
|
|
#endif
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
#ifdef ZEND_WIN32
|
|
|
|
# define LOCK_SH 0
|
|
|
|
# define LOCK_EX 1
|
|
|
|
# define LOCK_UN 2
|
|
|
|
static int zend_file_cache_flock(int fd, int op)
|
|
|
|
{
|
|
|
|
OVERLAPPED offset = {0,0,0,0,NULL};
|
|
|
|
if (op == LOCK_EX) {
|
|
|
|
if (LockFileEx((HANDLE)_get_osfhandle(fd),
|
|
|
|
LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset) == TRUE) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (op == LOCK_SH) {
|
|
|
|
if (LockFileEx((HANDLE)_get_osfhandle(fd),
|
|
|
|
0, 0, 1, 0, &offset) == TRUE) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (op == LOCK_UN) {
|
|
|
|
if (UnlockFileEx((HANDLE)_get_osfhandle(fd),
|
|
|
|
0, 1, 0, &offset) == TRUE) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#elif defined(HAVE_FLOCK)
|
|
|
|
# define zend_file_cache_flock flock
|
|
|
|
#else
|
|
|
|
# define LOCK_SH 0
|
|
|
|
# define LOCK_EX 1
|
|
|
|
# define LOCK_UN 2
|
|
|
|
static int zend_file_cache_flock(int fd, int type)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef O_BINARY
|
|
|
|
# define O_BINARY 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define SUFFIX ".bin"
|
|
|
|
|
|
|
|
#define IS_SERIALIZED_INTERNED(ptr) \
|
|
|
|
((size_t)(ptr) & Z_UL(1))
|
2018-04-27 22:58:30 +08:00
|
|
|
|
|
|
|
/* Allowing == here to account for a potential empty allocation at the end of the memory */
|
2015-05-07 04:46:49 +08:00
|
|
|
#define IS_SERIALIZED(ptr) \
|
2018-04-27 22:58:30 +08:00
|
|
|
((char*)(ptr) <= (char*)script->size)
|
2015-05-07 04:46:49 +08:00
|
|
|
#define IS_UNSERIALIZED(ptr) \
|
2018-04-28 18:26:32 +08:00
|
|
|
(((char*)(ptr) >= (char*)script->mem && (char*)(ptr) < (char*)script->mem + script->size) || \
|
|
|
|
IS_ACCEL_INTERNED(ptr))
|
2015-05-07 04:46:49 +08:00
|
|
|
#define SERIALIZE_PTR(ptr) do { \
|
2015-05-07 16:36:01 +08:00
|
|
|
if (ptr) { \
|
2018-04-28 18:26:32 +08:00
|
|
|
ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
|
2015-05-07 16:36:01 +08:00
|
|
|
(ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#define UNSERIALIZE_PTR(ptr) do { \
|
|
|
|
if (ptr) { \
|
|
|
|
ZEND_ASSERT(IS_SERIALIZED(ptr)); \
|
|
|
|
(ptr) = (void*)((char*)buf + (size_t)(ptr)); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#define SERIALIZE_STR(ptr) do { \
|
2015-05-07 04:46:49 +08:00
|
|
|
if (ptr) { \
|
|
|
|
if (IS_ACCEL_INTERNED(ptr)) { \
|
|
|
|
(ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \
|
|
|
|
} else { \
|
|
|
|
ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
|
2015-05-12 18:45:52 +08:00
|
|
|
/* script->corrupted shows if the script in SHM or not */ \
|
|
|
|
if (EXPECTED(script->corrupted)) { \
|
2018-02-28 05:52:12 +08:00
|
|
|
GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
|
|
|
|
GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
|
2015-05-12 18:45:52 +08:00
|
|
|
} \
|
2015-05-07 04:46:49 +08:00
|
|
|
(ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2015-05-07 16:36:01 +08:00
|
|
|
#define UNSERIALIZE_STR(ptr) do { \
|
2015-05-07 04:46:49 +08:00
|
|
|
if (ptr) { \
|
|
|
|
if (IS_SERIALIZED_INTERNED(ptr)) { \
|
2015-05-21 04:33:55 +08:00
|
|
|
(ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), !script->corrupted); \
|
2015-05-07 04:46:49 +08:00
|
|
|
} else { \
|
|
|
|
ZEND_ASSERT(IS_SERIALIZED(ptr)); \
|
|
|
|
(ptr) = (void*)((char*)buf + (size_t)(ptr)); \
|
2016-02-25 04:46:11 +08:00
|
|
|
/* script->corrupted shows if the script in SHM or not */ \
|
|
|
|
if (EXPECTED(!script->corrupted)) { \
|
2018-02-28 05:52:12 +08:00
|
|
|
GC_ADD_FLAGS(ptr, IS_STR_INTERNED | IS_STR_PERMANENT); \
|
2016-02-25 04:46:11 +08:00
|
|
|
} else { \
|
2018-02-28 05:52:12 +08:00
|
|
|
GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
|
|
|
|
GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
|
2016-02-25 04:46:11 +08:00
|
|
|
} \
|
2015-05-07 04:46:49 +08:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2020-05-25 02:57:00 +08:00
|
|
|
#define SERIALIZE_ATTRIBUTES(attributes) do { \
|
|
|
|
if ((attributes) && !IS_SERIALIZED(attributes)) { \
|
|
|
|
HashTable *ht; \
|
|
|
|
SERIALIZE_PTR(attributes); \
|
|
|
|
ht = (attributes); \
|
|
|
|
UNSERIALIZE_PTR(ht); \
|
|
|
|
zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_attribute); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define UNSERIALIZE_ATTRIBUTES(attributes) do { \
|
|
|
|
if ((attributes) && !IS_UNSERIALIZED(attributes)) { \
|
|
|
|
HashTable *ht; \
|
|
|
|
UNSERIALIZE_PTR(attributes); \
|
|
|
|
ht = (attributes); \
|
|
|
|
zend_file_cache_unserialize_hash(ht, script, buf, zend_file_cache_unserialize_attribute, NULL); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
|
|
|
|
{HT_INVALID_IDX, HT_INVALID_IDX};
|
|
|
|
|
|
|
|
typedef struct _zend_file_cache_metainfo {
|
|
|
|
char magic[8];
|
|
|
|
char system_id[32];
|
|
|
|
size_t mem_size;
|
|
|
|
size_t str_size;
|
|
|
|
size_t script_offset;
|
|
|
|
accel_time_t timestamp;
|
|
|
|
uint32_t checksum;
|
|
|
|
} zend_file_cache_metainfo;
|
|
|
|
|
|
|
|
static int zend_file_cache_mkdir(char *filename, size_t start)
|
|
|
|
{
|
|
|
|
char *s = filename + start;
|
|
|
|
|
|
|
|
while (*s) {
|
|
|
|
if (IS_SLASH(*s)) {
|
|
|
|
char old = *s;
|
|
|
|
*s = '\000';
|
2018-07-11 20:28:57 +08:00
|
|
|
#ifndef ZEND_WIN32
|
2015-05-07 04:46:49 +08:00
|
|
|
if (mkdir(filename, S_IRWXU) < 0 && errno != EEXIST) {
|
2018-07-11 20:28:57 +08:00
|
|
|
#else
|
|
|
|
if (php_win32_ioutil_mkdir(filename, 0700) < 0 && errno != EEXIST) {
|
|
|
|
#endif
|
2015-05-07 04:46:49 +08:00
|
|
|
*s = old;
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
*s = old;
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void (*serialize_callback_t)(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf);
|
|
|
|
|
|
|
|
typedef void (*unserialize_callback_t)(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf);
|
|
|
|
|
|
|
|
static void zend_file_cache_serialize_zval(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf);
|
|
|
|
static void zend_file_cache_unserialize_zval(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf);
|
|
|
|
|
|
|
|
static void *zend_file_cache_serialize_interned(zend_string *str,
|
|
|
|
zend_file_cache_metainfo *info)
|
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
/* check if the same interned string was already stored */
|
|
|
|
ret = zend_shared_alloc_get_xlat_entry(str);
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-29 21:44:54 +08:00
|
|
|
len = ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str)));
|
2015-05-07 04:46:49 +08:00
|
|
|
ret = (void*)(info->str_size | Z_UL(1));
|
|
|
|
zend_shared_alloc_register_xlat_entry(str, ret);
|
2015-06-30 09:05:24 +08:00
|
|
|
if (info->str_size + len > ZSTR_LEN((zend_string*)ZCG(mem))) {
|
2015-05-07 04:46:49 +08:00
|
|
|
size_t new_len = info->str_size + len;
|
|
|
|
ZCG(mem) = (void*)zend_string_realloc(
|
|
|
|
(zend_string*)ZCG(mem),
|
2015-06-29 21:44:54 +08:00
|
|
|
((_ZSTR_HEADER_SIZE + 1 + new_len + 4095) & ~0xfff) - (_ZSTR_HEADER_SIZE + 1),
|
2015-05-07 04:46:49 +08:00
|
|
|
0);
|
|
|
|
}
|
2015-06-30 09:05:24 +08:00
|
|
|
memcpy(ZSTR_VAL((zend_string*)ZCG(mem)) + info->str_size, str, len);
|
2015-05-07 04:46:49 +08:00
|
|
|
info->str_size += len;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-05-07 16:36:01 +08:00
|
|
|
static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
|
2015-05-07 04:46:49 +08:00
|
|
|
{
|
|
|
|
zend_string *ret;
|
|
|
|
|
|
|
|
str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1)));
|
2016-02-25 02:15:53 +08:00
|
|
|
if (in_shm) {
|
|
|
|
ret = accel_new_interned_string(str);
|
|
|
|
if (ret == str) {
|
2017-12-19 02:04:41 +08:00
|
|
|
/* We have to create new SHM allocated string */
|
|
|
|
size_t size = _ZSTR_STRUCT_SIZE(ZSTR_LEN(str));
|
|
|
|
ret = zend_shared_alloc(size);
|
|
|
|
if (!ret) {
|
|
|
|
zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
|
|
|
|
LONGJMP(*EG(bailout), FAILURE);
|
|
|
|
}
|
|
|
|
memcpy(ret, str, size);
|
2016-02-25 02:15:53 +08:00
|
|
|
/* String wasn't interned but we will use it as interned anyway */
|
2017-12-19 02:04:41 +08:00
|
|
|
GC_SET_REFCOUNT(ret, 1);
|
2020-06-15 19:26:22 +08:00
|
|
|
GC_TYPE_INFO(ret) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERSISTENT | IS_STR_PERMANENT) << GC_FLAGS_SHIFT);
|
2015-05-07 16:36:01 +08:00
|
|
|
}
|
2016-02-25 02:15:53 +08:00
|
|
|
} else {
|
|
|
|
ret = str;
|
2018-02-28 05:52:12 +08:00
|
|
|
GC_ADD_FLAGS(ret, IS_STR_INTERNED);
|
|
|
|
GC_DEL_FLAGS(ret, IS_STR_PERMANENT);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_serialize_hash(HashTable *ht,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf,
|
|
|
|
serialize_callback_t func)
|
|
|
|
{
|
|
|
|
Bucket *p, *end;
|
|
|
|
|
2018-12-28 16:22:18 +08:00
|
|
|
if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) {
|
2015-05-07 04:46:49 +08:00
|
|
|
ht->arData = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (IS_SERIALIZED(ht->arData)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SERIALIZE_PTR(ht->arData);
|
|
|
|
p = ht->arData;
|
|
|
|
UNSERIALIZE_PTR(p);
|
|
|
|
end = p + ht->nNumUsed;
|
|
|
|
while (p < end) {
|
|
|
|
if (Z_TYPE(p->val) != IS_UNDEF) {
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(p->key);
|
2015-05-07 04:46:49 +08:00
|
|
|
func(&p->val, script, info, buf);
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-11 00:37:46 +08:00
|
|
|
static void zend_file_cache_serialize_ast(zend_ast *ast,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
2015-05-07 04:46:49 +08:00
|
|
|
{
|
|
|
|
uint32_t i;
|
2017-10-11 00:37:46 +08:00
|
|
|
zend_ast *tmp;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2017-10-10 15:11:05 +08:00
|
|
|
if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_serialize_zval(&((zend_ast_zval*)ast)->val, script, info, buf);
|
|
|
|
} else if (zend_ast_is_list(ast)) {
|
|
|
|
zend_ast_list *list = zend_ast_get_list(ast);
|
|
|
|
for (i = 0; i < list->children; i++) {
|
2017-10-11 00:37:46 +08:00
|
|
|
if (list->child[i] && !IS_SERIALIZED(list->child[i])) {
|
|
|
|
SERIALIZE_PTR(list->child[i]);
|
|
|
|
tmp = list->child[i];
|
|
|
|
UNSERIALIZE_PTR(tmp);
|
|
|
|
zend_file_cache_serialize_ast(tmp, script, info, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
uint32_t children = zend_ast_get_num_children(ast);
|
|
|
|
for (i = 0; i < children; i++) {
|
2017-10-11 00:37:46 +08:00
|
|
|
if (ast->child[i] && !IS_SERIALIZED(ast->child[i])) {
|
|
|
|
SERIALIZE_PTR(ast->child[i]);
|
|
|
|
tmp = ast->child[i];
|
|
|
|
UNSERIALIZE_PTR(tmp);
|
|
|
|
zend_file_cache_serialize_ast(tmp, script, info, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_serialize_zval(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
switch (Z_TYPE_P(zv)) {
|
|
|
|
case IS_STRING:
|
|
|
|
if (!IS_SERIALIZED(Z_STR_P(zv))) {
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(Z_STR_P(zv));
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_ARRAY:
|
|
|
|
if (!IS_SERIALIZED(Z_ARR_P(zv))) {
|
|
|
|
HashTable *ht;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_ARR_P(zv));
|
|
|
|
ht = Z_ARR_P(zv);
|
|
|
|
UNSERIALIZE_PTR(ht);
|
|
|
|
zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_REFERENCE:
|
|
|
|
if (!IS_SERIALIZED(Z_REF_P(zv))) {
|
|
|
|
zend_reference *ref;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_REF_P(zv));
|
|
|
|
ref = Z_REF_P(zv);
|
|
|
|
UNSERIALIZE_PTR(ref);
|
|
|
|
zend_file_cache_serialize_zval(&ref->val, script, info, buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_CONSTANT_AST:
|
|
|
|
if (!IS_SERIALIZED(Z_AST_P(zv))) {
|
|
|
|
zend_ast_ref *ast;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_AST_P(zv));
|
|
|
|
ast = Z_AST_P(zv);
|
|
|
|
UNSERIALIZE_PTR(ast);
|
2017-10-11 00:37:46 +08:00
|
|
|
zend_file_cache_serialize_ast(GC_AST(ast), script, info, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
break;
|
2020-05-20 16:55:36 +08:00
|
|
|
case IS_INDIRECT:
|
|
|
|
/* Used by static properties. */
|
|
|
|
SERIALIZE_PTR(Z_INDIRECT_P(zv));
|
|
|
|
break;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-25 02:57:00 +08:00
|
|
|
static void zend_file_cache_serialize_attribute(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
zend_attribute *attr = Z_PTR_P(zv);
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
attr = Z_PTR_P(zv);
|
|
|
|
UNSERIALIZE_PTR(attr);
|
|
|
|
|
|
|
|
SERIALIZE_STR(attr->name);
|
|
|
|
SERIALIZE_STR(attr->lcname);
|
|
|
|
|
|
|
|
for (i = 0; i < attr->argc; i++) {
|
2020-04-06 18:46:52 +08:00
|
|
|
SERIALIZE_STR(attr->args[i].name);
|
|
|
|
zend_file_cache_serialize_zval(&attr->args[i].value, script, info, buf);
|
2020-05-25 02:57:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-25 19:21:13 +08:00
|
|
|
static void zend_file_cache_serialize_type(
|
|
|
|
zend_type *type, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
|
|
|
|
{
|
|
|
|
if (ZEND_TYPE_HAS_LIST(*type)) {
|
|
|
|
zend_type_list *list = ZEND_TYPE_LIST(*type);
|
|
|
|
SERIALIZE_PTR(list);
|
|
|
|
ZEND_TYPE_SET_PTR(*type, list);
|
|
|
|
UNSERIALIZE_PTR(list);
|
|
|
|
|
2020-01-17 00:04:11 +08:00
|
|
|
zend_type *list_type;
|
|
|
|
ZEND_TYPE_LIST_FOREACH(list, list_type) {
|
|
|
|
zend_file_cache_serialize_type(list_type, script, info, buf);
|
2019-09-25 19:21:13 +08:00
|
|
|
} ZEND_TYPE_LIST_FOREACH_END();
|
|
|
|
} else if (ZEND_TYPE_HAS_NAME(*type)) {
|
|
|
|
zend_string *type_name = ZEND_TYPE_NAME(*type);
|
|
|
|
SERIALIZE_STR(type_name);
|
|
|
|
ZEND_TYPE_SET_PTR(*type, type_name);
|
|
|
|
} else if (ZEND_TYPE_HAS_CE(*type)) {
|
|
|
|
zend_class_entry *ce = ZEND_TYPE_CE(*type);
|
|
|
|
SERIALIZE_PTR(ce);
|
|
|
|
ZEND_TYPE_SET_PTR(*type, ce);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static void zend_file_cache_serialize_op_array(zend_op_array *op_array,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
2020-08-11 20:42:13 +08:00
|
|
|
/* Check whether this op_array has already been serialized. */
|
|
|
|
if (IS_SERIALIZED(op_array->opcodes)) {
|
|
|
|
ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->static_variables) {
|
2015-05-07 04:46:49 +08:00
|
|
|
HashTable *ht;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(op_array->static_variables);
|
|
|
|
ht = op_array->static_variables;
|
|
|
|
UNSERIALIZE_PTR(ht);
|
|
|
|
zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:42:13 +08:00
|
|
|
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
|
|
|
|
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
|
|
|
|
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
|
|
|
|
} else {
|
|
|
|
SERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->scope) {
|
2017-03-03 21:10:46 +08:00
|
|
|
if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
|
|
|
|
op_array->refcount = (uint32_t*)(intptr_t)-1;
|
|
|
|
SERIALIZE_PTR(op_array->literals);
|
|
|
|
SERIALIZE_PTR(op_array->opcodes);
|
|
|
|
SERIALIZE_PTR(op_array->arg_info);
|
|
|
|
SERIALIZE_PTR(op_array->vars);
|
|
|
|
SERIALIZE_STR(op_array->function_name);
|
|
|
|
SERIALIZE_STR(op_array->filename);
|
2017-03-03 21:12:41 +08:00
|
|
|
SERIALIZE_PTR(op_array->live_range);
|
2017-03-03 21:10:46 +08:00
|
|
|
SERIALIZE_PTR(op_array->scope);
|
|
|
|
SERIALIZE_STR(op_array->doc_comment);
|
2020-05-25 02:57:00 +08:00
|
|
|
SERIALIZE_ATTRIBUTES(op_array->attributes);
|
2017-03-03 21:10:46 +08:00
|
|
|
SERIALIZE_PTR(op_array->try_catch_array);
|
|
|
|
SERIALIZE_PTR(op_array->prototype);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes);
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:42:13 +08:00
|
|
|
if (op_array->literals) {
|
2015-05-07 04:46:49 +08:00
|
|
|
zval *p, *end;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(op_array->literals);
|
|
|
|
p = op_array->literals;
|
|
|
|
UNSERIALIZE_PTR(p);
|
|
|
|
end = p + op_array->last_literal;
|
|
|
|
while (p < end) {
|
|
|
|
zend_file_cache_serialize_zval(p, script, info, buf);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:42:13 +08:00
|
|
|
{
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_op *opline, *end;
|
|
|
|
|
2017-12-11 05:33:47 +08:00
|
|
|
#if !ZEND_USE_ABS_CONST_ADDR
|
|
|
|
zval *literals = op_array->literals;
|
|
|
|
UNSERIALIZE_PTR(literals);
|
|
|
|
#endif
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(op_array->opcodes);
|
|
|
|
opline = op_array->opcodes;
|
|
|
|
UNSERIALIZE_PTR(opline);
|
|
|
|
end = opline + op_array->last;
|
|
|
|
while (opline < end) {
|
2016-04-09 16:43:28 +08:00
|
|
|
#if ZEND_USE_ABS_CONST_ADDR
|
2015-11-12 07:02:24 +08:00
|
|
|
if (opline->op1_type == IS_CONST) {
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(opline->op1.zv);
|
|
|
|
}
|
2015-11-12 07:02:24 +08:00
|
|
|
if (opline->op2_type == IS_CONST) {
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(opline->op2.zv);
|
|
|
|
}
|
2017-10-04 21:53:01 +08:00
|
|
|
#else
|
|
|
|
if (opline->op1_type == IS_CONST) {
|
2017-12-11 05:33:47 +08:00
|
|
|
opline->op1.constant = RT_CONSTANT(opline, opline->op1) - literals;
|
2017-10-04 21:53:01 +08:00
|
|
|
}
|
|
|
|
if (opline->op2_type == IS_CONST) {
|
2017-12-11 05:33:47 +08:00
|
|
|
opline->op2.constant = RT_CONSTANT(opline, opline->op2) - literals;
|
2017-10-04 21:53:01 +08:00
|
|
|
}
|
2016-04-09 16:43:28 +08:00
|
|
|
#endif
|
|
|
|
#if ZEND_USE_ABS_JMP_ADDR
|
2015-05-07 04:46:49 +08:00
|
|
|
switch (opline->opcode) {
|
|
|
|
case ZEND_JMP:
|
|
|
|
case ZEND_FAST_CALL:
|
|
|
|
SERIALIZE_PTR(opline->op1.jmp_addr);
|
|
|
|
break;
|
|
|
|
case ZEND_JMPZNZ:
|
|
|
|
/* relative extended_value don't have to be changed */
|
|
|
|
/* break omitted intentionally */
|
|
|
|
case ZEND_JMPZ:
|
|
|
|
case ZEND_JMPNZ:
|
|
|
|
case ZEND_JMPZ_EX:
|
|
|
|
case ZEND_JMPNZ_EX:
|
|
|
|
case ZEND_JMP_SET:
|
|
|
|
case ZEND_COALESCE:
|
|
|
|
case ZEND_FE_RESET_R:
|
|
|
|
case ZEND_FE_RESET_RW:
|
|
|
|
case ZEND_ASSERT_CHECK:
|
2020-05-24 18:42:48 +08:00
|
|
|
case ZEND_JMP_NULL:
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(opline->op2.jmp_addr);
|
|
|
|
break;
|
2018-02-01 03:39:30 +08:00
|
|
|
case ZEND_CATCH:
|
2018-02-06 00:41:47 +08:00
|
|
|
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
2018-02-01 03:39:30 +08:00
|
|
|
SERIALIZE_PTR(opline->op2.jmp_addr);
|
|
|
|
}
|
|
|
|
break;
|
2015-05-13 17:55:42 +08:00
|
|
|
case ZEND_FE_FETCH_R:
|
|
|
|
case ZEND_FE_FETCH_RW:
|
2017-03-18 06:45:05 +08:00
|
|
|
case ZEND_SWITCH_LONG:
|
|
|
|
case ZEND_SWITCH_STRING:
|
2020-04-10 04:36:37 +08:00
|
|
|
case ZEND_MATCH:
|
2015-05-13 17:55:42 +08:00
|
|
|
/* relative extended_value don't have to be changed */
|
|
|
|
break;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
2016-04-09 16:43:28 +08:00
|
|
|
#endif
|
2016-03-18 03:00:27 +08:00
|
|
|
zend_serialize_opcode_handler(opline);
|
2015-05-07 04:46:49 +08:00
|
|
|
opline++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->arg_info) {
|
|
|
|
zend_arg_info *p, *end;
|
|
|
|
SERIALIZE_PTR(op_array->arg_info);
|
|
|
|
p = op_array->arg_info;
|
|
|
|
UNSERIALIZE_PTR(p);
|
|
|
|
end = p + op_array->num_args;
|
|
|
|
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
while (p < end) {
|
|
|
|
if (!IS_SERIALIZED(p->name)) {
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(p->name);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
2019-09-25 19:21:13 +08:00
|
|
|
zend_file_cache_serialize_type(&p->type, script, info, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->vars) {
|
|
|
|
zend_string **p, **end;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(op_array->vars);
|
|
|
|
p = op_array->vars;
|
|
|
|
UNSERIALIZE_PTR(p);
|
|
|
|
end = p + op_array->last_var;
|
|
|
|
while (p < end) {
|
|
|
|
if (!IS_SERIALIZED(*p)) {
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(*p);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(op_array->function_name);
|
|
|
|
SERIALIZE_STR(op_array->filename);
|
2015-11-11 02:48:03 +08:00
|
|
|
SERIALIZE_PTR(op_array->live_range);
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(op_array->scope);
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(op_array->doc_comment);
|
2020-05-25 02:57:00 +08:00
|
|
|
SERIALIZE_ATTRIBUTES(op_array->attributes);
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(op_array->try_catch_array);
|
|
|
|
SERIALIZE_PTR(op_array->prototype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_serialize_func(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
zend_op_array *op_array;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
op_array = Z_PTR_P(zv);
|
|
|
|
UNSERIALIZE_PTR(op_array);
|
|
|
|
zend_file_cache_serialize_op_array(op_array, script, info, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_serialize_prop_info(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
if (!IS_SERIALIZED(Z_PTR_P(zv))) {
|
|
|
|
zend_property_info *prop;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
prop = Z_PTR_P(zv);
|
|
|
|
UNSERIALIZE_PTR(prop);
|
|
|
|
|
2018-05-03 17:10:33 +08:00
|
|
|
ZEND_ASSERT(prop->ce != NULL && prop->name != NULL);
|
|
|
|
if (!IS_SERIALIZED(prop->ce)) {
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(prop->ce);
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(prop->name);
|
2018-05-03 17:10:33 +08:00
|
|
|
if (prop->doc_comment) {
|
|
|
|
SERIALIZE_STR(prop->doc_comment);
|
|
|
|
}
|
2020-05-25 02:57:00 +08:00
|
|
|
SERIALIZE_ATTRIBUTES(prop->attributes);
|
2019-09-25 19:21:13 +08:00
|
|
|
zend_file_cache_serialize_type(&prop->type, script, info, buf);
|
2019-01-07 19:28:51 +08:00
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-08 17:40:42 +08:00
|
|
|
static void zend_file_cache_serialize_class_constant(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
if (!IS_SERIALIZED(Z_PTR_P(zv))) {
|
|
|
|
zend_class_constant *c;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
c = Z_PTR_P(zv);
|
|
|
|
UNSERIALIZE_PTR(c);
|
|
|
|
|
2018-05-03 17:10:33 +08:00
|
|
|
ZEND_ASSERT(c->ce != NULL);
|
|
|
|
if (!IS_SERIALIZED(c->ce)) {
|
2015-12-08 17:40:42 +08:00
|
|
|
SERIALIZE_PTR(c->ce);
|
2018-05-03 17:10:33 +08:00
|
|
|
|
|
|
|
zend_file_cache_serialize_zval(&c->value, script, info, buf);
|
|
|
|
|
|
|
|
if (c->doc_comment) {
|
|
|
|
SERIALIZE_STR(c->doc_comment);
|
|
|
|
}
|
2020-05-25 02:57:00 +08:00
|
|
|
|
|
|
|
SERIALIZE_ATTRIBUTES(c->attributes);
|
2015-12-08 17:40:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static void zend_file_cache_serialize_class(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
zend_class_entry *ce;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
ce = Z_PTR_P(zv);
|
|
|
|
UNSERIALIZE_PTR(ce);
|
|
|
|
|
2015-05-07 16:36:01 +08:00
|
|
|
SERIALIZE_STR(ce->name);
|
2018-09-18 16:41:40 +08:00
|
|
|
if (ce->parent) {
|
|
|
|
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
|
|
|
|
SERIALIZE_STR(ce->parent_name);
|
|
|
|
} else {
|
|
|
|
SERIALIZE_PTR(ce->parent);
|
|
|
|
}
|
2018-08-24 05:20:57 +08:00
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_serialize_hash(&ce->function_table, script, info, buf, zend_file_cache_serialize_func);
|
|
|
|
if (ce->default_properties_table) {
|
|
|
|
zval *p, *end;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(ce->default_properties_table);
|
|
|
|
p = ce->default_properties_table;
|
|
|
|
UNSERIALIZE_PTR(p);
|
|
|
|
end = p + ce->default_properties_count;
|
|
|
|
while (p < end) {
|
|
|
|
zend_file_cache_serialize_zval(p, script, info, buf);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ce->default_static_members_table) {
|
2020-05-20 16:55:36 +08:00
|
|
|
zval *p, *end;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
SERIALIZE_PTR(ce->default_static_members_table);
|
2020-05-20 16:55:36 +08:00
|
|
|
p = ce->default_static_members_table;
|
|
|
|
UNSERIALIZE_PTR(p);
|
2018-06-22 18:58:48 +08:00
|
|
|
|
2020-05-20 16:55:36 +08:00
|
|
|
end = p + ce->default_static_members_count;
|
2015-05-07 04:46:49 +08:00
|
|
|
while (p < end) {
|
|
|
|
zend_file_cache_serialize_zval(p, script, info, buf);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
2015-12-08 17:40:42 +08:00
|
|
|
zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant);
|
2015-11-12 07:02:24 +08:00
|
|
|
SERIALIZE_STR(ce->info.user.filename);
|
|
|
|
SERIALIZE_STR(ce->info.user.doc_comment);
|
2020-05-25 02:57:00 +08:00
|
|
|
SERIALIZE_ATTRIBUTES(ce->attributes);
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
|
|
|
|
|
2019-01-07 19:28:51 +08:00
|
|
|
if (ce->properties_info_table) {
|
|
|
|
uint32_t i;
|
|
|
|
zend_property_info **table;
|
|
|
|
|
|
|
|
SERIALIZE_PTR(ce->properties_info_table);
|
|
|
|
table = ce->properties_info_table;
|
|
|
|
UNSERIALIZE_PTR(table);
|
|
|
|
|
|
|
|
for (i = 0; i < ce->default_properties_count; i++) {
|
|
|
|
SERIALIZE_PTR(table[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (ce->num_interfaces) {
|
|
|
|
uint32_t i;
|
|
|
|
zend_class_name *interface_names;
|
|
|
|
|
2018-09-18 16:41:40 +08:00
|
|
|
ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
|
2018-08-23 22:16:28 +08:00
|
|
|
|
|
|
|
SERIALIZE_PTR(ce->interface_names);
|
|
|
|
interface_names = ce->interface_names;
|
|
|
|
UNSERIALIZE_PTR(interface_names);
|
|
|
|
|
|
|
|
for (i = 0; i < ce->num_interfaces; i++) {
|
|
|
|
SERIALIZE_STR(interface_names[i].name);
|
|
|
|
SERIALIZE_STR(interface_names[i].lc_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
if (ce->num_traits) {
|
|
|
|
uint32_t i;
|
|
|
|
zend_class_name *trait_names;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
SERIALIZE_PTR(ce->trait_names);
|
|
|
|
trait_names = ce->trait_names;
|
|
|
|
UNSERIALIZE_PTR(trait_names);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
for (i = 0; i < ce->num_traits; i++) {
|
|
|
|
SERIALIZE_STR(trait_names[i].name);
|
|
|
|
SERIALIZE_STR(trait_names[i].lc_name);
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
if (ce->trait_aliases) {
|
|
|
|
zend_trait_alias **p, *q;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
SERIALIZE_PTR(ce->trait_aliases);
|
|
|
|
p = ce->trait_aliases;
|
|
|
|
UNSERIALIZE_PTR(p);
|
|
|
|
|
|
|
|
while (*p) {
|
|
|
|
SERIALIZE_PTR(*p);
|
|
|
|
q = *p;
|
|
|
|
UNSERIALIZE_PTR(q);
|
|
|
|
|
|
|
|
if (q->trait_method.method_name) {
|
|
|
|
SERIALIZE_STR(q->trait_method.method_name);
|
|
|
|
}
|
|
|
|
if (q->trait_method.class_name) {
|
|
|
|
SERIALIZE_STR(q->trait_method.class_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (q->alias) {
|
|
|
|
SERIALIZE_STR(q->alias);
|
|
|
|
}
|
|
|
|
p++;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
if (ce->trait_precedences) {
|
|
|
|
zend_trait_precedence **p, *q;
|
2019-01-09 05:08:40 +08:00
|
|
|
uint32_t j;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
SERIALIZE_PTR(ce->trait_precedences);
|
|
|
|
p = ce->trait_precedences;
|
|
|
|
UNSERIALIZE_PTR(p);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
while (*p) {
|
|
|
|
SERIALIZE_PTR(*p);
|
|
|
|
q = *p;
|
|
|
|
UNSERIALIZE_PTR(q);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
if (q->trait_method.method_name) {
|
|
|
|
SERIALIZE_STR(q->trait_method.method_name);
|
|
|
|
}
|
|
|
|
if (q->trait_method.class_name) {
|
|
|
|
SERIALIZE_STR(q->trait_method.class_name);
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
for (j = 0; j < q->num_excludes; j++) {
|
|
|
|
SERIALIZE_STR(q->exclude_class_names[j]);
|
|
|
|
}
|
|
|
|
p++;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SERIALIZE_PTR(ce->constructor);
|
|
|
|
SERIALIZE_PTR(ce->destructor);
|
|
|
|
SERIALIZE_PTR(ce->clone);
|
|
|
|
SERIALIZE_PTR(ce->__get);
|
|
|
|
SERIALIZE_PTR(ce->__set);
|
|
|
|
SERIALIZE_PTR(ce->__call);
|
2020-06-26 16:54:40 +08:00
|
|
|
SERIALIZE_PTR(ce->__serialize);
|
|
|
|
SERIALIZE_PTR(ce->__unserialize);
|
2015-05-07 04:46:49 +08:00
|
|
|
SERIALIZE_PTR(ce->__isset);
|
|
|
|
SERIALIZE_PTR(ce->__unset);
|
|
|
|
SERIALIZE_PTR(ce->__tostring);
|
|
|
|
SERIALIZE_PTR(ce->__callstatic);
|
|
|
|
SERIALIZE_PTR(ce->__debugInfo);
|
2018-10-17 20:52:50 +08:00
|
|
|
|
|
|
|
if (ce->iterator_funcs_ptr) {
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_new_iterator);
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_rewind);
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_valid);
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_key);
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_current);
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_next);
|
|
|
|
SERIALIZE_PTR(ce->iterator_funcs_ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
|
2020-05-19 21:01:18 +08:00
|
|
|
static void zend_file_cache_serialize_warnings(
|
|
|
|
zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
|
|
|
|
{
|
|
|
|
if (script->warnings) {
|
|
|
|
zend_recorded_warning **warnings;
|
|
|
|
SERIALIZE_PTR(script->warnings);
|
|
|
|
warnings = script->warnings;
|
|
|
|
UNSERIALIZE_PTR(warnings);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < script->num_warnings; i++) {
|
|
|
|
zend_recorded_warning *warning;
|
|
|
|
SERIALIZE_PTR(warnings[i]);
|
|
|
|
warning = warnings[i];
|
|
|
|
UNSERIALIZE_PTR(warning);
|
|
|
|
SERIALIZE_STR(warning->error_filename);
|
|
|
|
SERIALIZE_STR(warning->error_message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static void zend_file_cache_serialize(zend_persistent_script *script,
|
|
|
|
zend_file_cache_metainfo *info,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
zend_persistent_script *new_script;
|
|
|
|
|
|
|
|
memcpy(info->magic, "OPCACHE", 8);
|
2020-07-17 07:31:10 +08:00
|
|
|
memcpy(info->system_id, zend_system_id, 32);
|
2015-05-07 04:46:49 +08:00
|
|
|
info->mem_size = script->size;
|
|
|
|
info->str_size = 0;
|
|
|
|
info->script_offset = (char*)script - (char*)script->mem;
|
|
|
|
info->timestamp = script->timestamp;
|
|
|
|
|
|
|
|
memcpy(buf, script->mem, script->size);
|
|
|
|
|
|
|
|
new_script = (zend_persistent_script*)((char*)buf + info->script_offset);
|
2015-11-12 07:02:24 +08:00
|
|
|
SERIALIZE_STR(new_script->script.filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2015-11-12 07:02:24 +08:00
|
|
|
zend_file_cache_serialize_hash(&new_script->script.class_table, script, info, buf, zend_file_cache_serialize_class);
|
|
|
|
zend_file_cache_serialize_hash(&new_script->script.function_table, script, info, buf, zend_file_cache_serialize_func);
|
|
|
|
zend_file_cache_serialize_op_array(&new_script->script.main_op_array, script, info, buf);
|
2020-05-19 21:01:18 +08:00
|
|
|
zend_file_cache_serialize_warnings(new_script, info, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
SERIALIZE_PTR(new_script->arena_mem);
|
|
|
|
new_script->mem = NULL;
|
|
|
|
}
|
|
|
|
|
2015-07-17 21:14:25 +08:00
|
|
|
static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
|
2015-05-07 04:46:49 +08:00
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
char *filename;
|
|
|
|
|
2018-03-05 22:16:55 +08:00
|
|
|
#ifndef ZEND_WIN32
|
2015-05-07 04:46:49 +08:00
|
|
|
len = strlen(ZCG(accel_directives).file_cache);
|
2015-07-17 21:14:25 +08:00
|
|
|
filename = emalloc(len + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
|
2015-05-07 04:46:49 +08:00
|
|
|
memcpy(filename, ZCG(accel_directives).file_cache, len);
|
|
|
|
filename[len] = '/';
|
2020-07-17 07:31:10 +08:00
|
|
|
memcpy(filename + len + 1, zend_system_id, 32);
|
2015-07-17 21:14:25 +08:00
|
|
|
memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
|
|
|
|
memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
|
2015-07-17 19:50:40 +08:00
|
|
|
#else
|
2018-03-05 22:16:55 +08:00
|
|
|
len = strlen(ZCG(accel_directives).file_cache);
|
|
|
|
|
|
|
|
filename = emalloc(len + 33 + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
|
|
|
|
|
|
|
|
memcpy(filename, ZCG(accel_directives).file_cache, len);
|
|
|
|
filename[len] = '\\';
|
Allow multiple cache instances per user/host on Windows
Formerly, there was at most a single OPcache instance per user and the
so called system ID (which is determined from the PHP version).
Sometimes multiple OPcaches might be desired, though, particularly for
unrelated CLI scripts, which may even be necessary (e.g. for our test
suite in parallel mode).
We therefore introduce a new INI directive `opcache.cache_id` which
allows to configure independent OPcache instances for the same user.
We also use `GetUserNameW()` instead of `php_win32_get_username()`,
because the latter retrieves the user name encoded in the
`default_charset`, which can obviously yield different results for
different charsets, leading to OPcache "incompatibilities". Slightly
worse, some characters may not even be encodeable in the
`default_charset` and would be replaced by question marks, which could
result in different users sharing the same OPcache.
We also refactor, and re-use existing APIs to avoid duplicated code.
2019-07-17 03:14:57 +08:00
|
|
|
memcpy(filename + 1 + len, accel_uname_id, 32);
|
2019-06-20 23:53:10 +08:00
|
|
|
len += 1 + 32;
|
2015-07-17 19:50:40 +08:00
|
|
|
filename[len] = '\\';
|
2018-03-05 22:16:55 +08:00
|
|
|
|
2020-07-17 07:31:10 +08:00
|
|
|
memcpy(filename + len + 1, zend_system_id, 32);
|
2019-04-10 20:55:15 +08:00
|
|
|
|
|
|
|
if (ZSTR_LEN(script_path) >= 7 && ':' == ZSTR_VAL(script_path)[4] && '/' == ZSTR_VAL(script_path)[5] && '/' == ZSTR_VAL(script_path)[6]) {
|
|
|
|
/* phar:// or file:// */
|
|
|
|
*(filename + len + 33) = '\\';
|
|
|
|
memcpy(filename + len + 34, ZSTR_VAL(script_path), 4);
|
|
|
|
if (ZSTR_LEN(script_path) - 7 >= 2 && ':' == ZSTR_VAL(script_path)[8]) {
|
|
|
|
*(filename + len + 38) = '\\';
|
|
|
|
*(filename + len + 39) = ZSTR_VAL(script_path)[7];
|
|
|
|
memcpy(filename + len + 40, ZSTR_VAL(script_path) + 9, ZSTR_LEN(script_path) - 9);
|
|
|
|
memcpy(filename + len + 40 + ZSTR_LEN(script_path) - 9, SUFFIX, sizeof(SUFFIX));
|
|
|
|
} else {
|
|
|
|
memcpy(filename + len + 38, ZSTR_VAL(script_path) + 7, ZSTR_LEN(script_path) - 7);
|
|
|
|
memcpy(filename + len + 38 + ZSTR_LEN(script_path) - 7, SUFFIX, sizeof(SUFFIX));
|
|
|
|
}
|
|
|
|
} else if (ZSTR_LEN(script_path) >= 2 && ':' == ZSTR_VAL(script_path)[1]) {
|
2015-07-17 19:50:40 +08:00
|
|
|
/* local fs */
|
|
|
|
*(filename + len + 33) = '\\';
|
2015-07-17 21:14:25 +08:00
|
|
|
*(filename + len + 34) = ZSTR_VAL(script_path)[0];
|
|
|
|
memcpy(filename + len + 35, ZSTR_VAL(script_path) + 2, ZSTR_LEN(script_path) - 2);
|
|
|
|
memcpy(filename + len + 35 + ZSTR_LEN(script_path) - 2, SUFFIX, sizeof(SUFFIX));
|
2015-07-17 19:50:40 +08:00
|
|
|
} else {
|
|
|
|
/* network path */
|
2015-07-17 21:14:25 +08:00
|
|
|
memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
|
|
|
|
memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
|
2015-07-17 19:50:40 +08:00
|
|
|
}
|
|
|
|
#endif
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2015-07-17 21:14:25 +08:00
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char *filename;
|
|
|
|
zend_file_cache_metainfo info;
|
2015-12-01 10:35:32 +08:00
|
|
|
#ifdef HAVE_SYS_UIO_H
|
2015-07-17 21:14:25 +08:00
|
|
|
struct iovec vec[3];
|
|
|
|
#endif
|
|
|
|
void *mem, *buf;
|
|
|
|
|
2019-04-11 18:52:50 +08:00
|
|
|
#ifdef HAVE_JIT
|
2019-04-01 15:27:11 +08:00
|
|
|
/* FIXME: dump jited codes out to file cache? */
|
2020-05-18 15:23:06 +08:00
|
|
|
if (JIT_G(on)) {
|
2019-04-01 15:27:11 +08:00
|
|
|
return FAILURE;
|
|
|
|
}
|
2019-04-11 18:52:50 +08:00
|
|
|
#endif
|
2019-04-01 15:27:11 +08:00
|
|
|
|
2015-11-12 07:02:24 +08:00
|
|
|
filename = zend_file_cache_get_bin_file_path(script->script.filename);
|
2015-07-17 21:14:25 +08:00
|
|
|
|
|
|
|
if (zend_file_cache_mkdir(filename, strlen(ZCG(accel_directives).file_cache)) != SUCCESS) {
|
2018-07-11 20:34:18 +08:00
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create directory for file '%s', %s\n", filename, strerror(errno));
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2018-07-14 18:51:37 +08:00
|
|
|
fd = zend_file_cache_open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
|
2015-05-07 04:46:49 +08:00
|
|
|
if (fd < 0) {
|
|
|
|
if (errno != EEXIST) {
|
2018-07-11 20:34:18 +08:00
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create file '%s', %s\n", filename, strerror(errno));
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
efree(filename);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zend_file_cache_flock(fd, LOCK_EX) != 0) {
|
|
|
|
close(fd);
|
|
|
|
efree(filename);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2018-02-15 00:18:47 +08:00
|
|
|
#if defined(__AVX__) || defined(__SSE2__)
|
2015-05-07 04:46:49 +08:00
|
|
|
/* Align to 64-byte boundary */
|
|
|
|
mem = emalloc(script->size + 64);
|
|
|
|
buf = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
|
|
|
|
#else
|
|
|
|
mem = buf = emalloc(script->size);
|
|
|
|
#endif
|
|
|
|
|
2015-06-29 21:44:54 +08:00
|
|
|
ZCG(mem) = zend_string_alloc(4096 - (_ZSTR_HEADER_SIZE + 1), 0);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
zend_shared_alloc_init_xlat_table();
|
2015-05-21 04:33:55 +08:00
|
|
|
if (!in_shm) {
|
|
|
|
script->corrupted = 1; /* used to check if script restored to SHM or process memory */
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_serialize(script, &info, buf);
|
2015-05-21 04:33:55 +08:00
|
|
|
if (!in_shm) {
|
|
|
|
script->corrupted = 0;
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_shared_alloc_destroy_xlat_table();
|
|
|
|
|
|
|
|
info.checksum = zend_adler32(ADLER32_INIT, buf, script->size);
|
2019-10-09 16:38:11 +08:00
|
|
|
info.checksum = zend_adler32(info.checksum, (unsigned char*)ZSTR_VAL((zend_string*)ZCG(mem)), info.str_size);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2019-07-01 17:02:31 +08:00
|
|
|
#if __has_feature(memory_sanitizer)
|
|
|
|
/* The buffer may contain uninitialized regions. However, the uninitialized parts will not be
|
|
|
|
* used when reading the cache. We should probably still try to get things fully initialized
|
|
|
|
* for reproducibility, but for now ignore this issue. */
|
|
|
|
__msan_unpoison(&info, sizeof(info));
|
|
|
|
__msan_unpoison(buf, script->size);
|
|
|
|
#endif
|
|
|
|
|
2015-12-01 10:35:32 +08:00
|
|
|
#ifdef HAVE_SYS_UIO_H
|
2020-08-05 17:09:18 +08:00
|
|
|
vec[0].iov_base = (void *)&info;
|
2015-05-07 04:46:49 +08:00
|
|
|
vec[0].iov_len = sizeof(info);
|
|
|
|
vec[1].iov_base = buf;
|
|
|
|
vec[1].iov_len = script->size;
|
2015-06-30 09:05:24 +08:00
|
|
|
vec[2].iov_base = ZSTR_VAL((zend_string*)ZCG(mem));
|
2015-05-07 04:46:49 +08:00
|
|
|
vec[2].iov_len = info.str_size;
|
|
|
|
|
|
|
|
if (writev(fd, vec, 3) != (ssize_t)(sizeof(info) + script->size + info.str_size)) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex((zend_string*)ZCG(mem), 0);
|
2016-06-27 14:42:49 +08:00
|
|
|
close(fd);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(mem);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (ZEND_LONG_MAX < (zend_long)(sizeof(info) + script->size + info.str_size) ||
|
|
|
|
write(fd, &info, sizeof(info)) != sizeof(info) ||
|
|
|
|
write(fd, buf, script->size) != script->size ||
|
|
|
|
write(fd, ((zend_string*)ZCG(mem))->val, info.str_size) != info.str_size
|
|
|
|
) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex((zend_string*)ZCG(mem), 0);
|
2016-06-27 14:42:49 +08:00
|
|
|
close(fd);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(mem);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-05-28 21:27:12 +08:00
|
|
|
zend_string_release_ex((zend_string*)ZCG(mem), 0);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(mem);
|
|
|
|
if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
efree(filename);
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_unserialize_hash(HashTable *ht,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf,
|
2015-11-04 18:59:30 +08:00
|
|
|
unserialize_callback_t func,
|
|
|
|
dtor_func_t dtor)
|
2015-05-07 04:46:49 +08:00
|
|
|
{
|
|
|
|
Bucket *p, *end;
|
|
|
|
|
2015-11-04 18:59:30 +08:00
|
|
|
ht->pDestructor = dtor;
|
2018-12-28 16:22:18 +08:00
|
|
|
if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) {
|
2018-03-12 16:18:12 +08:00
|
|
|
if (EXPECTED(!file_cache_only)) {
|
|
|
|
HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
|
|
|
|
} else {
|
|
|
|
HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (IS_UNSERIALIZED(ht->arData)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
UNSERIALIZE_PTR(ht->arData);
|
|
|
|
p = ht->arData;
|
|
|
|
end = p + ht->nNumUsed;
|
|
|
|
while (p < end) {
|
|
|
|
if (Z_TYPE(p->val) != IS_UNDEF) {
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(p->key);
|
2015-05-07 04:46:49 +08:00
|
|
|
func(&p->val, script, buf);
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-11 00:37:46 +08:00
|
|
|
static void zend_file_cache_unserialize_ast(zend_ast *ast,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
2015-05-07 04:46:49 +08:00
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
|
2017-10-10 15:11:05 +08:00
|
|
|
if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_unserialize_zval(&((zend_ast_zval*)ast)->val, script, buf);
|
|
|
|
} else if (zend_ast_is_list(ast)) {
|
|
|
|
zend_ast_list *list = zend_ast_get_list(ast);
|
|
|
|
for (i = 0; i < list->children; i++) {
|
2018-04-28 18:26:32 +08:00
|
|
|
if (list->child[i] && !IS_UNSERIALIZED(list->child[i])) {
|
2017-10-11 00:37:46 +08:00
|
|
|
UNSERIALIZE_PTR(list->child[i]);
|
|
|
|
zend_file_cache_unserialize_ast(list->child[i], script, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
uint32_t children = zend_ast_get_num_children(ast);
|
|
|
|
for (i = 0; i < children; i++) {
|
2018-04-28 18:26:32 +08:00
|
|
|
if (ast->child[i] && !IS_UNSERIALIZED(ast->child[i])) {
|
2017-10-11 00:37:46 +08:00
|
|
|
UNSERIALIZE_PTR(ast->child[i]);
|
|
|
|
zend_file_cache_unserialize_ast(ast->child[i], script, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_unserialize_zval(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
switch (Z_TYPE_P(zv)) {
|
|
|
|
case IS_STRING:
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(Z_STR_P(zv))) {
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(Z_STR_P(zv));
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_ARRAY:
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(Z_ARR_P(zv))) {
|
2015-05-07 04:46:49 +08:00
|
|
|
HashTable *ht;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_ARR_P(zv));
|
|
|
|
ht = Z_ARR_P(zv);
|
2015-11-04 18:59:30 +08:00
|
|
|
zend_file_cache_unserialize_hash(ht,
|
|
|
|
script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_REFERENCE:
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(Z_REF_P(zv))) {
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_reference *ref;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_REF_P(zv));
|
|
|
|
ref = Z_REF_P(zv);
|
|
|
|
zend_file_cache_unserialize_zval(&ref->val, script, buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IS_CONSTANT_AST:
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(Z_AST_P(zv))) {
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(Z_AST_P(zv));
|
2017-10-09 21:57:51 +08:00
|
|
|
zend_file_cache_unserialize_ast(Z_ASTVAL_P(zv), script, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
break;
|
2020-05-20 16:55:36 +08:00
|
|
|
case IS_INDIRECT:
|
|
|
|
/* Used by static properties. */
|
|
|
|
UNSERIALIZE_PTR(Z_INDIRECT_P(zv));
|
|
|
|
break;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-25 02:57:00 +08:00
|
|
|
static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_script *script, void *buf)
|
|
|
|
{
|
|
|
|
zend_attribute *attr;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
attr = Z_PTR_P(zv);
|
|
|
|
|
|
|
|
UNSERIALIZE_STR(attr->name);
|
|
|
|
UNSERIALIZE_STR(attr->lcname);
|
|
|
|
|
|
|
|
for (i = 0; i < attr->argc; i++) {
|
2020-04-06 18:46:52 +08:00
|
|
|
UNSERIALIZE_STR(attr->args[i].name);
|
|
|
|
zend_file_cache_unserialize_zval(&attr->args[i].value, script, buf);
|
2020-05-25 02:57:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-25 19:21:13 +08:00
|
|
|
static void zend_file_cache_unserialize_type(
|
|
|
|
zend_type *type, zend_persistent_script *script, void *buf)
|
|
|
|
{
|
|
|
|
if (ZEND_TYPE_HAS_LIST(*type)) {
|
|
|
|
zend_type_list *list = ZEND_TYPE_LIST(*type);
|
|
|
|
UNSERIALIZE_PTR(list);
|
|
|
|
ZEND_TYPE_SET_PTR(*type, list);
|
|
|
|
|
2020-01-17 00:04:11 +08:00
|
|
|
zend_type *list_type;
|
|
|
|
ZEND_TYPE_LIST_FOREACH(list, list_type) {
|
|
|
|
zend_file_cache_unserialize_type(list_type, script, buf);
|
2019-09-25 19:21:13 +08:00
|
|
|
} ZEND_TYPE_LIST_FOREACH_END();
|
|
|
|
} else if (ZEND_TYPE_HAS_NAME(*type)) {
|
|
|
|
zend_string *type_name = ZEND_TYPE_NAME(*type);
|
|
|
|
UNSERIALIZE_STR(type_name);
|
|
|
|
ZEND_TYPE_SET_PTR(*type, type_name);
|
|
|
|
} else if (ZEND_TYPE_HAS_CE(*type)) {
|
|
|
|
zend_class_entry *ce = ZEND_TYPE_CE(*type);
|
|
|
|
UNSERIALIZE_PTR(ce);
|
|
|
|
ZEND_TYPE_SET_PTR(*type, ce);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static void zend_file_cache_unserialize_op_array(zend_op_array *op_array,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
2020-08-11 20:42:13 +08:00
|
|
|
/* Check whether this op_array has already been unserialized. */
|
|
|
|
if (IS_UNSERIALIZED(op_array->opcodes)) {
|
|
|
|
ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->static_variables) {
|
2015-05-07 04:46:49 +08:00
|
|
|
HashTable *ht;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(op_array->static_variables);
|
|
|
|
ht = op_array->static_variables;
|
2015-11-04 18:59:30 +08:00
|
|
|
zend_file_cache_unserialize_hash(ht,
|
|
|
|
script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
|
2020-08-11 20:42:13 +08:00
|
|
|
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
|
|
|
|
if (op_array->static_variables) {
|
|
|
|
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
|
|
|
|
} else {
|
|
|
|
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
|
|
|
|
}
|
|
|
|
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
|
|
|
|
} else {
|
|
|
|
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
|
|
|
|
if (ZEND_MAP_PTR(op_array->run_time_cache)) {
|
|
|
|
if (script->corrupted) {
|
|
|
|
/* Not in SHM: Use serialized arena pointer. */
|
|
|
|
UNSERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
|
|
|
|
} else {
|
|
|
|
/* In SHM: Allocate new pointer. */
|
|
|
|
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-03 21:10:46 +08:00
|
|
|
if (op_array->refcount) {
|
|
|
|
op_array->refcount = NULL;
|
|
|
|
UNSERIALIZE_PTR(op_array->literals);
|
|
|
|
UNSERIALIZE_PTR(op_array->opcodes);
|
|
|
|
UNSERIALIZE_PTR(op_array->arg_info);
|
|
|
|
UNSERIALIZE_PTR(op_array->vars);
|
|
|
|
UNSERIALIZE_STR(op_array->function_name);
|
|
|
|
UNSERIALIZE_STR(op_array->filename);
|
2017-03-03 21:12:41 +08:00
|
|
|
UNSERIALIZE_PTR(op_array->live_range);
|
2017-03-03 21:10:46 +08:00
|
|
|
UNSERIALIZE_PTR(op_array->scope);
|
|
|
|
UNSERIALIZE_STR(op_array->doc_comment);
|
2020-05-25 02:57:00 +08:00
|
|
|
UNSERIALIZE_ATTRIBUTES(op_array->attributes);
|
2017-03-03 21:10:46 +08:00
|
|
|
UNSERIALIZE_PTR(op_array->try_catch_array);
|
|
|
|
UNSERIALIZE_PTR(op_array->prototype);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:42:13 +08:00
|
|
|
if (op_array->literals) {
|
2015-05-07 04:46:49 +08:00
|
|
|
zval *p, *end;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(op_array->literals);
|
|
|
|
p = op_array->literals;
|
|
|
|
end = p + op_array->last_literal;
|
|
|
|
while (p < end) {
|
|
|
|
zend_file_cache_unserialize_zval(p, script, buf);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:42:13 +08:00
|
|
|
{
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_op *opline, *end;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(op_array->opcodes);
|
|
|
|
opline = op_array->opcodes;
|
|
|
|
end = opline + op_array->last;
|
|
|
|
while (opline < end) {
|
2017-10-04 21:53:01 +08:00
|
|
|
#if ZEND_USE_ABS_CONST_ADDR
|
2015-11-12 07:02:24 +08:00
|
|
|
if (opline->op1_type == IS_CONST) {
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(opline->op1.zv);
|
|
|
|
}
|
2015-11-12 07:02:24 +08:00
|
|
|
if (opline->op2_type == IS_CONST) {
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(opline->op2.zv);
|
|
|
|
}
|
2017-10-04 21:53:01 +08:00
|
|
|
#else
|
|
|
|
if (opline->op1_type == IS_CONST) {
|
|
|
|
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1);
|
|
|
|
}
|
|
|
|
if (opline->op2_type == IS_CONST) {
|
|
|
|
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if ZEND_USE_ABS_JMP_ADDR
|
2015-05-07 04:46:49 +08:00
|
|
|
switch (opline->opcode) {
|
|
|
|
case ZEND_JMP:
|
|
|
|
case ZEND_FAST_CALL:
|
|
|
|
UNSERIALIZE_PTR(opline->op1.jmp_addr);
|
|
|
|
break;
|
|
|
|
case ZEND_JMPZNZ:
|
|
|
|
/* relative extended_value don't have to be changed */
|
|
|
|
/* break omitted intentionally */
|
|
|
|
case ZEND_JMPZ:
|
|
|
|
case ZEND_JMPNZ:
|
|
|
|
case ZEND_JMPZ_EX:
|
|
|
|
case ZEND_JMPNZ_EX:
|
|
|
|
case ZEND_JMP_SET:
|
|
|
|
case ZEND_COALESCE:
|
|
|
|
case ZEND_FE_RESET_R:
|
|
|
|
case ZEND_FE_RESET_RW:
|
|
|
|
case ZEND_ASSERT_CHECK:
|
2020-05-24 18:42:48 +08:00
|
|
|
case ZEND_JMP_NULL:
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(opline->op2.jmp_addr);
|
|
|
|
break;
|
2018-02-01 03:39:30 +08:00
|
|
|
case ZEND_CATCH:
|
2018-02-06 00:41:47 +08:00
|
|
|
if (!(opline->extended_value & ZEND_LAST_CATCH)) {
|
2018-02-01 03:39:30 +08:00
|
|
|
UNSERIALIZE_PTR(opline->op2.jmp_addr);
|
|
|
|
}
|
|
|
|
break;
|
2015-05-13 17:55:42 +08:00
|
|
|
case ZEND_FE_FETCH_R:
|
|
|
|
case ZEND_FE_FETCH_RW:
|
2017-03-18 06:45:05 +08:00
|
|
|
case ZEND_SWITCH_LONG:
|
|
|
|
case ZEND_SWITCH_STRING:
|
2015-05-13 17:55:42 +08:00
|
|
|
/* relative extended_value don't have to be changed */
|
|
|
|
break;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
2017-10-04 21:53:01 +08:00
|
|
|
#endif
|
2016-03-18 03:00:27 +08:00
|
|
|
zend_deserialize_opcode_handler(opline);
|
2015-05-07 04:46:49 +08:00
|
|
|
opline++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->arg_info) {
|
|
|
|
zend_arg_info *p, *end;
|
|
|
|
UNSERIALIZE_PTR(op_array->arg_info);
|
|
|
|
p = op_array->arg_info;
|
|
|
|
end = p + op_array->num_args;
|
|
|
|
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
while (p < end) {
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(p->name)) {
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(p->name);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
2019-09-25 19:21:13 +08:00
|
|
|
zend_file_cache_unserialize_type(&p->type, script, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op_array->vars) {
|
|
|
|
zend_string **p, **end;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(op_array->vars);
|
|
|
|
p = op_array->vars;
|
|
|
|
end = p + op_array->last_var;
|
|
|
|
while (p < end) {
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(*p)) {
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(*p);
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(op_array->function_name);
|
|
|
|
UNSERIALIZE_STR(op_array->filename);
|
2015-11-11 02:48:03 +08:00
|
|
|
UNSERIALIZE_PTR(op_array->live_range);
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(op_array->scope);
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(op_array->doc_comment);
|
2020-05-25 02:57:00 +08:00
|
|
|
UNSERIALIZE_ATTRIBUTES(op_array->attributes);
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(op_array->try_catch_array);
|
|
|
|
UNSERIALIZE_PTR(op_array->prototype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_unserialize_func(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
zend_op_array *op_array;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
op_array = Z_PTR_P(zv);
|
|
|
|
zend_file_cache_unserialize_op_array(op_array, script, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void zend_file_cache_unserialize_prop_info(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_property_info *prop;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
prop = Z_PTR_P(zv);
|
|
|
|
|
2018-05-03 17:10:33 +08:00
|
|
|
ZEND_ASSERT(prop->ce != NULL && prop->name != NULL);
|
|
|
|
if (!IS_UNSERIALIZED(prop->ce)) {
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(prop->ce);
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(prop->name);
|
2018-05-03 17:10:33 +08:00
|
|
|
if (prop->doc_comment) {
|
|
|
|
UNSERIALIZE_STR(prop->doc_comment);
|
|
|
|
}
|
2020-05-25 02:57:00 +08:00
|
|
|
UNSERIALIZE_ATTRIBUTES(prop->attributes);
|
2019-09-25 19:21:13 +08:00
|
|
|
zend_file_cache_unserialize_type(&prop->type, script, buf);
|
2019-01-07 19:28:51 +08:00
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-08 17:40:42 +08:00
|
|
|
static void zend_file_cache_unserialize_class_constant(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
2018-04-28 18:26:32 +08:00
|
|
|
if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
|
2015-12-08 17:40:42 +08:00
|
|
|
zend_class_constant *c;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
c = Z_PTR_P(zv);
|
|
|
|
|
2018-05-03 17:10:33 +08:00
|
|
|
ZEND_ASSERT(c->ce != NULL);
|
|
|
|
if (!IS_UNSERIALIZED(c->ce)) {
|
2015-12-08 17:40:42 +08:00
|
|
|
UNSERIALIZE_PTR(c->ce);
|
2018-05-03 17:10:33 +08:00
|
|
|
|
|
|
|
zend_file_cache_unserialize_zval(&c->value, script, buf);
|
|
|
|
|
|
|
|
if (c->doc_comment) {
|
|
|
|
UNSERIALIZE_STR(c->doc_comment);
|
|
|
|
}
|
2020-05-25 02:57:00 +08:00
|
|
|
UNSERIALIZE_ATTRIBUTES(c->attributes);
|
2015-12-08 17:40:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static void zend_file_cache_unserialize_class(zval *zv,
|
|
|
|
zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
zend_class_entry *ce;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(Z_PTR_P(zv));
|
|
|
|
ce = Z_PTR_P(zv);
|
|
|
|
|
2015-05-07 16:36:01 +08:00
|
|
|
UNSERIALIZE_STR(ce->name);
|
2018-09-18 16:41:40 +08:00
|
|
|
if (ce->parent) {
|
|
|
|
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
|
|
|
|
UNSERIALIZE_STR(ce->parent_name);
|
|
|
|
} else {
|
|
|
|
UNSERIALIZE_PTR(ce->parent);
|
|
|
|
}
|
2018-08-24 05:20:57 +08:00
|
|
|
}
|
2015-11-04 18:59:30 +08:00
|
|
|
zend_file_cache_unserialize_hash(&ce->function_table,
|
|
|
|
script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
|
2015-05-07 04:46:49 +08:00
|
|
|
if (ce->default_properties_table) {
|
|
|
|
zval *p, *end;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(ce->default_properties_table);
|
|
|
|
p = ce->default_properties_table;
|
|
|
|
end = p + ce->default_properties_count;
|
|
|
|
while (p < end) {
|
|
|
|
zend_file_cache_unserialize_zval(p, script, buf);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ce->default_static_members_table) {
|
2020-05-20 16:55:36 +08:00
|
|
|
zval *p, *end;
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(ce->default_static_members_table);
|
2020-05-20 16:55:36 +08:00
|
|
|
p = ce->default_static_members_table;
|
|
|
|
end = p + ce->default_static_members_count;
|
2015-05-07 04:46:49 +08:00
|
|
|
while (p < end) {
|
|
|
|
zend_file_cache_unserialize_zval(p, script, buf);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
2015-11-04 18:59:30 +08:00
|
|
|
zend_file_cache_unserialize_hash(&ce->constants_table,
|
2015-12-08 17:40:42 +08:00
|
|
|
script, buf, zend_file_cache_unserialize_class_constant, NULL);
|
2015-11-12 07:02:24 +08:00
|
|
|
UNSERIALIZE_STR(ce->info.user.filename);
|
|
|
|
UNSERIALIZE_STR(ce->info.user.doc_comment);
|
2020-05-25 02:57:00 +08:00
|
|
|
UNSERIALIZE_ATTRIBUTES(ce->attributes);
|
2015-11-04 18:59:30 +08:00
|
|
|
zend_file_cache_unserialize_hash(&ce->properties_info,
|
2018-03-06 05:46:19 +08:00
|
|
|
script, buf, zend_file_cache_unserialize_prop_info, NULL);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2019-01-07 19:28:51 +08:00
|
|
|
if (ce->properties_info_table) {
|
|
|
|
uint32_t i;
|
|
|
|
UNSERIALIZE_PTR(ce->properties_info_table);
|
|
|
|
|
|
|
|
for (i = 0; i < ce->default_properties_count; i++) {
|
|
|
|
UNSERIALIZE_PTR(ce->properties_info_table[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (ce->num_interfaces) {
|
|
|
|
uint32_t i;
|
|
|
|
|
2018-09-18 16:41:40 +08:00
|
|
|
ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
|
2018-08-23 22:16:28 +08:00
|
|
|
UNSERIALIZE_PTR(ce->interface_names);
|
|
|
|
|
|
|
|
for (i = 0; i < ce->num_interfaces; i++) {
|
|
|
|
UNSERIALIZE_STR(ce->interface_names[i].name);
|
|
|
|
UNSERIALIZE_STR(ce->interface_names[i].lc_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 07:02:26 +08:00
|
|
|
if (ce->num_traits) {
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(ce->trait_names);
|
|
|
|
|
|
|
|
for (i = 0; i < ce->num_traits; i++) {
|
|
|
|
UNSERIALIZE_STR(ce->trait_names[i].name);
|
|
|
|
UNSERIALIZE_STR(ce->trait_names[i].lc_name);
|
|
|
|
}
|
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (ce->trait_aliases) {
|
|
|
|
zend_trait_alias **p, *q;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
UNSERIALIZE_PTR(ce->trait_aliases);
|
|
|
|
p = ce->trait_aliases;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
while (*p) {
|
|
|
|
UNSERIALIZE_PTR(*p);
|
|
|
|
q = *p;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (q->trait_method.method_name) {
|
|
|
|
UNSERIALIZE_STR(q->trait_method.method_name);
|
|
|
|
}
|
|
|
|
if (q->trait_method.class_name) {
|
|
|
|
UNSERIALIZE_STR(q->trait_method.class_name);
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (q->alias) {
|
|
|
|
UNSERIALIZE_STR(q->alias);
|
|
|
|
}
|
|
|
|
p++;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (ce->trait_precedences) {
|
|
|
|
zend_trait_precedence **p, *q;
|
2019-01-09 05:08:40 +08:00
|
|
|
uint32_t j;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
UNSERIALIZE_PTR(ce->trait_precedences);
|
|
|
|
p = ce->trait_precedences;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
while (*p) {
|
|
|
|
UNSERIALIZE_PTR(*p);
|
|
|
|
q = *p;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
if (q->trait_method.method_name) {
|
|
|
|
UNSERIALIZE_STR(q->trait_method.method_name);
|
|
|
|
}
|
|
|
|
if (q->trait_method.class_name) {
|
|
|
|
UNSERIALIZE_STR(q->trait_method.class_name);
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-08-23 22:16:28 +08:00
|
|
|
for (j = 0; j < q->num_excludes; j++) {
|
|
|
|
UNSERIALIZE_STR(q->exclude_class_names[j]);
|
|
|
|
}
|
|
|
|
p++;
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UNSERIALIZE_PTR(ce->constructor);
|
|
|
|
UNSERIALIZE_PTR(ce->destructor);
|
|
|
|
UNSERIALIZE_PTR(ce->clone);
|
|
|
|
UNSERIALIZE_PTR(ce->__get);
|
|
|
|
UNSERIALIZE_PTR(ce->__set);
|
|
|
|
UNSERIALIZE_PTR(ce->__call);
|
2020-06-26 16:54:40 +08:00
|
|
|
UNSERIALIZE_PTR(ce->__serialize);
|
|
|
|
UNSERIALIZE_PTR(ce->__unserialize);
|
2015-05-07 04:46:49 +08:00
|
|
|
UNSERIALIZE_PTR(ce->__isset);
|
|
|
|
UNSERIALIZE_PTR(ce->__unset);
|
|
|
|
UNSERIALIZE_PTR(ce->__tostring);
|
|
|
|
UNSERIALIZE_PTR(ce->__callstatic);
|
|
|
|
UNSERIALIZE_PTR(ce->__debugInfo);
|
2015-11-04 18:59:30 +08:00
|
|
|
|
|
|
|
if (UNEXPECTED((ce->ce_flags & ZEND_ACC_ANON_CLASS))) {
|
|
|
|
ce->serialize = zend_class_serialize_deny;
|
|
|
|
ce->unserialize = zend_class_unserialize_deny;
|
|
|
|
}
|
2018-10-17 20:52:50 +08:00
|
|
|
|
|
|
|
if (ce->iterator_funcs_ptr) {
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr);
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_new_iterator);
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_rewind);
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_valid);
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_key);
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_current);
|
|
|
|
UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_next);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ce->ce_flags & ZEND_ACC_IMMUTABLE && ce->default_static_members_table) {
|
|
|
|
ZEND_MAP_PTR_NEW(ce->static_members_table);
|
|
|
|
} else {
|
|
|
|
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
|
|
|
|
}
|
2015-05-07 04:46:49 +08:00
|
|
|
}
|
|
|
|
|
2020-05-19 21:01:18 +08:00
|
|
|
static void zend_file_cache_unserialize_warnings(zend_persistent_script *script, void *buf)
|
|
|
|
{
|
|
|
|
if (script->warnings) {
|
|
|
|
UNSERIALIZE_PTR(script->warnings);
|
|
|
|
for (uint32_t i = 0; i < script->num_warnings; i++) {
|
|
|
|
UNSERIALIZE_PTR(script->warnings[i]);
|
|
|
|
UNSERIALIZE_STR(script->warnings[i]->error_filename);
|
|
|
|
UNSERIALIZE_STR(script->warnings[i]->error_message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
static void zend_file_cache_unserialize(zend_persistent_script *script,
|
|
|
|
void *buf)
|
|
|
|
{
|
|
|
|
script->mem = buf;
|
|
|
|
|
2015-11-12 07:02:24 +08:00
|
|
|
UNSERIALIZE_STR(script->script.filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2015-11-12 07:02:24 +08:00
|
|
|
zend_file_cache_unserialize_hash(&script->script.class_table,
|
2015-11-04 18:59:30 +08:00
|
|
|
script, buf, zend_file_cache_unserialize_class, ZEND_CLASS_DTOR);
|
2015-11-12 07:02:24 +08:00
|
|
|
zend_file_cache_unserialize_hash(&script->script.function_table,
|
2015-11-04 18:59:30 +08:00
|
|
|
script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
|
2015-11-12 07:02:24 +08:00
|
|
|
zend_file_cache_unserialize_op_array(&script->script.main_op_array, script, buf);
|
2020-05-19 21:01:18 +08:00
|
|
|
zend_file_cache_unserialize_warnings(script, buf);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
UNSERIALIZE_PTR(script->arena_mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle)
|
|
|
|
{
|
|
|
|
zend_string *full_path = file_handle->opened_path;
|
|
|
|
int fd;
|
|
|
|
char *filename;
|
|
|
|
zend_persistent_script *script;
|
|
|
|
zend_file_cache_metainfo info;
|
|
|
|
zend_accel_hash_entry *bucket;
|
|
|
|
void *mem, *checkpoint, *buf;
|
|
|
|
int cache_it = 1;
|
2019-10-09 16:38:11 +08:00
|
|
|
unsigned int actual_checksum;
|
2017-12-22 04:34:21 +08:00
|
|
|
int ok;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
if (!full_path) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-07-17 21:14:25 +08:00
|
|
|
filename = zend_file_cache_get_bin_file_path(full_path);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-07-14 18:51:37 +08:00
|
|
|
fd = zend_file_cache_open(filename, O_RDONLY | O_BINARY);
|
2015-05-07 04:46:49 +08:00
|
|
|
if (fd < 0) {
|
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zend_file_cache_flock(fd, LOCK_SH) != 0) {
|
|
|
|
close(fd);
|
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(fd, &info, sizeof(info)) != sizeof(info)) {
|
2018-07-14 01:01:43 +08:00
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (info)\n", filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_flock(fd, LOCK_UN);
|
|
|
|
close(fd);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* verify header */
|
2015-12-09 18:34:45 +08:00
|
|
|
if (memcmp(info.magic, "OPCACHE", 8) != 0) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename);
|
|
|
|
zend_file_cache_flock(fd, LOCK_UN);
|
|
|
|
close(fd);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-12-09 18:34:45 +08:00
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-07-17 07:31:10 +08:00
|
|
|
if (memcmp(info.system_id, zend_system_id, 32) != 0) {
|
2015-12-09 18:34:45 +08:00
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_flock(fd, LOCK_UN);
|
|
|
|
close(fd);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* verify timestamp */
|
|
|
|
if (ZCG(accel_directives).validate_timestamps &&
|
|
|
|
zend_get_file_handle_timestamp(file_handle, NULL) != info.timestamp) {
|
|
|
|
if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
|
|
|
|
}
|
|
|
|
close(fd);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
checkpoint = zend_arena_checkpoint(CG(arena));
|
2018-02-15 00:18:47 +08:00
|
|
|
#if defined(__AVX__) || defined(__SSE2__)
|
2015-05-07 04:46:49 +08:00
|
|
|
/* Align to 64-byte boundary */
|
|
|
|
mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size + 64);
|
|
|
|
mem = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
|
|
|
|
#else
|
|
|
|
mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (read(fd, mem, info.mem_size + info.str_size) != (ssize_t)(info.mem_size + info.str_size)) {
|
2018-07-14 01:01:43 +08:00
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (mem)\n", filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_file_cache_flock(fd, LOCK_UN);
|
|
|
|
close(fd);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_arena_release(&CG(arena), checkpoint);
|
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
/* verify checksum */
|
|
|
|
if (ZCG(accel_directives).file_cache_consistency_checks &&
|
2019-10-09 16:38:11 +08:00
|
|
|
(actual_checksum = zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size)) != info.checksum) {
|
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s' excepted checksum: 0x%08x actual checksum: 0x%08x\n", filename, info.checksum, actual_checksum);
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_arena_release(&CG(arena), checkpoint);
|
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-05 21:01:43 +08:00
|
|
|
if (!file_cache_only &&
|
2016-02-25 02:15:53 +08:00
|
|
|
!ZCSG(restart_in_progress) &&
|
2017-12-22 04:34:21 +08:00
|
|
|
!ZSMMG(memory_exhausted) &&
|
2016-02-25 02:15:53 +08:00
|
|
|
accelerator_shm_read_lock() == SUCCESS) {
|
2015-05-07 04:46:49 +08:00
|
|
|
/* exclusive lock */
|
|
|
|
zend_shared_alloc_lock();
|
|
|
|
|
|
|
|
/* Check if we still need to put the file into the cache (may be it was
|
|
|
|
* already stored by another process. This final check is done under
|
|
|
|
* exclusive lock) */
|
|
|
|
bucket = zend_accel_hash_find_entry(&ZCSG(hash), full_path);
|
|
|
|
if (bucket) {
|
|
|
|
script = (zend_persistent_script *)bucket->data;
|
|
|
|
if (!script->corrupted) {
|
|
|
|
zend_shared_alloc_unlock();
|
|
|
|
zend_arena_release(&CG(arena), checkpoint);
|
|
|
|
efree(filename);
|
|
|
|
return script;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zend_accel_hash_is_full(&ZCSG(hash))) {
|
|
|
|
zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
|
|
|
|
ZSMMG(memory_exhausted) = 1;
|
|
|
|
zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
|
|
|
|
zend_shared_alloc_unlock();
|
|
|
|
goto use_process_mem;
|
|
|
|
}
|
|
|
|
|
2018-02-15 00:18:47 +08:00
|
|
|
#if defined(__AVX__) || defined(__SSE2__)
|
2015-05-07 04:46:49 +08:00
|
|
|
/* Align to 64-byte boundary */
|
|
|
|
buf = zend_shared_alloc(info.mem_size + 64);
|
|
|
|
buf = (void*)(((zend_uintptr_t)buf + 63L) & ~63L);
|
|
|
|
#else
|
|
|
|
buf = zend_shared_alloc(info.mem_size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!buf) {
|
|
|
|
zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
|
|
|
|
zend_shared_alloc_unlock();
|
|
|
|
goto use_process_mem;
|
|
|
|
}
|
|
|
|
memcpy(buf, mem, info.mem_size);
|
2018-10-17 20:52:50 +08:00
|
|
|
zend_map_ptr_extend(ZCSG(map_ptr_last));
|
2015-05-07 04:46:49 +08:00
|
|
|
} else {
|
|
|
|
use_process_mem:
|
|
|
|
buf = mem;
|
|
|
|
cache_it = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZCG(mem) = ((char*)mem + info.mem_size);
|
|
|
|
script = (zend_persistent_script*)((char*)buf + info.script_offset);
|
2015-05-21 04:33:55 +08:00
|
|
|
script->corrupted = !cache_it; /* used to check if script restored to SHM or process memory */
|
2017-12-19 02:04:41 +08:00
|
|
|
|
2017-12-22 04:34:21 +08:00
|
|
|
ok = 1;
|
2017-12-19 02:04:41 +08:00
|
|
|
zend_try {
|
|
|
|
zend_file_cache_unserialize(script, buf);
|
|
|
|
} zend_catch {
|
2017-12-22 04:34:21 +08:00
|
|
|
ok = 0;
|
2017-12-19 02:04:41 +08:00
|
|
|
} zend_end_try();
|
2017-12-22 04:34:21 +08:00
|
|
|
if (!ok) {
|
|
|
|
if (cache_it) {
|
|
|
|
zend_shared_alloc_unlock();
|
|
|
|
goto use_process_mem;
|
|
|
|
} else {
|
|
|
|
zend_arena_release(&CG(arena), checkpoint);
|
|
|
|
efree(filename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2017-12-19 02:04:41 +08:00
|
|
|
|
2015-05-07 16:36:01 +08:00
|
|
|
script->corrupted = 0;
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
if (cache_it) {
|
2018-10-17 20:52:50 +08:00
|
|
|
ZCSG(map_ptr_last) = CG(map_ptr_last);
|
2015-05-07 04:46:49 +08:00
|
|
|
script->dynamic_members.checksum = zend_accel_script_checksum(script);
|
2016-02-25 02:15:53 +08:00
|
|
|
script->dynamic_members.last_used = ZCG(request_time);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2015-11-12 07:02:24 +08:00
|
|
|
zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->script.filename), ZSTR_LEN(script->script.filename), 0, script);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
|
|
|
zend_shared_alloc_unlock();
|
2019-10-09 16:38:11 +08:00
|
|
|
zend_accel_error(ACCEL_LOG_INFO, "File cached script loaded into memory '%s'", ZSTR_VAL(script->script.filename));
|
|
|
|
|
2015-05-07 04:46:49 +08:00
|
|
|
zend_arena_release(&CG(arena), checkpoint);
|
|
|
|
}
|
|
|
|
efree(filename);
|
|
|
|
|
|
|
|
return script;
|
|
|
|
}
|
|
|
|
|
|
|
|
void zend_file_cache_invalidate(zend_string *full_path)
|
|
|
|
{
|
|
|
|
char *filename;
|
|
|
|
|
2015-07-17 21:14:25 +08:00
|
|
|
filename = zend_file_cache_get_bin_file_path(full_path);
|
2015-05-07 04:46:49 +08:00
|
|
|
|
2018-07-14 18:51:37 +08:00
|
|
|
zend_file_cache_unlink(filename);
|
2015-05-07 04:46:49 +08:00
|
|
|
efree(filename);
|
|
|
|
}
|