Skip to content

Commit 283844e

Browse files
committed
switch to zend_file_cache_script_validate(...)
1 parent 30641d6 commit 283844e

File tree

4 files changed

+100
-14
lines changed

4 files changed

+100
-14
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,7 +1916,7 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int
19161916

19171917
HANDLE_BLOCK_INTERRUPTIONS();
19181918
SHM_UNPROTECT();
1919-
persistent_script = zend_file_cache_script_load(file_handle, false);
1919+
persistent_script = zend_file_cache_script_load(file_handle);
19201920
SHM_PROTECT();
19211921
HANDLE_UNBLOCK_INTERRUPTIONS();
19221922
if (persistent_script) {
@@ -2133,7 +2133,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
21332133

21342134
/* Check the second level cache */
21352135
if (!persistent_script && ZCG(accel_directives).file_cache) {
2136-
persistent_script = zend_file_cache_script_load(file_handle, false);
2136+
persistent_script = zend_file_cache_script_load(file_handle);
21372137
}
21382138

21392139
/* If script was not found or invalidated by validate_timestamps */

ext/opcache/zend_accelerator_module.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,15 +384,11 @@ static int filename_is_in_file_cache(zend_string *filename)
384384
zend_stream_init_filename_ex(&handle, filename);
385385
handle.opened_path = realpath;
386386

387-
zend_persistent_script *persistent_script = zend_file_cache_script_load(&handle, true);
387+
bool result = zend_file_cache_script_validate(&handle);
388388

389389
zend_destroy_file_handle(&handle);
390390

391-
if (persistent_script) {
392-
return 1;
393-
}
394-
395-
return 0;
391+
return result;
396392
}
397393

398394

@@ -1018,9 +1014,11 @@ ZEND_FUNCTION(opcache_is_script_cached)
10181014
zend_string *script_name;
10191015
bool file_cache = 0;
10201016

1021-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &script_name, &file_cache) == FAILURE) {
1022-
RETURN_THROWS();
1023-
}
1017+
ZEND_PARSE_PARAMETERS_START(1, 2)
1018+
Z_PARAM_STR(script_name)
1019+
Z_PARAM_OPTIONAL
1020+
Z_PARAM_BOOL(file_cache)
1021+
ZEND_PARSE_PARAMETERS_END();
10241022

10251023
if (!validate_api_restriction()) {
10261024
RETURN_FALSE;

ext/opcache/zend_file_cache.c

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,95 @@ static void zend_file_cache_unserialize(zend_persistent_script *script,
18131813
zend_file_cache_unserialize_early_bindings(script, buf);
18141814
}
18151815

1816-
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle, bool force_file_cache_only)
1816+
// Function to validate the file cache and return a boolean result
1817+
bool zend_file_cache_script_validate(zend_file_handle *file_handle)
1818+
{
1819+
int fd;
1820+
char *filename;
1821+
zend_file_cache_metainfo info;
1822+
unsigned int actual_checksum;
1823+
void *mem;
1824+
1825+
if (!file_handle || !file_handle->opened_path) {
1826+
return false;
1827+
}
1828+
1829+
filename = zend_file_cache_get_bin_file_path(file_handle->opened_path);
1830+
fd = zend_file_cache_open(filename, O_RDONLY | O_BINARY);
1831+
if (fd < 0) {
1832+
goto failure; // Open failed
1833+
}
1834+
1835+
if (zend_file_cache_flock(fd, LOCK_SH) != 0) {
1836+
goto failure_close; // Flock failed
1837+
}
1838+
1839+
1840+
if (read(fd, &info, sizeof(info)) != sizeof(info)) {
1841+
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (info)\n", filename);
1842+
goto failure_unlock_close;
1843+
}
1844+
1845+
// Verify header
1846+
if (memcmp(info.magic, "OPCACHE", 8) != 0 || memcmp(info.system_id, zend_system_id, 32) != 0) {
1847+
zend_accel_error(ACCEL_LOG_WARNING, "opcache invalid header in file '%s'\n", filename);
1848+
goto failure_unlock_close;
1849+
}
1850+
1851+
// Verify timestamp if required
1852+
if (ZCG(accel_directives).validate_timestamps &&
1853+
zend_get_file_handle_timestamp(file_handle, NULL) != info.timestamp) {
1854+
goto failure_unlock_close;
1855+
}
1856+
1857+
checkpoint = zend_arena_checkpoint(CG(arena));
1858+
#if defined(__AVX__) || defined(__SSE2__)
1859+
/* Align to 64-byte boundary */
1860+
mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size + 64);
1861+
mem = (void*)(((uintptr_t)mem + 63L) & ~63L);
1862+
#else
1863+
mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size);
1864+
#endif
1865+
1866+
if (read(fd, mem, info.mem_size + info.str_size) != (ssize_t)(info.mem_size + info.str_size)) {
1867+
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (mem)\n", filename);
1868+
zend_arena_release(&CG(arena), checkpoint);
1869+
goto failure_unlock_close;
1870+
}
1871+
if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
1872+
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
1873+
}
1874+
close(fd);
1875+
1876+
/* verify checksum */
1877+
if (ZCG(accel_directives).file_cache_consistency_checks &&
1878+
(actual_checksum = zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size)) != info.checksum) {
1879+
zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s' excepted checksum: 0x%08x actual checksum: 0x%08x\n", filename, info.checksum, actual_checksum);
1880+
zend_arena_release(&CG(arena), checkpoint);
1881+
goto failure;
1882+
}
1883+
1884+
zend_arena_release(&CG(arena), checkpoint);
1885+
zend_file_cache_flock(fd, LOCK_UN);
1886+
close(fd);
1887+
efree(filename);
1888+
return true; // Validation successful
1889+
1890+
failure_unlock_close:
1891+
zend_file_cache_flock(fd, LOCK_UN);
1892+
failure_close:
1893+
close(fd);
1894+
failure:
1895+
if (!ZCG(accel_directives).file_cache_read_only) {
1896+
zend_file_cache_unlink(filename);
1897+
}
1898+
efree(filename);
1899+
1900+
return false; // Validation failed
1901+
}
1902+
1903+
1904+
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle)
18171905
{
18181906
zend_string *full_path = file_handle->opened_path;
18191907
int fd;
@@ -1928,7 +2016,6 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
19282016
}
19292017

19302018
if (!file_cache_only &&
1931-
!force_file_cache_only &&
19322019
!ZCSG(restart_in_progress) &&
19332020
!ZCSG(restart_pending) &&
19342021
!ZSMMG(memory_exhausted) &&

ext/opcache/zend_file_cache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
#define ZEND_FILE_CACHE_H
2121

2222
int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm);
23-
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle, bool force_file_cache_only);
23+
bool zend_file_cache_script_validate(zend_file_handle *file_handle);
24+
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle);
2425
void zend_file_cache_invalidate(zend_string *full_path);
2526

2627
#endif /* ZEND_FILE_CACHE_H */

0 commit comments

Comments
 (0)