Skip to content

Commit 89aa1b7

Browse files
committed
Ensure proper data alignment
1 parent 37f0c6b commit 89aa1b7

7 files changed

+38
-6
lines changed

Zend/zend_alloc.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ typedef zend_ulong zend_mm_bitset; /* 4-byte or 8-byte integer */
149149
(((size_t)(size)) & ((alignment) - 1))
150150
#define ZEND_MM_ALIGNED_BASE(size, alignment) \
151151
(((size_t)(size)) & ~((alignment) - 1))
152-
#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \
153-
(((size_t)(size) + ((alignment) - 1)) & ~((alignment) - 1))
154152
#define ZEND_MM_SIZE_TO_NUM(size, alignment) \
155153
(((size_t)(size) + ((alignment) - 1)) / (alignment))
156154

Zend/zend_alloc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242

4343
#define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - Z_L(1)) & ZEND_MM_ALIGNMENT_MASK)
4444

45+
#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \
46+
(((size) + ((alignment) - Z_L(1))) & ~((alignment) - Z_L(1)))
47+
4548
typedef struct _zend_leak_info {
4649
void *addr;
4750
size_t size;

Zend/zend_string.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ END_EXTERN_C()
6262
#define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1)
6363

6464
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
65-
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(_len)), (use_heap)); \
65+
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
6666
GC_REFCOUNT(str) = 1; \
6767
GC_TYPE_INFO(str) = IS_STRING; \
6868
zend_string_forget_hash_val(str); \

ext/opcache/zend_persist.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement
7979
HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
8080
return;
8181
}
82+
if (ht->nNumUsed == 0) {
83+
efree(HT_GET_DATA_ADDR(ht));
84+
ht->nTableMask = HT_MIN_MASK;
85+
HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
86+
ht->u.flags &= ~HASH_FLAG_INITIALIZED;
87+
return;
88+
}
8289
if (ht->u.flags & HASH_FLAG_PACKED) {
8390
void *data = HT_GET_DATA_ADDR(ht);
8491
zend_accel_store(data, HT_USED_SIZE(ht));
@@ -92,7 +99,11 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement
9299
while (hash_size >> 1 > ht->nNumUsed) {
93100
hash_size >>= 1;
94101
}
102+
if (hash_size < -HT_MIN_MASK) {
103+
hash_size = -HT_MIN_MASK;
104+
}
95105
ht->nTableMask = -hash_size;
106+
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
96107
HT_SET_DATA_ADDR(ht, ZCG(mem));
97108
ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))));
98109
HT_HASH_RESET(ht);
@@ -120,6 +131,7 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement
120131
void *data = ZCG(mem);
121132
void *old_data = HT_GET_DATA_ADDR(ht);
122133

134+
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
123135
ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht));
124136
memcpy(data, old_data, HT_USED_SIZE(ht));
125137
efree(old_data);
@@ -149,6 +161,13 @@ static void zend_hash_persist_immutable(HashTable *ht)
149161
HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
150162
return;
151163
}
164+
if (ht->nNumUsed == 0) {
165+
efree(HT_GET_DATA_ADDR(ht));
166+
ht->nTableMask = HT_MIN_MASK;
167+
HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
168+
ht->u.flags &= ~HASH_FLAG_INITIALIZED;
169+
return;
170+
}
152171
if (ht->u.flags & HASH_FLAG_PACKED) {
153172
HT_SET_DATA_ADDR(ht, zend_accel_memdup(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht)));
154173
} else if (ht->nNumUsed < -(int32_t)ht->nTableMask / 2) {
@@ -160,7 +179,11 @@ static void zend_hash_persist_immutable(HashTable *ht)
160179
while (hash_size >> 1 > ht->nNumUsed) {
161180
hash_size >>= 1;
162181
}
182+
if (hash_size < -HT_MIN_MASK) {
183+
hash_size = -HT_MIN_MASK;
184+
}
163185
ht->nTableMask = -hash_size;
186+
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
164187
HT_SET_DATA_ADDR(ht, ZCG(mem));
165188
ZCG(mem) = (void*)((char*)ZCG(mem) + (hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket)));
166189
HT_HASH_RESET(ht);
@@ -187,6 +210,7 @@ static void zend_hash_persist_immutable(HashTable *ht)
187210
} else {
188211
void *data = ZCG(mem);
189212

213+
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
190214
ZCG(mem) = (void*)((char*)data + HT_USED_SIZE(ht));
191215
memcpy(data, HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht));
192216
HT_SET_DATA_ADDR(ht, data);
@@ -869,6 +893,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
869893
{
870894
script->mem = ZCG(mem);
871895

896+
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
872897
zend_shared_alloc_clear_xlat_table();
873898

874899
zend_accel_store(script, sizeof(zend_persistent_script));
@@ -880,6 +905,8 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
880905
#ifdef __SSE2__
881906
/* Align to 64-byte boundary */
882907
ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
908+
#else
909+
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
883910
#endif
884911

885912
script->arena_mem = ZCG(arena_mem) = ZCG(mem);

ext/opcache/zend_persist_calc.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *
5454
uint idx;
5555
Bucket *p;
5656

57-
if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
57+
if (!(ht->u.flags & HASH_FLAG_INITIALIZED) || ht->nNumUsed == 0) {
5858
return;
5959
}
6060

@@ -65,6 +65,9 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *
6565
while (hash_size >> 1 > ht->nNumUsed) {
6666
hash_size >>= 1;
6767
}
68+
if (hash_size < -HT_MIN_MASK) {
69+
hash_size = -HT_MIN_MASK;
70+
}
6871
ADD_SIZE(hash_size * sizeof(uint32_t) + ht->nNumUsed * sizeof(Bucket));
6972
} else {
7073
ADD_SIZE(HT_USED_SIZE(ht));

ext/opcache/zend_shared_alloc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ void *zend_shared_alloc(size_t size)
313313
ZSMMG(shared_segments)[i]->pos += block_size;
314314
ZSMMG(shared_free) -= block_size;
315315
memset(retval, 0, block_size);
316+
ZEND_ASSERT(((zend_uintptr_t)retval & 0x7) == 0); /* should be 8 byte aligned */
316317
return retval;
317318
}
318319
}

ext/opcache/zend_shared_alloc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,13 @@ typedef union _align_test {
134134
} align_test;
135135

136136
#if ZEND_GCC_VERSION >= 2000
137-
# define PLATFORM_ALIGNMENT (__alignof__ (align_test))
137+
# define PLATFORM_ALIGNMENT (__alignof__(align_test) < 8 ? 8 : __alignof__(align_test))
138138
#else
139139
# define PLATFORM_ALIGNMENT (sizeof(align_test))
140140
#endif
141141

142142
#define ZEND_ALIGNED_SIZE(size) \
143-
((size + PLATFORM_ALIGNMENT - 1) & ~(PLATFORM_ALIGNMENT - 1))
143+
ZEND_MM_ALIGNED_SIZE_EX(size, PLATFORM_ALIGNMENT)
144144

145145
/* exclusive locking */
146146
void zend_shared_alloc_lock(void);

0 commit comments

Comments
 (0)