diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index b9149fa1fa12a..1c2960fd8d819 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -404,22 +404,22 @@ static inline void accel_unlock_all(void) #define STRTAB_INVALID_POS 0 #define STRTAB_HASH_TO_SLOT(tab, h) \ - ((uint32_t*)((char*)(tab) + sizeof(*(tab)) + ((h) & (tab)->nTableMask))) + ((zend_string_table_pos_t*)((char*)(tab) + sizeof(*(tab)) + ((h) & (tab)->nTableMask))) #define STRTAB_STR_TO_POS(tab, s) \ - ((uint32_t)((char*)s - (char*)(tab))) + ((zend_string_table_pos_t)(((char*)s - (char*)(tab)) / ZEND_STRING_TABLE_POS_ALIGNMENT)) #define STRTAB_POS_TO_STR(tab, pos) \ - ((zend_string*)((char*)(tab) + (pos))) + ((zend_string*)((char*)(tab) + ((uintptr_t)(pos) * ZEND_STRING_TABLE_POS_ALIGNMENT))) #define STRTAB_COLLISION(s) \ - (*((uint32_t*)((char*)s - sizeof(uint32_t)))) + (*((zend_string_table_pos_t*)((char*)s - sizeof(zend_string_table_pos_t)))) #define STRTAB_STR_SIZE(s) \ - ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_HEADER_SIZE + ZSTR_LEN(s) + 5, 8) + ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(ZSTR_LEN(s)) + sizeof(zend_string_table_pos_t), ZEND_STRING_TABLE_POS_ALIGNMENT) #define STRTAB_NEXT(s) \ ((zend_string*)((char*)(s) + STRTAB_STR_SIZE(s))) static void accel_interned_strings_restore_state(void) { zend_string *s, *top; - uint32_t *hash_slot, n; + zend_string_table_pos_t *hash_slot, n; /* clear removed content */ memset(ZCSG(interned_strings).saved_top, @@ -465,7 +465,7 @@ static void accel_interned_strings_save_state(void) static zend_always_inline zend_string *accel_find_interned_string(zend_string *str) { zend_ulong h; - uint32_t pos; + zend_string_table_pos_t pos; zend_string *s; if (IS_ACCEL_INTERNED(str)) { @@ -500,7 +500,7 @@ static zend_always_inline zend_string *accel_find_interned_string(zend_string *s zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str) { zend_ulong h; - uint32_t pos, *hash_slot; + zend_string_table_pos_t pos, *hash_slot; zend_string *s; if (UNEXPECTED(file_cache_only)) { @@ -575,7 +575,7 @@ static zend_string* ZEND_FASTCALL accel_new_interned_string_for_php(zend_string static zend_always_inline zend_string *accel_find_interned_string_ex(zend_ulong h, const char *str, size_t size) { - uint32_t pos; + zend_string_table_pos_t pos; zend_string *s; /* check for existing interned string */ @@ -2842,7 +2842,7 @@ static zend_result zend_accel_init_shm(void) } else { /* Make sure there is always at least one interned string hash slot, * so the table can be queried unconditionally. */ - accel_shared_globals_size = sizeof(zend_accel_shared_globals) + sizeof(uint32_t); + accel_shared_globals_size = sizeof(zend_accel_shared_globals) + sizeof(zend_string_table_pos_t); } accel_shared_globals = zend_shared_alloc(accel_shared_globals_size); @@ -2869,18 +2869,22 @@ static zend_result zend_accel_init_shm(void) hash_size |= (hash_size >> 8); hash_size |= (hash_size >> 16); - ZCSG(interned_strings).nTableMask = hash_size << 2; + ZCSG(interned_strings).nTableMask = + hash_size * sizeof(zend_string_table_pos_t); ZCSG(interned_strings).nNumOfElements = 0; ZCSG(interned_strings).start = (zend_string*)((char*)&ZCSG(interned_strings) + sizeof(zend_string_table) + - ((hash_size + 1) * sizeof(uint32_t))) + + ((hash_size + 1) * sizeof(zend_string_table_pos_t))) + 8; + ZEND_ASSERT(((uintptr_t)ZCSG(interned_strings).start & 0x7) == 0); /* should be 8 byte aligned */ + ZCSG(interned_strings).top = ZCSG(interned_strings).start; ZCSG(interned_strings).end = (zend_string*)((char*)(accel_shared_globals + 1) + /* table data is stored after accel_shared_globals */ ZCG(accel_directives).interned_strings_buffer * 1024 * 1024); + ZEND_ASSERT(((uintptr_t)ZCSG(interned_strings).end - (uintptr_t)&ZCSG(interned_strings)) / ZEND_STRING_TABLE_POS_ALIGNMENT < ZEND_STRING_TABLE_POS_MAX); ZCSG(interned_strings).saved_top = NULL; memset((char*)&ZCSG(interned_strings) + sizeof(zend_string_table), diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index e958e8fd65064..6fed5af22a8d7 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -236,6 +236,11 @@ typedef struct _zend_string_table { zend_string *saved_top; } zend_string_table; +typedef uint32_t zend_string_table_pos_t; + +#define ZEND_STRING_TABLE_POS_MAX UINT32_MAX +#define ZEND_STRING_TABLE_POS_ALIGNMENT 8 + typedef struct _zend_accel_shared_globals { /* Cache Data Structures */ zend_ulong hits; diff --git a/ext/opcache/tests/gh9259_001.phpt b/ext/opcache/tests/gh9259_001.phpt index bcc0f113c57f6..3a507669bc1dd 100644 --- a/ext/opcache/tests/gh9259_001.phpt +++ b/ext/opcache/tests/gh9259_001.phpt @@ -13,6 +13,6 @@ echo 'OK'; ?> --EXPECTF-- -%sWarning opcache.interned_strings_buffer must be less than or equal to 4095, 131072 given%s +%sWarning opcache.interned_strings_buffer must be less than or equal to 32767, 131072 given%s OK diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index f5dbeadf51f86..f688126cdf4f7 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -41,7 +41,17 @@ #define STRING_NOT_NULL(s) (NULL == (s)?"":s) #define MIN_ACCEL_FILES 200 #define MAX_ACCEL_FILES 1000000 -#define MAX_INTERNED_STRINGS_BUFFER_SIZE ((zend_long)((UINT32_MAX-PLATFORM_ALIGNMENT-sizeof(zend_accel_shared_globals))/(1024*1024))) +/* Max value of opcache.interned_strings_buffer */ +#define MAX_INTERNED_STRINGS_BUFFER_SIZE ((zend_long)MIN( \ + MIN( \ + /* STRTAB_STR_TO_POS() must not overflow (zend_string_table_pos_t) */ \ + (ZEND_STRING_TABLE_POS_MAX - sizeof(zend_string_table)) / (1024 * 1024 / ZEND_STRING_TABLE_POS_ALIGNMENT), \ + /* nTableMask must not overflow (uint32_t) */ \ + UINT32_MAX / (32 * 1024 * sizeof(zend_string_table_pos_t)) \ + ), \ + /* SHM allocation must not overflow (size_t) */ \ + (SIZE_MAX - sizeof(zend_accel_shared_globals)) / (1024 * 1024) \ +)) #define TOKENTOSTR(X) #X static zif_handler orig_file_exists = NULL; diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index bfff9ad5cef79..8db61ed3f3465 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -369,11 +369,7 @@ void *zend_shared_alloc(size_t size) ZEND_ASSERT(ZCG(locked)); int i; - unsigned int block_size = ZEND_ALIGNED_SIZE(size); - - if (UNEXPECTED(block_size < size)) { - zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Possible integer overflow in shared memory allocation (%zu + %zu)", size, PLATFORM_ALIGNMENT); - } + size_t block_size = ZEND_ALIGNED_SIZE(size); if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */ SHARED_ALLOC_FAILED();