diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-08-31 13:56:42 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-08-31 13:56:42 +0300 |
commit | 89aa1b73929d3a02d4e0bae6edf76e6b325ce8f9 (patch) | |
tree | c24d82df8672666e65c9ea41153d1016f3e61269 | |
parent | 37f0c6b5cb4f8ad01651b3ea80712f6a8b6f2ea0 (diff) | |
download | php-git-89aa1b73929d3a02d4e0bae6edf76e6b325ce8f9.tar.gz |
Ensure proper data alignment
-rw-r--r-- | Zend/zend_alloc.c | 2 | ||||
-rw-r--r-- | Zend/zend_alloc.h | 3 | ||||
-rw-r--r-- | Zend/zend_string.h | 2 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 27 | ||||
-rw-r--r-- | ext/opcache/zend_persist_calc.c | 5 | ||||
-rw-r--r-- | ext/opcache/zend_shared_alloc.c | 1 | ||||
-rw-r--r-- | ext/opcache/zend_shared_alloc.h | 4 |
7 files changed, 38 insertions, 6 deletions
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index c30d26b623..78845e6cac 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -149,8 +149,6 @@ typedef zend_ulong zend_mm_bitset; /* 4-byte or 8-byte integer */ (((size_t)(size)) & ((alignment) - 1)) #define ZEND_MM_ALIGNED_BASE(size, alignment) \ (((size_t)(size)) & ~((alignment) - 1)) -#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \ - (((size_t)(size) + ((alignment) - 1)) & ~((alignment) - 1)) #define ZEND_MM_SIZE_TO_NUM(size, alignment) \ (((size_t)(size) + ((alignment) - 1)) / (alignment)) diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 787597366a..cd4bb62e1d 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -42,6 +42,9 @@ #define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - Z_L(1)) & ZEND_MM_ALIGNMENT_MASK) +#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \ + (((size) + ((alignment) - Z_L(1))) & ~((alignment) - Z_L(1))) + typedef struct _zend_leak_info { void *addr; size_t size; diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 137545624e..9c022e8b89 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -62,7 +62,7 @@ END_EXTERN_C() #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1) #define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \ - (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(_len)), (use_heap)); \ + (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \ GC_REFCOUNT(str) = 1; \ GC_TYPE_INFO(str) = IS_STRING; \ zend_string_forget_hash_val(str); \ diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 243d99e255..dec68b7cd7 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -79,6 +79,13 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement HT_SET_DATA_ADDR(ht, &uninitialized_bucket); return; } + if (ht->nNumUsed == 0) { + efree(HT_GET_DATA_ADDR(ht)); + ht->nTableMask = HT_MIN_MASK; + HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + ht->u.flags &= ~HASH_FLAG_INITIALIZED; + return; + } if (ht->u.flags & HASH_FLAG_PACKED) { void *data = HT_GET_DATA_ADDR(ht); zend_accel_store(data, HT_USED_SIZE(ht)); @@ -92,7 +99,11 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement while (hash_size >> 1 > ht->nNumUsed) { hash_size >>= 1; } + if (hash_size < -HT_MIN_MASK) { + hash_size = -HT_MIN_MASK; + } ht->nTableMask = -hash_size; + ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ HT_SET_DATA_ADDR(ht, ZCG(mem)); ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket)))); HT_HASH_RESET(ht); @@ -120,6 +131,7 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement void *data = ZCG(mem); void *old_data = HT_GET_DATA_ADDR(ht); + ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht)); memcpy(data, old_data, HT_USED_SIZE(ht)); efree(old_data); @@ -149,6 +161,13 @@ static void zend_hash_persist_immutable(HashTable *ht) HT_SET_DATA_ADDR(ht, &uninitialized_bucket); return; } + if (ht->nNumUsed == 0) { + efree(HT_GET_DATA_ADDR(ht)); + ht->nTableMask = HT_MIN_MASK; + HT_SET_DATA_ADDR(ht, &uninitialized_bucket); + ht->u.flags &= ~HASH_FLAG_INITIALIZED; + return; + } if (ht->u.flags & HASH_FLAG_PACKED) { HT_SET_DATA_ADDR(ht, zend_accel_memdup(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht))); } else if (ht->nNumUsed < -(int32_t)ht->nTableMask / 2) { @@ -160,7 +179,11 @@ static void zend_hash_persist_immutable(HashTable *ht) while (hash_size >> 1 > ht->nNumUsed) { hash_size >>= 1; } + if (hash_size < -HT_MIN_MASK) { + hash_size = -HT_MIN_MASK; + } ht->nTableMask = -hash_size; + ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ HT_SET_DATA_ADDR(ht, ZCG(mem)); ZCG(mem) = (void*)((char*)ZCG(mem) + (hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))); HT_HASH_RESET(ht); @@ -187,6 +210,7 @@ static void zend_hash_persist_immutable(HashTable *ht) } else { void *data = ZCG(mem); + ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht)); memcpy(data, HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht)); HT_SET_DATA_ADDR(ht, data); @@ -869,6 +893,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script { script->mem = ZCG(mem); + ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ zend_shared_alloc_clear_xlat_table(); zend_accel_store(script, sizeof(zend_persistent_script)); @@ -880,6 +905,8 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script #ifdef __SSE2__ /* Align to 64-byte boundary */ ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L); +#else + ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */ #endif script->arena_mem = ZCG(arena_mem) = ZCG(mem); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index d78cc59259..5217c2ca9e 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -54,7 +54,7 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval * uint idx; Bucket *p; - if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { + if (!(ht->u.flags & HASH_FLAG_INITIALIZED) || ht->nNumUsed == 0) { return; } @@ -65,6 +65,9 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval * while (hash_size >> 1 > ht->nNumUsed) { hash_size >>= 1; } + if (hash_size < -HT_MIN_MASK) { + hash_size = -HT_MIN_MASK; + } ADD_SIZE(hash_size * sizeof(uint32_t) + ht->nNumUsed * sizeof(Bucket)); } else { ADD_SIZE(HT_USED_SIZE(ht)); diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index ca50ab9219..09da83a6a6 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -313,6 +313,7 @@ void *zend_shared_alloc(size_t size) ZSMMG(shared_segments)[i]->pos += block_size; ZSMMG(shared_free) -= block_size; memset(retval, 0, block_size); + ZEND_ASSERT(((zend_uintptr_t)retval & 0x7) == 0); /* should be 8 byte aligned */ return retval; } } diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h index 63947169b4..398b64f432 100644 --- a/ext/opcache/zend_shared_alloc.h +++ b/ext/opcache/zend_shared_alloc.h @@ -134,13 +134,13 @@ typedef union _align_test { } align_test; #if ZEND_GCC_VERSION >= 2000 -# define PLATFORM_ALIGNMENT (__alignof__ (align_test)) +# define PLATFORM_ALIGNMENT (__alignof__(align_test) < 8 ? 8 : __alignof__(align_test)) #else # define PLATFORM_ALIGNMENT (sizeof(align_test)) #endif #define ZEND_ALIGNED_SIZE(size) \ - ((size + PLATFORM_ALIGNMENT - 1) & ~(PLATFORM_ALIGNMENT - 1)) + ZEND_MM_ALIGNED_SIZE_EX(size, PLATFORM_ALIGNMENT) /* exclusive locking */ void zend_shared_alloc_lock(void); |