]> granicus.if.org Git - php/commitdiff
Ensure proper data alignment
authorDmitry Stogov <dmitry@zend.com>
Mon, 31 Aug 2015 10:56:42 +0000 (13:56 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 31 Aug 2015 10:56:42 +0000 (13:56 +0300)
Zend/zend_alloc.c
Zend/zend_alloc.h
Zend/zend_string.h
ext/opcache/zend_persist.c
ext/opcache/zend_persist_calc.c
ext/opcache/zend_shared_alloc.c
ext/opcache/zend_shared_alloc.h

index c30d26b6239d325b5d3bff7753a5fd316ceac5d1..78845e6cacd3bf8bfb35826c99fd3bb82f5088a3 100644 (file)
@@ -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))
 
index 787597366a91968a77ebde1b995e1cd326d4919e..cd4bb62e1d392e4ff2b37cb4bb066f2840a9698b 100644 (file)
@@ -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;
index 137545624e59b6b5c8a559c9e8e99016c732fb7f..9c022e8b895c56074da6fe0a97f7b0e9f8a6e656 100644 (file)
@@ -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); \
index 243d99e2557882baeb30ade9c96cacb878cff077..dec68b7cd710cebfe2185806b01af5df32891731 100644 (file)
@@ -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);
index d78cc592591f10cf5b5491011a1ca8fe3aa34e1d..5217c2ca9e6b7e88c891fa2284d776f48964e13c 100644 (file)
@@ -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));
index ca50ab92193cd1b49dd1c15584ee08a37f5f00d3..09da83a6a63da902bdea62a0fa6e8bf4b84a788b 100644 (file)
@@ -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;
                }
        }
index 63947169b430b1e2a3684a6b0afeff4350cd3f49..398b64f432a6a68f05c691469edfadad4bd8e565 100644 (file)
@@ -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);