summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-08-31 13:56:42 +0300
committerDmitry Stogov <dmitry@zend.com>2015-08-31 13:56:42 +0300
commit89aa1b73929d3a02d4e0bae6edf76e6b325ce8f9 (patch)
treec24d82df8672666e65c9ea41153d1016f3e61269
parent37f0c6b5cb4f8ad01651b3ea80712f6a8b6f2ea0 (diff)
downloadphp-git-89aa1b73929d3a02d4e0bae6edf76e6b325ce8f9.tar.gz
Ensure proper data alignment
-rw-r--r--Zend/zend_alloc.c2
-rw-r--r--Zend/zend_alloc.h3
-rw-r--r--Zend/zend_string.h2
-rw-r--r--ext/opcache/zend_persist.c27
-rw-r--r--ext/opcache/zend_persist_calc.c5
-rw-r--r--ext/opcache/zend_shared_alloc.c1
-rw-r--r--ext/opcache/zend_shared_alloc.h4
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);