zend_file_cache.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend OPcache |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Dmitry Stogov <dmitry@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "zend.h"
  19. #include "zend_virtual_cwd.h"
  20. #include "zend_compile.h"
  21. #include "zend_vm.h"
  22. #include "zend_interfaces.h"
  23. #include "zend_attributes.h"
  24. #include "zend_system_id.h"
  25. #include "php.h"
  26. #ifdef ZEND_WIN32
  27. #include "ext/standard/md5.h"
  28. #endif
  29. #include "ZendAccelerator.h"
  30. #include "zend_file_cache.h"
  31. #include "zend_shared_alloc.h"
  32. #include "zend_accelerator_util_funcs.h"
  33. #include "zend_accelerator_hash.h"
  34. #if HAVE_JIT
  35. #include "jit/zend_jit.h"
  36. #endif
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <fcntl.h>
  40. #if HAVE_UNISTD_H
  41. #include <unistd.h>
  42. #endif
  43. #ifdef HAVE_SYS_UIO_H
  44. # include <sys/uio.h>
  45. #endif
  46. #ifdef HAVE_SYS_FILE_H
  47. # include <sys/file.h>
  48. #endif
  49. #if __has_feature(memory_sanitizer)
  50. # include <sanitizer/msan_interface.h>
  51. #endif
  52. #ifndef ZEND_WIN32
  53. #define zend_file_cache_unlink unlink
  54. #define zend_file_cache_open open
  55. #else
  56. #define zend_file_cache_unlink php_win32_ioutil_unlink
  57. #define zend_file_cache_open php_win32_ioutil_open
  58. #endif
  59. #ifdef ZEND_WIN32
  60. # define LOCK_SH 0
  61. # define LOCK_EX 1
  62. # define LOCK_UN 2
  63. static int zend_file_cache_flock(int fd, int op)
  64. {
  65. OVERLAPPED offset = {0,0,0,0,NULL};
  66. if (op == LOCK_EX) {
  67. if (LockFileEx((HANDLE)_get_osfhandle(fd),
  68. LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset) == TRUE) {
  69. return 0;
  70. }
  71. } else if (op == LOCK_SH) {
  72. if (LockFileEx((HANDLE)_get_osfhandle(fd),
  73. 0, 0, 1, 0, &offset) == TRUE) {
  74. return 0;
  75. }
  76. } else if (op == LOCK_UN) {
  77. if (UnlockFileEx((HANDLE)_get_osfhandle(fd),
  78. 0, 1, 0, &offset) == TRUE) {
  79. return 0;
  80. }
  81. }
  82. return -1;
  83. }
  84. #elif defined(HAVE_FLOCK)
  85. # define zend_file_cache_flock flock
  86. #else
  87. # define LOCK_SH 0
  88. # define LOCK_EX 1
  89. # define LOCK_UN 2
  90. static int zend_file_cache_flock(int fd, int type)
  91. {
  92. return 0;
  93. }
  94. #endif
  95. #ifndef O_BINARY
  96. # define O_BINARY 0
  97. #endif
  98. #define SUFFIX ".bin"
  99. #define IS_SERIALIZED_INTERNED(ptr) \
  100. ((size_t)(ptr) & Z_UL(1))
  101. /* Allowing == on the upper bound accounts for a potential empty allocation at the end of the
  102. * memory region. This can also happen for a return-type-only arg_info, where &arg_info[1] is
  103. * stored, which may point to the end of the region. */
  104. #define IS_SERIALIZED(ptr) \
  105. ((char*)(ptr) <= (char*)script->size)
  106. #define IS_UNSERIALIZED(ptr) \
  107. (((char*)(ptr) >= (char*)script->mem && (char*)(ptr) <= (char*)script->mem + script->size) || \
  108. IS_ACCEL_INTERNED(ptr))
  109. #define SERIALIZE_PTR(ptr) do { \
  110. if (ptr) { \
  111. ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
  112. (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
  113. } \
  114. } while (0)
  115. #define UNSERIALIZE_PTR(ptr) do { \
  116. if (ptr) { \
  117. ZEND_ASSERT(IS_SERIALIZED(ptr)); \
  118. (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
  119. } \
  120. } while (0)
  121. #define SERIALIZE_STR(ptr) do { \
  122. if (ptr) { \
  123. if (IS_ACCEL_INTERNED(ptr)) { \
  124. (ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \
  125. } else { \
  126. ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
  127. /* script->corrupted shows if the script in SHM or not */ \
  128. if (EXPECTED(script->corrupted)) { \
  129. GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
  130. GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
  131. } \
  132. (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
  133. } \
  134. } \
  135. } while (0)
  136. #define UNSERIALIZE_STR(ptr) do { \
  137. if (ptr) { \
  138. if (IS_SERIALIZED_INTERNED(ptr)) { \
  139. (ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), !script->corrupted); \
  140. } else { \
  141. ZEND_ASSERT(IS_SERIALIZED(ptr)); \
  142. (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
  143. /* script->corrupted shows if the script in SHM or not */ \
  144. if (EXPECTED(!script->corrupted)) { \
  145. GC_ADD_FLAGS(ptr, IS_STR_INTERNED | IS_STR_PERMANENT); \
  146. } else { \
  147. GC_ADD_FLAGS(ptr, IS_STR_INTERNED); \
  148. GC_DEL_FLAGS(ptr, IS_STR_PERMANENT); \
  149. } \
  150. } \
  151. } \
  152. } while (0)
  153. #define SERIALIZE_ATTRIBUTES(attributes) do { \
  154. if ((attributes) && !IS_SERIALIZED(attributes)) { \
  155. HashTable *ht; \
  156. SERIALIZE_PTR(attributes); \
  157. ht = (attributes); \
  158. UNSERIALIZE_PTR(ht); \
  159. zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_attribute); \
  160. } \
  161. } while (0)
  162. #define UNSERIALIZE_ATTRIBUTES(attributes) do { \
  163. if ((attributes) && !IS_UNSERIALIZED(attributes)) { \
  164. HashTable *ht; \
  165. UNSERIALIZE_PTR(attributes); \
  166. ht = (attributes); \
  167. zend_file_cache_unserialize_hash(ht, script, buf, zend_file_cache_unserialize_attribute, NULL); \
  168. } \
  169. } while (0)
  170. static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
  171. {HT_INVALID_IDX, HT_INVALID_IDX};
  172. typedef struct _zend_file_cache_metainfo {
  173. char magic[8];
  174. char system_id[32];
  175. size_t mem_size;
  176. size_t str_size;
  177. size_t script_offset;
  178. accel_time_t timestamp;
  179. uint32_t checksum;
  180. } zend_file_cache_metainfo;
  181. static int zend_file_cache_mkdir(char *filename, size_t start)
  182. {
  183. char *s = filename + start;
  184. while (*s) {
  185. if (IS_SLASH(*s)) {
  186. char old = *s;
  187. *s = '\000';
  188. #ifndef ZEND_WIN32
  189. if (mkdir(filename, S_IRWXU) < 0 && errno != EEXIST) {
  190. #else
  191. if (php_win32_ioutil_mkdir(filename, 0700) < 0 && errno != EEXIST) {
  192. #endif
  193. *s = old;
  194. return FAILURE;
  195. }
  196. *s = old;
  197. }
  198. s++;
  199. }
  200. return SUCCESS;
  201. }
  202. typedef void (*serialize_callback_t)(zval *zv,
  203. zend_persistent_script *script,
  204. zend_file_cache_metainfo *info,
  205. void *buf);
  206. typedef void (*unserialize_callback_t)(zval *zv,
  207. zend_persistent_script *script,
  208. void *buf);
  209. static void zend_file_cache_serialize_zval(zval *zv,
  210. zend_persistent_script *script,
  211. zend_file_cache_metainfo *info,
  212. void *buf);
  213. static void zend_file_cache_unserialize_zval(zval *zv,
  214. zend_persistent_script *script,
  215. void *buf);
  216. static void *zend_file_cache_serialize_interned(zend_string *str,
  217. zend_file_cache_metainfo *info)
  218. {
  219. size_t len;
  220. void *ret;
  221. /* check if the same interned string was already stored */
  222. ret = zend_shared_alloc_get_xlat_entry(str);
  223. if (ret) {
  224. return ret;
  225. }
  226. len = ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str)));
  227. ret = (void*)(info->str_size | Z_UL(1));
  228. zend_shared_alloc_register_xlat_entry(str, ret);
  229. if (info->str_size + len > ZSTR_LEN((zend_string*)ZCG(mem))) {
  230. size_t new_len = info->str_size + len;
  231. ZCG(mem) = (void*)zend_string_realloc(
  232. (zend_string*)ZCG(mem),
  233. ((_ZSTR_HEADER_SIZE + 1 + new_len + 4095) & ~0xfff) - (_ZSTR_HEADER_SIZE + 1),
  234. 0);
  235. }
  236. zend_string *new_str = (zend_string *) (ZSTR_VAL((zend_string*)ZCG(mem)) + info->str_size);
  237. memcpy(new_str, str, len);
  238. GC_ADD_FLAGS(new_str, IS_STR_INTERNED);
  239. GC_DEL_FLAGS(new_str, IS_STR_PERMANENT|IS_STR_CLASS_NAME_MAP_PTR);
  240. info->str_size += len;
  241. return ret;
  242. }
  243. static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
  244. {
  245. str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1)));
  246. if (!in_shm) {
  247. return str;
  248. }
  249. zend_string *ret = accel_new_interned_string(str);
  250. if (ret == str) {
  251. /* We have to create new SHM allocated string */
  252. size_t size = _ZSTR_STRUCT_SIZE(ZSTR_LEN(str));
  253. ret = zend_shared_alloc(size);
  254. if (!ret) {
  255. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
  256. LONGJMP(*EG(bailout), FAILURE);
  257. }
  258. memcpy(ret, str, size);
  259. /* String wasn't interned but we will use it as interned anyway */
  260. GC_SET_REFCOUNT(ret, 1);
  261. GC_TYPE_INFO(ret) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERSISTENT | IS_STR_PERMANENT) << GC_FLAGS_SHIFT);
  262. }
  263. return ret;
  264. }
  265. static void zend_file_cache_serialize_hash(HashTable *ht,
  266. zend_persistent_script *script,
  267. zend_file_cache_metainfo *info,
  268. void *buf,
  269. serialize_callback_t func)
  270. {
  271. Bucket *p, *end;
  272. if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) {
  273. ht->arData = NULL;
  274. return;
  275. }
  276. if (IS_SERIALIZED(ht->arData)) {
  277. return;
  278. }
  279. SERIALIZE_PTR(ht->arData);
  280. p = ht->arData;
  281. UNSERIALIZE_PTR(p);
  282. end = p + ht->nNumUsed;
  283. while (p < end) {
  284. if (Z_TYPE(p->val) != IS_UNDEF) {
  285. SERIALIZE_STR(p->key);
  286. func(&p->val, script, info, buf);
  287. }
  288. p++;
  289. }
  290. }
  291. static void zend_file_cache_serialize_ast(zend_ast *ast,
  292. zend_persistent_script *script,
  293. zend_file_cache_metainfo *info,
  294. void *buf)
  295. {
  296. uint32_t i;
  297. zend_ast *tmp;
  298. if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
  299. zend_file_cache_serialize_zval(&((zend_ast_zval*)ast)->val, script, info, buf);
  300. } else if (zend_ast_is_list(ast)) {
  301. zend_ast_list *list = zend_ast_get_list(ast);
  302. for (i = 0; i < list->children; i++) {
  303. if (list->child[i] && !IS_SERIALIZED(list->child[i])) {
  304. SERIALIZE_PTR(list->child[i]);
  305. tmp = list->child[i];
  306. UNSERIALIZE_PTR(tmp);
  307. zend_file_cache_serialize_ast(tmp, script, info, buf);
  308. }
  309. }
  310. } else {
  311. uint32_t children = zend_ast_get_num_children(ast);
  312. for (i = 0; i < children; i++) {
  313. if (ast->child[i] && !IS_SERIALIZED(ast->child[i])) {
  314. SERIALIZE_PTR(ast->child[i]);
  315. tmp = ast->child[i];
  316. UNSERIALIZE_PTR(tmp);
  317. zend_file_cache_serialize_ast(tmp, script, info, buf);
  318. }
  319. }
  320. }
  321. }
  322. static void zend_file_cache_serialize_zval(zval *zv,
  323. zend_persistent_script *script,
  324. zend_file_cache_metainfo *info,
  325. void *buf)
  326. {
  327. switch (Z_TYPE_P(zv)) {
  328. case IS_STRING:
  329. if (!IS_SERIALIZED(Z_STR_P(zv))) {
  330. SERIALIZE_STR(Z_STR_P(zv));
  331. }
  332. break;
  333. case IS_ARRAY:
  334. if (!IS_SERIALIZED(Z_ARR_P(zv))) {
  335. HashTable *ht;
  336. SERIALIZE_PTR(Z_ARR_P(zv));
  337. ht = Z_ARR_P(zv);
  338. UNSERIALIZE_PTR(ht);
  339. zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
  340. }
  341. break;
  342. case IS_CONSTANT_AST:
  343. if (!IS_SERIALIZED(Z_AST_P(zv))) {
  344. zend_ast_ref *ast;
  345. SERIALIZE_PTR(Z_AST_P(zv));
  346. ast = Z_AST_P(zv);
  347. UNSERIALIZE_PTR(ast);
  348. zend_file_cache_serialize_ast(GC_AST(ast), script, info, buf);
  349. }
  350. break;
  351. case IS_INDIRECT:
  352. /* Used by static properties. */
  353. SERIALIZE_PTR(Z_INDIRECT_P(zv));
  354. break;
  355. default:
  356. ZEND_ASSERT(Z_TYPE_P(zv) < IS_STRING);
  357. break;
  358. }
  359. }
  360. static void zend_file_cache_serialize_attribute(zval *zv,
  361. zend_persistent_script *script,
  362. zend_file_cache_metainfo *info,
  363. void *buf)
  364. {
  365. zend_attribute *attr = Z_PTR_P(zv);
  366. uint32_t i;
  367. SERIALIZE_PTR(Z_PTR_P(zv));
  368. attr = Z_PTR_P(zv);
  369. UNSERIALIZE_PTR(attr);
  370. SERIALIZE_STR(attr->name);
  371. SERIALIZE_STR(attr->lcname);
  372. for (i = 0; i < attr->argc; i++) {
  373. SERIALIZE_STR(attr->args[i].name);
  374. zend_file_cache_serialize_zval(&attr->args[i].value, script, info, buf);
  375. }
  376. }
  377. static void zend_file_cache_serialize_type(
  378. zend_type *type, zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
  379. {
  380. if (ZEND_TYPE_HAS_LIST(*type)) {
  381. zend_type_list *list = ZEND_TYPE_LIST(*type);
  382. SERIALIZE_PTR(list);
  383. ZEND_TYPE_SET_PTR(*type, list);
  384. UNSERIALIZE_PTR(list);
  385. zend_type *list_type;
  386. ZEND_TYPE_LIST_FOREACH(list, list_type) {
  387. zend_file_cache_serialize_type(list_type, script, info, buf);
  388. } ZEND_TYPE_LIST_FOREACH_END();
  389. } else if (ZEND_TYPE_HAS_NAME(*type)) {
  390. zend_string *type_name = ZEND_TYPE_NAME(*type);
  391. SERIALIZE_STR(type_name);
  392. ZEND_TYPE_SET_PTR(*type, type_name);
  393. }
  394. }
  395. static void zend_file_cache_serialize_op_array(zend_op_array *op_array,
  396. zend_persistent_script *script,
  397. zend_file_cache_metainfo *info,
  398. void *buf)
  399. {
  400. ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, NULL);
  401. ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
  402. /* Check whether this op_array has already been serialized. */
  403. if (IS_SERIALIZED(op_array->opcodes)) {
  404. ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
  405. return;
  406. }
  407. if (op_array->scope) {
  408. if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
  409. op_array->refcount = (uint32_t*)(intptr_t)-1;
  410. SERIALIZE_PTR(op_array->static_variables);
  411. SERIALIZE_PTR(op_array->literals);
  412. SERIALIZE_PTR(op_array->opcodes);
  413. SERIALIZE_PTR(op_array->arg_info);
  414. SERIALIZE_PTR(op_array->vars);
  415. SERIALIZE_STR(op_array->function_name);
  416. SERIALIZE_STR(op_array->filename);
  417. SERIALIZE_PTR(op_array->live_range);
  418. SERIALIZE_PTR(op_array->scope);
  419. SERIALIZE_STR(op_array->doc_comment);
  420. SERIALIZE_ATTRIBUTES(op_array->attributes);
  421. SERIALIZE_PTR(op_array->try_catch_array);
  422. SERIALIZE_PTR(op_array->prototype);
  423. return;
  424. }
  425. zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes);
  426. }
  427. if (op_array->static_variables) {
  428. HashTable *ht;
  429. SERIALIZE_PTR(op_array->static_variables);
  430. ht = op_array->static_variables;
  431. UNSERIALIZE_PTR(ht);
  432. zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
  433. }
  434. if (op_array->literals) {
  435. zval *p, *end;
  436. SERIALIZE_PTR(op_array->literals);
  437. p = op_array->literals;
  438. UNSERIALIZE_PTR(p);
  439. end = p + op_array->last_literal;
  440. while (p < end) {
  441. zend_file_cache_serialize_zval(p, script, info, buf);
  442. p++;
  443. }
  444. }
  445. {
  446. zend_op *opline, *end;
  447. #if !ZEND_USE_ABS_CONST_ADDR
  448. zval *literals = op_array->literals;
  449. UNSERIALIZE_PTR(literals);
  450. #endif
  451. SERIALIZE_PTR(op_array->opcodes);
  452. opline = op_array->opcodes;
  453. UNSERIALIZE_PTR(opline);
  454. end = opline + op_array->last;
  455. while (opline < end) {
  456. #if ZEND_USE_ABS_CONST_ADDR
  457. if (opline->op1_type == IS_CONST) {
  458. SERIALIZE_PTR(opline->op1.zv);
  459. }
  460. if (opline->op2_type == IS_CONST) {
  461. SERIALIZE_PTR(opline->op2.zv);
  462. }
  463. #else
  464. if (opline->op1_type == IS_CONST) {
  465. opline->op1.constant = RT_CONSTANT(opline, opline->op1) - literals;
  466. }
  467. if (opline->op2_type == IS_CONST) {
  468. opline->op2.constant = RT_CONSTANT(opline, opline->op2) - literals;
  469. }
  470. #endif
  471. #if ZEND_USE_ABS_JMP_ADDR
  472. switch (opline->opcode) {
  473. case ZEND_JMP:
  474. case ZEND_FAST_CALL:
  475. SERIALIZE_PTR(opline->op1.jmp_addr);
  476. break;
  477. case ZEND_JMPZNZ:
  478. /* relative extended_value don't have to be changed */
  479. /* break omitted intentionally */
  480. case ZEND_JMPZ:
  481. case ZEND_JMPNZ:
  482. case ZEND_JMPZ_EX:
  483. case ZEND_JMPNZ_EX:
  484. case ZEND_JMP_SET:
  485. case ZEND_COALESCE:
  486. case ZEND_FE_RESET_R:
  487. case ZEND_FE_RESET_RW:
  488. case ZEND_ASSERT_CHECK:
  489. case ZEND_JMP_NULL:
  490. SERIALIZE_PTR(opline->op2.jmp_addr);
  491. break;
  492. case ZEND_CATCH:
  493. if (!(opline->extended_value & ZEND_LAST_CATCH)) {
  494. SERIALIZE_PTR(opline->op2.jmp_addr);
  495. }
  496. break;
  497. case ZEND_FE_FETCH_R:
  498. case ZEND_FE_FETCH_RW:
  499. case ZEND_SWITCH_LONG:
  500. case ZEND_SWITCH_STRING:
  501. case ZEND_MATCH:
  502. /* relative extended_value don't have to be changed */
  503. break;
  504. }
  505. #endif
  506. zend_serialize_opcode_handler(opline);
  507. opline++;
  508. }
  509. if (op_array->arg_info) {
  510. zend_arg_info *p, *end;
  511. SERIALIZE_PTR(op_array->arg_info);
  512. p = op_array->arg_info;
  513. UNSERIALIZE_PTR(p);
  514. end = p + op_array->num_args;
  515. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  516. p--;
  517. }
  518. if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
  519. end++;
  520. }
  521. while (p < end) {
  522. if (!IS_SERIALIZED(p->name)) {
  523. SERIALIZE_STR(p->name);
  524. }
  525. zend_file_cache_serialize_type(&p->type, script, info, buf);
  526. p++;
  527. }
  528. }
  529. if (op_array->vars) {
  530. zend_string **p, **end;
  531. SERIALIZE_PTR(op_array->vars);
  532. p = op_array->vars;
  533. UNSERIALIZE_PTR(p);
  534. end = p + op_array->last_var;
  535. while (p < end) {
  536. if (!IS_SERIALIZED(*p)) {
  537. SERIALIZE_STR(*p);
  538. }
  539. p++;
  540. }
  541. }
  542. if (op_array->num_dynamic_func_defs) {
  543. zend_op_array **defs;
  544. SERIALIZE_PTR(op_array->dynamic_func_defs);
  545. defs = op_array->dynamic_func_defs;
  546. UNSERIALIZE_PTR(defs);
  547. for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
  548. zend_op_array *def;
  549. SERIALIZE_PTR(defs[i]);
  550. def = defs[i];
  551. UNSERIALIZE_PTR(def);
  552. zend_file_cache_serialize_op_array(def, script, info, buf);
  553. }
  554. }
  555. SERIALIZE_STR(op_array->function_name);
  556. SERIALIZE_STR(op_array->filename);
  557. SERIALIZE_PTR(op_array->live_range);
  558. SERIALIZE_PTR(op_array->scope);
  559. SERIALIZE_STR(op_array->doc_comment);
  560. SERIALIZE_ATTRIBUTES(op_array->attributes);
  561. SERIALIZE_PTR(op_array->try_catch_array);
  562. SERIALIZE_PTR(op_array->prototype);
  563. }
  564. }
  565. static void zend_file_cache_serialize_func(zval *zv,
  566. zend_persistent_script *script,
  567. zend_file_cache_metainfo *info,
  568. void *buf)
  569. {
  570. zend_function *func;
  571. SERIALIZE_PTR(Z_PTR_P(zv));
  572. func = Z_PTR_P(zv);
  573. UNSERIALIZE_PTR(func);
  574. ZEND_ASSERT(func->type == ZEND_USER_FUNCTION);
  575. zend_file_cache_serialize_op_array(&func->op_array, script, info, buf);
  576. }
  577. static void zend_file_cache_serialize_prop_info(zval *zv,
  578. zend_persistent_script *script,
  579. zend_file_cache_metainfo *info,
  580. void *buf)
  581. {
  582. if (!IS_SERIALIZED(Z_PTR_P(zv))) {
  583. zend_property_info *prop;
  584. SERIALIZE_PTR(Z_PTR_P(zv));
  585. prop = Z_PTR_P(zv);
  586. UNSERIALIZE_PTR(prop);
  587. ZEND_ASSERT(prop->ce != NULL && prop->name != NULL);
  588. if (!IS_SERIALIZED(prop->ce)) {
  589. SERIALIZE_PTR(prop->ce);
  590. SERIALIZE_STR(prop->name);
  591. if (prop->doc_comment) {
  592. SERIALIZE_STR(prop->doc_comment);
  593. }
  594. SERIALIZE_ATTRIBUTES(prop->attributes);
  595. zend_file_cache_serialize_type(&prop->type, script, info, buf);
  596. }
  597. }
  598. }
  599. static void zend_file_cache_serialize_class_constant(zval *zv,
  600. zend_persistent_script *script,
  601. zend_file_cache_metainfo *info,
  602. void *buf)
  603. {
  604. if (!IS_SERIALIZED(Z_PTR_P(zv))) {
  605. zend_class_constant *c;
  606. SERIALIZE_PTR(Z_PTR_P(zv));
  607. c = Z_PTR_P(zv);
  608. UNSERIALIZE_PTR(c);
  609. ZEND_ASSERT(c->ce != NULL);
  610. if (!IS_SERIALIZED(c->ce)) {
  611. SERIALIZE_PTR(c->ce);
  612. zend_file_cache_serialize_zval(&c->value, script, info, buf);
  613. if (c->doc_comment) {
  614. SERIALIZE_STR(c->doc_comment);
  615. }
  616. SERIALIZE_ATTRIBUTES(c->attributes);
  617. }
  618. }
  619. }
  620. static void zend_file_cache_serialize_class(zval *zv,
  621. zend_persistent_script *script,
  622. zend_file_cache_metainfo *info,
  623. void *buf)
  624. {
  625. zend_class_entry *ce;
  626. SERIALIZE_PTR(Z_PTR_P(zv));
  627. ce = Z_PTR_P(zv);
  628. UNSERIALIZE_PTR(ce);
  629. SERIALIZE_STR(ce->name);
  630. if (ce->parent) {
  631. if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
  632. SERIALIZE_STR(ce->parent_name);
  633. } else {
  634. SERIALIZE_PTR(ce->parent);
  635. }
  636. }
  637. zend_file_cache_serialize_hash(&ce->function_table, script, info, buf, zend_file_cache_serialize_func);
  638. if (ce->default_properties_table) {
  639. zval *p, *end;
  640. SERIALIZE_PTR(ce->default_properties_table);
  641. p = ce->default_properties_table;
  642. UNSERIALIZE_PTR(p);
  643. end = p + ce->default_properties_count;
  644. while (p < end) {
  645. zend_file_cache_serialize_zval(p, script, info, buf);
  646. p++;
  647. }
  648. }
  649. if (ce->default_static_members_table) {
  650. zval *p, *end;
  651. SERIALIZE_PTR(ce->default_static_members_table);
  652. p = ce->default_static_members_table;
  653. UNSERIALIZE_PTR(p);
  654. end = p + ce->default_static_members_count;
  655. while (p < end) {
  656. zend_file_cache_serialize_zval(p, script, info, buf);
  657. p++;
  658. }
  659. }
  660. zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant);
  661. SERIALIZE_STR(ce->info.user.filename);
  662. SERIALIZE_STR(ce->info.user.doc_comment);
  663. SERIALIZE_ATTRIBUTES(ce->attributes);
  664. zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
  665. if (ce->properties_info_table) {
  666. uint32_t i;
  667. zend_property_info **table;
  668. SERIALIZE_PTR(ce->properties_info_table);
  669. table = ce->properties_info_table;
  670. UNSERIALIZE_PTR(table);
  671. for (i = 0; i < ce->default_properties_count; i++) {
  672. SERIALIZE_PTR(table[i]);
  673. }
  674. }
  675. if (ce->num_interfaces) {
  676. uint32_t i;
  677. zend_class_name *interface_names;
  678. ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
  679. SERIALIZE_PTR(ce->interface_names);
  680. interface_names = ce->interface_names;
  681. UNSERIALIZE_PTR(interface_names);
  682. for (i = 0; i < ce->num_interfaces; i++) {
  683. SERIALIZE_STR(interface_names[i].name);
  684. SERIALIZE_STR(interface_names[i].lc_name);
  685. }
  686. }
  687. if (ce->num_traits) {
  688. uint32_t i;
  689. zend_class_name *trait_names;
  690. SERIALIZE_PTR(ce->trait_names);
  691. trait_names = ce->trait_names;
  692. UNSERIALIZE_PTR(trait_names);
  693. for (i = 0; i < ce->num_traits; i++) {
  694. SERIALIZE_STR(trait_names[i].name);
  695. SERIALIZE_STR(trait_names[i].lc_name);
  696. }
  697. if (ce->trait_aliases) {
  698. zend_trait_alias **p, *q;
  699. SERIALIZE_PTR(ce->trait_aliases);
  700. p = ce->trait_aliases;
  701. UNSERIALIZE_PTR(p);
  702. while (*p) {
  703. SERIALIZE_PTR(*p);
  704. q = *p;
  705. UNSERIALIZE_PTR(q);
  706. if (q->trait_method.method_name) {
  707. SERIALIZE_STR(q->trait_method.method_name);
  708. }
  709. if (q->trait_method.class_name) {
  710. SERIALIZE_STR(q->trait_method.class_name);
  711. }
  712. if (q->alias) {
  713. SERIALIZE_STR(q->alias);
  714. }
  715. p++;
  716. }
  717. }
  718. if (ce->trait_precedences) {
  719. zend_trait_precedence **p, *q;
  720. uint32_t j;
  721. SERIALIZE_PTR(ce->trait_precedences);
  722. p = ce->trait_precedences;
  723. UNSERIALIZE_PTR(p);
  724. while (*p) {
  725. SERIALIZE_PTR(*p);
  726. q = *p;
  727. UNSERIALIZE_PTR(q);
  728. if (q->trait_method.method_name) {
  729. SERIALIZE_STR(q->trait_method.method_name);
  730. }
  731. if (q->trait_method.class_name) {
  732. SERIALIZE_STR(q->trait_method.class_name);
  733. }
  734. for (j = 0; j < q->num_excludes; j++) {
  735. SERIALIZE_STR(q->exclude_class_names[j]);
  736. }
  737. p++;
  738. }
  739. }
  740. }
  741. if (ce->backed_enum_table) {
  742. HashTable *ht;
  743. SERIALIZE_PTR(ce->backed_enum_table);
  744. ht = ce->backed_enum_table;
  745. UNSERIALIZE_PTR(ht);
  746. zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
  747. }
  748. SERIALIZE_PTR(ce->constructor);
  749. SERIALIZE_PTR(ce->destructor);
  750. SERIALIZE_PTR(ce->clone);
  751. SERIALIZE_PTR(ce->__get);
  752. SERIALIZE_PTR(ce->__set);
  753. SERIALIZE_PTR(ce->__call);
  754. SERIALIZE_PTR(ce->__serialize);
  755. SERIALIZE_PTR(ce->__unserialize);
  756. SERIALIZE_PTR(ce->__isset);
  757. SERIALIZE_PTR(ce->__unset);
  758. SERIALIZE_PTR(ce->__tostring);
  759. SERIALIZE_PTR(ce->__callstatic);
  760. SERIALIZE_PTR(ce->__debugInfo);
  761. if (ce->iterator_funcs_ptr) {
  762. SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_new_iterator);
  763. SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_rewind);
  764. SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_valid);
  765. SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_key);
  766. SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_current);
  767. SERIALIZE_PTR(ce->iterator_funcs_ptr->zf_next);
  768. SERIALIZE_PTR(ce->iterator_funcs_ptr);
  769. }
  770. ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
  771. ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
  772. }
  773. static void zend_file_cache_serialize_warnings(
  774. zend_persistent_script *script, zend_file_cache_metainfo *info, void *buf)
  775. {
  776. if (script->warnings) {
  777. zend_error_info **warnings;
  778. SERIALIZE_PTR(script->warnings);
  779. warnings = script->warnings;
  780. UNSERIALIZE_PTR(warnings);
  781. for (uint32_t i = 0; i < script->num_warnings; i++) {
  782. zend_error_info *warning;
  783. SERIALIZE_PTR(warnings[i]);
  784. warning = warnings[i];
  785. UNSERIALIZE_PTR(warning);
  786. SERIALIZE_STR(warning->filename);
  787. SERIALIZE_STR(warning->message);
  788. }
  789. }
  790. }
  791. static void zend_file_cache_serialize(zend_persistent_script *script,
  792. zend_file_cache_metainfo *info,
  793. void *buf)
  794. {
  795. zend_persistent_script *new_script;
  796. memcpy(info->magic, "OPCACHE", 8);
  797. memcpy(info->system_id, zend_system_id, 32);
  798. info->mem_size = script->size;
  799. info->str_size = 0;
  800. info->script_offset = (char*)script - (char*)script->mem;
  801. info->timestamp = script->timestamp;
  802. memcpy(buf, script->mem, script->size);
  803. new_script = (zend_persistent_script*)((char*)buf + info->script_offset);
  804. SERIALIZE_STR(new_script->script.filename);
  805. zend_file_cache_serialize_hash(&new_script->script.class_table, script, info, buf, zend_file_cache_serialize_class);
  806. zend_file_cache_serialize_hash(&new_script->script.function_table, script, info, buf, zend_file_cache_serialize_func);
  807. zend_file_cache_serialize_op_array(&new_script->script.main_op_array, script, info, buf);
  808. zend_file_cache_serialize_warnings(new_script, info, buf);
  809. new_script->mem = NULL;
  810. }
  811. static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
  812. {
  813. size_t len;
  814. char *filename;
  815. #ifndef ZEND_WIN32
  816. len = strlen(ZCG(accel_directives).file_cache);
  817. filename = emalloc(len + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
  818. memcpy(filename, ZCG(accel_directives).file_cache, len);
  819. filename[len] = '/';
  820. memcpy(filename + len + 1, zend_system_id, 32);
  821. memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
  822. memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
  823. #else
  824. len = strlen(ZCG(accel_directives).file_cache);
  825. filename = emalloc(len + 33 + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
  826. memcpy(filename, ZCG(accel_directives).file_cache, len);
  827. filename[len] = '\\';
  828. memcpy(filename + 1 + len, accel_uname_id, 32);
  829. len += 1 + 32;
  830. filename[len] = '\\';
  831. memcpy(filename + len + 1, zend_system_id, 32);
  832. if (ZSTR_LEN(script_path) >= 7 && ':' == ZSTR_VAL(script_path)[4] && '/' == ZSTR_VAL(script_path)[5] && '/' == ZSTR_VAL(script_path)[6]) {
  833. /* phar:// or file:// */
  834. *(filename + len + 33) = '\\';
  835. memcpy(filename + len + 34, ZSTR_VAL(script_path), 4);
  836. if (ZSTR_LEN(script_path) - 7 >= 2 && ':' == ZSTR_VAL(script_path)[8]) {
  837. *(filename + len + 38) = '\\';
  838. *(filename + len + 39) = ZSTR_VAL(script_path)[7];
  839. memcpy(filename + len + 40, ZSTR_VAL(script_path) + 9, ZSTR_LEN(script_path) - 9);
  840. memcpy(filename + len + 40 + ZSTR_LEN(script_path) - 9, SUFFIX, sizeof(SUFFIX));
  841. } else {
  842. memcpy(filename + len + 38, ZSTR_VAL(script_path) + 7, ZSTR_LEN(script_path) - 7);
  843. memcpy(filename + len + 38 + ZSTR_LEN(script_path) - 7, SUFFIX, sizeof(SUFFIX));
  844. }
  845. } else if (ZSTR_LEN(script_path) >= 2 && ':' == ZSTR_VAL(script_path)[1]) {
  846. /* local fs */
  847. *(filename + len + 33) = '\\';
  848. *(filename + len + 34) = ZSTR_VAL(script_path)[0];
  849. memcpy(filename + len + 35, ZSTR_VAL(script_path) + 2, ZSTR_LEN(script_path) - 2);
  850. memcpy(filename + len + 35 + ZSTR_LEN(script_path) - 2, SUFFIX, sizeof(SUFFIX));
  851. } else {
  852. /* network path */
  853. memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
  854. memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
  855. }
  856. #endif
  857. return filename;
  858. }
  859. int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
  860. {
  861. int fd;
  862. char *filename;
  863. zend_file_cache_metainfo info;
  864. #ifdef HAVE_SYS_UIO_H
  865. struct iovec vec[3];
  866. #endif
  867. void *mem, *buf;
  868. #ifdef HAVE_JIT
  869. /* FIXME: dump jited codes out to file cache? */
  870. if (JIT_G(on)) {
  871. return FAILURE;
  872. }
  873. #endif
  874. filename = zend_file_cache_get_bin_file_path(script->script.filename);
  875. if (zend_file_cache_mkdir(filename, strlen(ZCG(accel_directives).file_cache)) != SUCCESS) {
  876. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create directory for file '%s', %s\n", filename, strerror(errno));
  877. efree(filename);
  878. return FAILURE;
  879. }
  880. fd = zend_file_cache_open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
  881. if (fd < 0) {
  882. if (errno != EEXIST) {
  883. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create file '%s', %s\n", filename, strerror(errno));
  884. }
  885. efree(filename);
  886. return FAILURE;
  887. }
  888. if (zend_file_cache_flock(fd, LOCK_EX) != 0) {
  889. close(fd);
  890. efree(filename);
  891. return FAILURE;
  892. }
  893. #if defined(__AVX__) || defined(__SSE2__)
  894. /* Align to 64-byte boundary */
  895. mem = emalloc(script->size + 64);
  896. buf = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
  897. #else
  898. mem = buf = emalloc(script->size);
  899. #endif
  900. ZCG(mem) = zend_string_alloc(4096 - (_ZSTR_HEADER_SIZE + 1), 0);
  901. zend_shared_alloc_init_xlat_table();
  902. if (!in_shm) {
  903. script->corrupted = 1; /* used to check if script restored to SHM or process memory */
  904. }
  905. zend_file_cache_serialize(script, &info, buf);
  906. if (!in_shm) {
  907. script->corrupted = 0;
  908. }
  909. zend_shared_alloc_destroy_xlat_table();
  910. info.checksum = zend_adler32(ADLER32_INIT, buf, script->size);
  911. info.checksum = zend_adler32(info.checksum, (unsigned char*)ZSTR_VAL((zend_string*)ZCG(mem)), info.str_size);
  912. #if __has_feature(memory_sanitizer)
  913. /* The buffer may contain uninitialized regions. However, the uninitialized parts will not be
  914. * used when reading the cache. We should probably still try to get things fully initialized
  915. * for reproducibility, but for now ignore this issue. */
  916. __msan_unpoison(&info, sizeof(info));
  917. __msan_unpoison(buf, script->size);
  918. #endif
  919. #ifdef HAVE_SYS_UIO_H
  920. vec[0].iov_base = (void *)&info;
  921. vec[0].iov_len = sizeof(info);
  922. vec[1].iov_base = buf;
  923. vec[1].iov_len = script->size;
  924. vec[2].iov_base = ZSTR_VAL((zend_string*)ZCG(mem));
  925. vec[2].iov_len = info.str_size;
  926. if (writev(fd, vec, 3) != (ssize_t)(sizeof(info) + script->size + info.str_size)) {
  927. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
  928. zend_string_release_ex((zend_string*)ZCG(mem), 0);
  929. close(fd);
  930. efree(mem);
  931. zend_file_cache_unlink(filename);
  932. efree(filename);
  933. return FAILURE;
  934. }
  935. #else
  936. if (ZEND_LONG_MAX < (zend_long)(sizeof(info) + script->size + info.str_size) ||
  937. write(fd, &info, sizeof(info)) != sizeof(info) ||
  938. write(fd, buf, script->size) != script->size ||
  939. write(fd, ((zend_string*)ZCG(mem))->val, info.str_size) != info.str_size
  940. ) {
  941. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
  942. zend_string_release_ex((zend_string*)ZCG(mem), 0);
  943. close(fd);
  944. efree(mem);
  945. zend_file_cache_unlink(filename);
  946. efree(filename);
  947. return FAILURE;
  948. }
  949. #endif
  950. zend_string_release_ex((zend_string*)ZCG(mem), 0);
  951. efree(mem);
  952. if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
  953. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
  954. }
  955. close(fd);
  956. efree(filename);
  957. return SUCCESS;
  958. }
  959. static void zend_file_cache_unserialize_hash(HashTable *ht,
  960. zend_persistent_script *script,
  961. void *buf,
  962. unserialize_callback_t func,
  963. dtor_func_t dtor)
  964. {
  965. Bucket *p, *end;
  966. ht->pDestructor = dtor;
  967. if (HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED) {
  968. if (EXPECTED(!file_cache_only)) {
  969. HT_SET_DATA_ADDR(ht, &ZCSG(uninitialized_bucket));
  970. } else {
  971. HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
  972. }
  973. return;
  974. }
  975. if (IS_UNSERIALIZED(ht->arData)) {
  976. return;
  977. }
  978. UNSERIALIZE_PTR(ht->arData);
  979. p = ht->arData;
  980. end = p + ht->nNumUsed;
  981. while (p < end) {
  982. if (Z_TYPE(p->val) != IS_UNDEF) {
  983. UNSERIALIZE_STR(p->key);
  984. func(&p->val, script, buf);
  985. }
  986. p++;
  987. }
  988. }
  989. static void zend_file_cache_unserialize_ast(zend_ast *ast,
  990. zend_persistent_script *script,
  991. void *buf)
  992. {
  993. uint32_t i;
  994. if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
  995. zend_file_cache_unserialize_zval(&((zend_ast_zval*)ast)->val, script, buf);
  996. } else if (zend_ast_is_list(ast)) {
  997. zend_ast_list *list = zend_ast_get_list(ast);
  998. for (i = 0; i < list->children; i++) {
  999. if (list->child[i] && !IS_UNSERIALIZED(list->child[i])) {
  1000. UNSERIALIZE_PTR(list->child[i]);
  1001. zend_file_cache_unserialize_ast(list->child[i], script, buf);
  1002. }
  1003. }
  1004. } else {
  1005. uint32_t children = zend_ast_get_num_children(ast);
  1006. for (i = 0; i < children; i++) {
  1007. if (ast->child[i] && !IS_UNSERIALIZED(ast->child[i])) {
  1008. UNSERIALIZE_PTR(ast->child[i]);
  1009. zend_file_cache_unserialize_ast(ast->child[i], script, buf);
  1010. }
  1011. }
  1012. }
  1013. }
  1014. static void zend_file_cache_unserialize_zval(zval *zv,
  1015. zend_persistent_script *script,
  1016. void *buf)
  1017. {
  1018. switch (Z_TYPE_P(zv)) {
  1019. case IS_STRING:
  1020. /* We can't use !IS_UNSERIALIZED here, because that does not recognize unserialized
  1021. * interned strings in non-shm mode. */
  1022. if (IS_SERIALIZED(Z_STR_P(zv)) || IS_SERIALIZED_INTERNED(Z_STR_P(zv))) {
  1023. UNSERIALIZE_STR(Z_STR_P(zv));
  1024. }
  1025. break;
  1026. case IS_ARRAY:
  1027. if (!IS_UNSERIALIZED(Z_ARR_P(zv))) {
  1028. HashTable *ht;
  1029. UNSERIALIZE_PTR(Z_ARR_P(zv));
  1030. ht = Z_ARR_P(zv);
  1031. zend_file_cache_unserialize_hash(ht,
  1032. script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
  1033. }
  1034. break;
  1035. case IS_CONSTANT_AST:
  1036. if (!IS_UNSERIALIZED(Z_AST_P(zv))) {
  1037. UNSERIALIZE_PTR(Z_AST_P(zv));
  1038. zend_file_cache_unserialize_ast(Z_ASTVAL_P(zv), script, buf);
  1039. }
  1040. break;
  1041. case IS_INDIRECT:
  1042. /* Used by static properties. */
  1043. UNSERIALIZE_PTR(Z_INDIRECT_P(zv));
  1044. break;
  1045. default:
  1046. ZEND_ASSERT(Z_TYPE_P(zv) < IS_STRING);
  1047. break;
  1048. }
  1049. }
  1050. static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_script *script, void *buf)
  1051. {
  1052. zend_attribute *attr;
  1053. uint32_t i;
  1054. UNSERIALIZE_PTR(Z_PTR_P(zv));
  1055. attr = Z_PTR_P(zv);
  1056. UNSERIALIZE_STR(attr->name);
  1057. UNSERIALIZE_STR(attr->lcname);
  1058. for (i = 0; i < attr->argc; i++) {
  1059. UNSERIALIZE_STR(attr->args[i].name);
  1060. zend_file_cache_unserialize_zval(&attr->args[i].value, script, buf);
  1061. }
  1062. }
  1063. static void zend_file_cache_unserialize_type(
  1064. zend_type *type, zend_class_entry *scope, zend_persistent_script *script, void *buf)
  1065. {
  1066. if (ZEND_TYPE_HAS_LIST(*type)) {
  1067. zend_type_list *list = ZEND_TYPE_LIST(*type);
  1068. UNSERIALIZE_PTR(list);
  1069. ZEND_TYPE_SET_PTR(*type, list);
  1070. zend_type *list_type;
  1071. ZEND_TYPE_LIST_FOREACH(list, list_type) {
  1072. zend_file_cache_unserialize_type(list_type, scope, script, buf);
  1073. } ZEND_TYPE_LIST_FOREACH_END();
  1074. } else if (ZEND_TYPE_HAS_NAME(*type)) {
  1075. zend_string *type_name = ZEND_TYPE_NAME(*type);
  1076. UNSERIALIZE_STR(type_name);
  1077. ZEND_TYPE_SET_PTR(*type, type_name);
  1078. if (!script->corrupted) {
  1079. zend_accel_get_class_name_map_ptr(type_name);
  1080. } else {
  1081. zend_alloc_ce_cache(type_name);
  1082. }
  1083. }
  1084. }
  1085. static void zend_file_cache_unserialize_op_array(zend_op_array *op_array,
  1086. zend_persistent_script *script,
  1087. void *buf)
  1088. {
  1089. if (!script->corrupted) {
  1090. if (op_array != &script->script.main_op_array) {
  1091. op_array->fn_flags |= ZEND_ACC_IMMUTABLE;
  1092. ZEND_MAP_PTR_NEW(op_array->run_time_cache);
  1093. } else {
  1094. ZEND_ASSERT(!(op_array->fn_flags & ZEND_ACC_IMMUTABLE));
  1095. ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
  1096. }
  1097. if (op_array->static_variables) {
  1098. ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
  1099. }
  1100. } else {
  1101. op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
  1102. if (op_array->static_variables) {
  1103. ZEND_MAP_PTR_INIT(op_array->static_variables_ptr,
  1104. zend_arena_alloc(&CG(arena), sizeof(HashTable *)));
  1105. ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
  1106. }
  1107. if (op_array != &script->script.main_op_array) {
  1108. ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
  1109. ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
  1110. } else {
  1111. ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
  1112. }
  1113. }
  1114. /* Check whether this op_array has already been unserialized. */
  1115. if (IS_UNSERIALIZED(op_array->opcodes)) {
  1116. ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
  1117. return;
  1118. }
  1119. if (op_array->refcount) {
  1120. op_array->refcount = NULL;
  1121. UNSERIALIZE_PTR(op_array->static_variables);
  1122. UNSERIALIZE_PTR(op_array->literals);
  1123. UNSERIALIZE_PTR(op_array->opcodes);
  1124. UNSERIALIZE_PTR(op_array->arg_info);
  1125. UNSERIALIZE_PTR(op_array->vars);
  1126. UNSERIALIZE_STR(op_array->function_name);
  1127. UNSERIALIZE_STR(op_array->filename);
  1128. UNSERIALIZE_PTR(op_array->live_range);
  1129. UNSERIALIZE_PTR(op_array->scope);
  1130. UNSERIALIZE_STR(op_array->doc_comment);
  1131. UNSERIALIZE_ATTRIBUTES(op_array->attributes);
  1132. UNSERIALIZE_PTR(op_array->try_catch_array);
  1133. UNSERIALIZE_PTR(op_array->prototype);
  1134. return;
  1135. }
  1136. if (op_array->static_variables) {
  1137. HashTable *ht;
  1138. UNSERIALIZE_PTR(op_array->static_variables);
  1139. ht = op_array->static_variables;
  1140. zend_file_cache_unserialize_hash(ht,
  1141. script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
  1142. }
  1143. if (op_array->literals) {
  1144. zval *p, *end;
  1145. UNSERIALIZE_PTR(op_array->literals);
  1146. p = op_array->literals;
  1147. end = p + op_array->last_literal;
  1148. while (p < end) {
  1149. zend_file_cache_unserialize_zval(p, script, buf);
  1150. p++;
  1151. }
  1152. }
  1153. {
  1154. zend_op *opline, *end;
  1155. UNSERIALIZE_PTR(op_array->opcodes);
  1156. opline = op_array->opcodes;
  1157. end = opline + op_array->last;
  1158. while (opline < end) {
  1159. #if ZEND_USE_ABS_CONST_ADDR
  1160. if (opline->op1_type == IS_CONST) {
  1161. UNSERIALIZE_PTR(opline->op1.zv);
  1162. }
  1163. if (opline->op2_type == IS_CONST) {
  1164. UNSERIALIZE_PTR(opline->op2.zv);
  1165. }
  1166. #else
  1167. if (opline->op1_type == IS_CONST) {
  1168. ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1);
  1169. }
  1170. if (opline->op2_type == IS_CONST) {
  1171. ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2);
  1172. }
  1173. #endif
  1174. #if ZEND_USE_ABS_JMP_ADDR
  1175. switch (opline->opcode) {
  1176. case ZEND_JMP:
  1177. case ZEND_FAST_CALL:
  1178. UNSERIALIZE_PTR(opline->op1.jmp_addr);
  1179. break;
  1180. case ZEND_JMPZNZ:
  1181. /* relative extended_value don't have to be changed */
  1182. /* break omitted intentionally */
  1183. case ZEND_JMPZ:
  1184. case ZEND_JMPNZ:
  1185. case ZEND_JMPZ_EX:
  1186. case ZEND_JMPNZ_EX:
  1187. case ZEND_JMP_SET:
  1188. case ZEND_COALESCE:
  1189. case ZEND_FE_RESET_R:
  1190. case ZEND_FE_RESET_RW:
  1191. case ZEND_ASSERT_CHECK:
  1192. case ZEND_JMP_NULL:
  1193. UNSERIALIZE_PTR(opline->op2.jmp_addr);
  1194. break;
  1195. case ZEND_CATCH:
  1196. if (!(opline->extended_value & ZEND_LAST_CATCH)) {
  1197. UNSERIALIZE_PTR(opline->op2.jmp_addr);
  1198. }
  1199. break;
  1200. case ZEND_FE_FETCH_R:
  1201. case ZEND_FE_FETCH_RW:
  1202. case ZEND_SWITCH_LONG:
  1203. case ZEND_SWITCH_STRING:
  1204. /* relative extended_value don't have to be changed */
  1205. break;
  1206. }
  1207. #endif
  1208. zend_deserialize_opcode_handler(opline);
  1209. opline++;
  1210. }
  1211. UNSERIALIZE_PTR(op_array->scope);
  1212. if (op_array->arg_info) {
  1213. zend_arg_info *p, *end;
  1214. UNSERIALIZE_PTR(op_array->arg_info);
  1215. p = op_array->arg_info;
  1216. end = p + op_array->num_args;
  1217. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  1218. p--;
  1219. }
  1220. if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
  1221. end++;
  1222. }
  1223. while (p < end) {
  1224. if (!IS_UNSERIALIZED(p->name)) {
  1225. UNSERIALIZE_STR(p->name);
  1226. }
  1227. zend_file_cache_unserialize_type(&p->type, (op_array->fn_flags & ZEND_ACC_CLOSURE) ? NULL : op_array->scope, script, buf);
  1228. p++;
  1229. }
  1230. }
  1231. if (op_array->vars) {
  1232. zend_string **p, **end;
  1233. UNSERIALIZE_PTR(op_array->vars);
  1234. p = op_array->vars;
  1235. end = p + op_array->last_var;
  1236. while (p < end) {
  1237. if (!IS_UNSERIALIZED(*p)) {
  1238. UNSERIALIZE_STR(*p);
  1239. }
  1240. p++;
  1241. }
  1242. }
  1243. if (op_array->num_dynamic_func_defs) {
  1244. UNSERIALIZE_PTR(op_array->dynamic_func_defs);
  1245. for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
  1246. UNSERIALIZE_PTR(op_array->dynamic_func_defs[i]);
  1247. zend_file_cache_unserialize_op_array(op_array->dynamic_func_defs[i], script, buf);
  1248. }
  1249. }
  1250. UNSERIALIZE_STR(op_array->function_name);
  1251. UNSERIALIZE_STR(op_array->filename);
  1252. UNSERIALIZE_PTR(op_array->live_range);
  1253. UNSERIALIZE_STR(op_array->doc_comment);
  1254. UNSERIALIZE_ATTRIBUTES(op_array->attributes);
  1255. UNSERIALIZE_PTR(op_array->try_catch_array);
  1256. UNSERIALIZE_PTR(op_array->prototype);
  1257. }
  1258. }
  1259. static void zend_file_cache_unserialize_func(zval *zv,
  1260. zend_persistent_script *script,
  1261. void *buf)
  1262. {
  1263. zend_function *func;
  1264. UNSERIALIZE_PTR(Z_PTR_P(zv));
  1265. func = Z_PTR_P(zv);
  1266. ZEND_ASSERT(func->type == ZEND_USER_FUNCTION);
  1267. zend_file_cache_unserialize_op_array(&func->op_array, script, buf);
  1268. }
  1269. static void zend_file_cache_unserialize_prop_info(zval *zv,
  1270. zend_persistent_script *script,
  1271. void *buf)
  1272. {
  1273. if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
  1274. zend_property_info *prop;
  1275. UNSERIALIZE_PTR(Z_PTR_P(zv));
  1276. prop = Z_PTR_P(zv);
  1277. ZEND_ASSERT(prop->ce != NULL && prop->name != NULL);
  1278. if (!IS_UNSERIALIZED(prop->ce)) {
  1279. UNSERIALIZE_PTR(prop->ce);
  1280. UNSERIALIZE_STR(prop->name);
  1281. if (prop->doc_comment) {
  1282. UNSERIALIZE_STR(prop->doc_comment);
  1283. }
  1284. UNSERIALIZE_ATTRIBUTES(prop->attributes);
  1285. zend_file_cache_unserialize_type(&prop->type, prop->ce, script, buf);
  1286. }
  1287. }
  1288. }
  1289. static void zend_file_cache_unserialize_class_constant(zval *zv,
  1290. zend_persistent_script *script,
  1291. void *buf)
  1292. {
  1293. if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
  1294. zend_class_constant *c;
  1295. UNSERIALIZE_PTR(Z_PTR_P(zv));
  1296. c = Z_PTR_P(zv);
  1297. ZEND_ASSERT(c->ce != NULL);
  1298. if (!IS_UNSERIALIZED(c->ce)) {
  1299. UNSERIALIZE_PTR(c->ce);
  1300. zend_file_cache_unserialize_zval(&c->value, script, buf);
  1301. if (c->doc_comment) {
  1302. UNSERIALIZE_STR(c->doc_comment);
  1303. }
  1304. UNSERIALIZE_ATTRIBUTES(c->attributes);
  1305. }
  1306. }
  1307. }
  1308. static void zend_file_cache_unserialize_class(zval *zv,
  1309. zend_persistent_script *script,
  1310. void *buf)
  1311. {
  1312. zend_class_entry *ce;
  1313. UNSERIALIZE_PTR(Z_PTR_P(zv));
  1314. ce = Z_PTR_P(zv);
  1315. UNSERIALIZE_STR(ce->name);
  1316. if (!(ce->ce_flags & ZEND_ACC_ANON_CLASS)) {
  1317. if (!script->corrupted) {
  1318. zend_accel_get_class_name_map_ptr(ce->name);
  1319. } else {
  1320. zend_alloc_ce_cache(ce->name);
  1321. }
  1322. }
  1323. if (ce->parent) {
  1324. if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
  1325. UNSERIALIZE_STR(ce->parent_name);
  1326. } else {
  1327. UNSERIALIZE_PTR(ce->parent);
  1328. }
  1329. }
  1330. zend_file_cache_unserialize_hash(&ce->function_table,
  1331. script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
  1332. if (ce->default_properties_table) {
  1333. zval *p, *end;
  1334. UNSERIALIZE_PTR(ce->default_properties_table);
  1335. p = ce->default_properties_table;
  1336. end = p + ce->default_properties_count;
  1337. while (p < end) {
  1338. zend_file_cache_unserialize_zval(p, script, buf);
  1339. p++;
  1340. }
  1341. }
  1342. if (ce->default_static_members_table) {
  1343. zval *p, *end;
  1344. UNSERIALIZE_PTR(ce->default_static_members_table);
  1345. p = ce->default_static_members_table;
  1346. end = p + ce->default_static_members_count;
  1347. while (p < end) {
  1348. zend_file_cache_unserialize_zval(p, script, buf);
  1349. p++;
  1350. }
  1351. }
  1352. zend_file_cache_unserialize_hash(&ce->constants_table,
  1353. script, buf, zend_file_cache_unserialize_class_constant, NULL);
  1354. UNSERIALIZE_STR(ce->info.user.filename);
  1355. UNSERIALIZE_STR(ce->info.user.doc_comment);
  1356. UNSERIALIZE_ATTRIBUTES(ce->attributes);
  1357. zend_file_cache_unserialize_hash(&ce->properties_info,
  1358. script, buf, zend_file_cache_unserialize_prop_info, NULL);
  1359. if (ce->properties_info_table) {
  1360. uint32_t i;
  1361. UNSERIALIZE_PTR(ce->properties_info_table);
  1362. for (i = 0; i < ce->default_properties_count; i++) {
  1363. UNSERIALIZE_PTR(ce->properties_info_table[i]);
  1364. }
  1365. }
  1366. if (ce->num_interfaces) {
  1367. uint32_t i;
  1368. ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
  1369. UNSERIALIZE_PTR(ce->interface_names);
  1370. for (i = 0; i < ce->num_interfaces; i++) {
  1371. UNSERIALIZE_STR(ce->interface_names[i].name);
  1372. UNSERIALIZE_STR(ce->interface_names[i].lc_name);
  1373. }
  1374. }
  1375. if (ce->num_traits) {
  1376. uint32_t i;
  1377. UNSERIALIZE_PTR(ce->trait_names);
  1378. for (i = 0; i < ce->num_traits; i++) {
  1379. UNSERIALIZE_STR(ce->trait_names[i].name);
  1380. UNSERIALIZE_STR(ce->trait_names[i].lc_name);
  1381. }
  1382. if (ce->trait_aliases) {
  1383. zend_trait_alias **p, *q;
  1384. UNSERIALIZE_PTR(ce->trait_aliases);
  1385. p = ce->trait_aliases;
  1386. while (*p) {
  1387. UNSERIALIZE_PTR(*p);
  1388. q = *p;
  1389. if (q->trait_method.method_name) {
  1390. UNSERIALIZE_STR(q->trait_method.method_name);
  1391. }
  1392. if (q->trait_method.class_name) {
  1393. UNSERIALIZE_STR(q->trait_method.class_name);
  1394. }
  1395. if (q->alias) {
  1396. UNSERIALIZE_STR(q->alias);
  1397. }
  1398. p++;
  1399. }
  1400. }
  1401. if (ce->trait_precedences) {
  1402. zend_trait_precedence **p, *q;
  1403. uint32_t j;
  1404. UNSERIALIZE_PTR(ce->trait_precedences);
  1405. p = ce->trait_precedences;
  1406. while (*p) {
  1407. UNSERIALIZE_PTR(*p);
  1408. q = *p;
  1409. if (q->trait_method.method_name) {
  1410. UNSERIALIZE_STR(q->trait_method.method_name);
  1411. }
  1412. if (q->trait_method.class_name) {
  1413. UNSERIALIZE_STR(q->trait_method.class_name);
  1414. }
  1415. for (j = 0; j < q->num_excludes; j++) {
  1416. UNSERIALIZE_STR(q->exclude_class_names[j]);
  1417. }
  1418. p++;
  1419. }
  1420. }
  1421. }
  1422. if (ce->backed_enum_table) {
  1423. UNSERIALIZE_PTR(ce->backed_enum_table);
  1424. zend_file_cache_unserialize_hash(
  1425. ce->backed_enum_table, script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
  1426. }
  1427. UNSERIALIZE_PTR(ce->constructor);
  1428. UNSERIALIZE_PTR(ce->destructor);
  1429. UNSERIALIZE_PTR(ce->clone);
  1430. UNSERIALIZE_PTR(ce->__get);
  1431. UNSERIALIZE_PTR(ce->__set);
  1432. UNSERIALIZE_PTR(ce->__call);
  1433. UNSERIALIZE_PTR(ce->__serialize);
  1434. UNSERIALIZE_PTR(ce->__unserialize);
  1435. UNSERIALIZE_PTR(ce->__isset);
  1436. UNSERIALIZE_PTR(ce->__unset);
  1437. UNSERIALIZE_PTR(ce->__tostring);
  1438. UNSERIALIZE_PTR(ce->__callstatic);
  1439. UNSERIALIZE_PTR(ce->__debugInfo);
  1440. if (ce->iterator_funcs_ptr) {
  1441. UNSERIALIZE_PTR(ce->iterator_funcs_ptr);
  1442. UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_new_iterator);
  1443. UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_rewind);
  1444. UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_valid);
  1445. UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_key);
  1446. UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_current);
  1447. UNSERIALIZE_PTR(ce->iterator_funcs_ptr->zf_next);
  1448. }
  1449. if (!(script->corrupted)) {
  1450. ce->ce_flags |= ZEND_ACC_IMMUTABLE;
  1451. ce->ce_flags &= ~ZEND_ACC_FILE_CACHED;
  1452. ZEND_MAP_PTR_NEW(ce->mutable_data);
  1453. if (ce->default_static_members_count) {
  1454. ZEND_MAP_PTR_NEW(ce->static_members_table);
  1455. }
  1456. } else {
  1457. ce->ce_flags &= ~ZEND_ACC_IMMUTABLE;
  1458. ce->ce_flags |= ZEND_ACC_FILE_CACHED;
  1459. ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
  1460. if (ce->default_static_members_count) {
  1461. ZEND_MAP_PTR_INIT(ce->static_members_table,
  1462. zend_arena_alloc(&CG(arena), sizeof(zval *)));
  1463. ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
  1464. }
  1465. }
  1466. }
  1467. static void zend_file_cache_unserialize_warnings(zend_persistent_script *script, void *buf)
  1468. {
  1469. if (script->warnings) {
  1470. UNSERIALIZE_PTR(script->warnings);
  1471. for (uint32_t i = 0; i < script->num_warnings; i++) {
  1472. UNSERIALIZE_PTR(script->warnings[i]);
  1473. UNSERIALIZE_STR(script->warnings[i]->filename);
  1474. UNSERIALIZE_STR(script->warnings[i]->message);
  1475. }
  1476. }
  1477. }
  1478. static void zend_file_cache_unserialize(zend_persistent_script *script,
  1479. void *buf)
  1480. {
  1481. script->mem = buf;
  1482. UNSERIALIZE_STR(script->script.filename);
  1483. zend_file_cache_unserialize_hash(&script->script.class_table,
  1484. script, buf, zend_file_cache_unserialize_class, ZEND_CLASS_DTOR);
  1485. zend_file_cache_unserialize_hash(&script->script.function_table,
  1486. script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
  1487. zend_file_cache_unserialize_op_array(&script->script.main_op_array, script, buf);
  1488. zend_file_cache_unserialize_warnings(script, buf);
  1489. }
  1490. zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle)
  1491. {
  1492. zend_string *full_path = file_handle->opened_path;
  1493. int fd;
  1494. char *filename;
  1495. zend_persistent_script *script;
  1496. zend_file_cache_metainfo info;
  1497. zend_accel_hash_entry *bucket;
  1498. void *mem, *checkpoint, *buf;
  1499. int cache_it = 1;
  1500. unsigned int actual_checksum;
  1501. int ok;
  1502. if (!full_path) {
  1503. return NULL;
  1504. }
  1505. filename = zend_file_cache_get_bin_file_path(full_path);
  1506. fd = zend_file_cache_open(filename, O_RDONLY | O_BINARY);
  1507. if (fd < 0) {
  1508. efree(filename);
  1509. return NULL;
  1510. }
  1511. if (zend_file_cache_flock(fd, LOCK_SH) != 0) {
  1512. close(fd);
  1513. efree(filename);
  1514. return NULL;
  1515. }
  1516. if (read(fd, &info, sizeof(info)) != sizeof(info)) {
  1517. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (info)\n", filename);
  1518. zend_file_cache_flock(fd, LOCK_UN);
  1519. close(fd);
  1520. zend_file_cache_unlink(filename);
  1521. efree(filename);
  1522. return NULL;
  1523. }
  1524. /* verify header */
  1525. if (memcmp(info.magic, "OPCACHE", 8) != 0) {
  1526. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename);
  1527. zend_file_cache_flock(fd, LOCK_UN);
  1528. close(fd);
  1529. zend_file_cache_unlink(filename);
  1530. efree(filename);
  1531. return NULL;
  1532. }
  1533. if (memcmp(info.system_id, zend_system_id, 32) != 0) {
  1534. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
  1535. zend_file_cache_flock(fd, LOCK_UN);
  1536. close(fd);
  1537. zend_file_cache_unlink(filename);
  1538. efree(filename);
  1539. return NULL;
  1540. }
  1541. /* verify timestamp */
  1542. if (ZCG(accel_directives).validate_timestamps &&
  1543. zend_get_file_handle_timestamp(file_handle, NULL) != info.timestamp) {
  1544. if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
  1545. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
  1546. }
  1547. close(fd);
  1548. zend_file_cache_unlink(filename);
  1549. efree(filename);
  1550. return NULL;
  1551. }
  1552. checkpoint = zend_arena_checkpoint(CG(arena));
  1553. #if defined(__AVX__) || defined(__SSE2__)
  1554. /* Align to 64-byte boundary */
  1555. mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size + 64);
  1556. mem = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
  1557. #else
  1558. mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size);
  1559. #endif
  1560. if (read(fd, mem, info.mem_size + info.str_size) != (ssize_t)(info.mem_size + info.str_size)) {
  1561. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (mem)\n", filename);
  1562. zend_file_cache_flock(fd, LOCK_UN);
  1563. close(fd);
  1564. zend_file_cache_unlink(filename);
  1565. zend_arena_release(&CG(arena), checkpoint);
  1566. efree(filename);
  1567. return NULL;
  1568. }
  1569. if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
  1570. zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
  1571. }
  1572. close(fd);
  1573. /* verify checksum */
  1574. if (ZCG(accel_directives).file_cache_consistency_checks &&
  1575. (actual_checksum = zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size)) != info.checksum) {
  1576. zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s' excepted checksum: 0x%08x actual checksum: 0x%08x\n", filename, info.checksum, actual_checksum);
  1577. zend_file_cache_unlink(filename);
  1578. zend_arena_release(&CG(arena), checkpoint);
  1579. efree(filename);
  1580. return NULL;
  1581. }
  1582. if (!file_cache_only &&
  1583. !ZCSG(restart_in_progress) &&
  1584. !ZSMMG(memory_exhausted) &&
  1585. accelerator_shm_read_lock() == SUCCESS) {
  1586. /* exclusive lock */
  1587. zend_shared_alloc_lock();
  1588. /* Check if we still need to put the file into the cache (may be it was
  1589. * already stored by another process. This final check is done under
  1590. * exclusive lock) */
  1591. bucket = zend_accel_hash_find_entry(&ZCSG(hash), full_path);
  1592. if (bucket) {
  1593. script = (zend_persistent_script *)bucket->data;
  1594. if (!script->corrupted) {
  1595. zend_shared_alloc_unlock();
  1596. zend_arena_release(&CG(arena), checkpoint);
  1597. efree(filename);
  1598. return script;
  1599. }
  1600. }
  1601. if (zend_accel_hash_is_full(&ZCSG(hash))) {
  1602. zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
  1603. ZSMMG(memory_exhausted) = 1;
  1604. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
  1605. zend_shared_alloc_unlock();
  1606. goto use_process_mem;
  1607. }
  1608. #if defined(__AVX__) || defined(__SSE2__)
  1609. /* Align to 64-byte boundary */
  1610. buf = zend_shared_alloc(info.mem_size + 64);
  1611. buf = (void*)(((zend_uintptr_t)buf + 63L) & ~63L);
  1612. #else
  1613. buf = zend_shared_alloc(info.mem_size);
  1614. #endif
  1615. if (!buf) {
  1616. zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
  1617. zend_shared_alloc_unlock();
  1618. goto use_process_mem;
  1619. }
  1620. memcpy(buf, mem, info.mem_size);
  1621. zend_map_ptr_extend(ZCSG(map_ptr_last));
  1622. } else {
  1623. use_process_mem:
  1624. buf = mem;
  1625. cache_it = 0;
  1626. }
  1627. ZCG(mem) = ((char*)mem + info.mem_size);
  1628. script = (zend_persistent_script*)((char*)buf + info.script_offset);
  1629. script->corrupted = !cache_it; /* used to check if script restored to SHM or process memory */
  1630. ok = 1;
  1631. zend_try {
  1632. zend_file_cache_unserialize(script, buf);
  1633. } zend_catch {
  1634. ok = 0;
  1635. } zend_end_try();
  1636. if (!ok) {
  1637. if (cache_it) {
  1638. zend_shared_alloc_unlock();
  1639. goto use_process_mem;
  1640. } else {
  1641. zend_arena_release(&CG(arena), checkpoint);
  1642. efree(filename);
  1643. return NULL;
  1644. }
  1645. }
  1646. script->corrupted = 0;
  1647. if (cache_it) {
  1648. ZCSG(map_ptr_last) = CG(map_ptr_last);
  1649. script->dynamic_members.checksum = zend_accel_script_checksum(script);
  1650. script->dynamic_members.last_used = ZCG(request_time);
  1651. zend_accel_hash_update(&ZCSG(hash), script->script.filename, 0, script);
  1652. zend_shared_alloc_unlock();
  1653. zend_accel_error(ACCEL_LOG_INFO, "File cached script loaded into memory '%s'", ZSTR_VAL(script->script.filename));
  1654. zend_arena_release(&CG(arena), checkpoint);
  1655. }
  1656. efree(filename);
  1657. return script;
  1658. }
  1659. void zend_file_cache_invalidate(zend_string *full_path)
  1660. {
  1661. char *filename;
  1662. filename = zend_file_cache_get_bin_file_path(full_path);
  1663. zend_file_cache_unlink(filename);
  1664. efree(filename);
  1665. }