summaryrefslogtreecommitdiff
path: root/ext/opcache
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-02-24 23:46:11 +0300
committerDmitry Stogov <dmitry@zend.com>2016-02-24 23:46:11 +0300
commit6842a3674d8eadf9fac40411d21dd8b015e132f5 (patch)
treef110eeb209e42aab3137afec85f05b0f666ac216 /ext/opcache
parent43366f8ba82a68e74ccb568951ae809533d6d672 (diff)
downloadphp-git-6842a3674d8eadf9fac40411d21dd8b015e132f5.tar.gz
Fixed possible crash at PCRE on MSHUTDOWN
Diffstat (limited to 'ext/opcache')
-rw-r--r--ext/opcache/ZendAccelerator.c2
-rw-r--r--ext/opcache/zend_file_cache.c12
-rw-r--r--ext/opcache/zend_shared_alloc.c13
-rw-r--r--ext/opcache/zend_shared_alloc.h2
4 files changed, 24 insertions, 5 deletions
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index cd91dfbc4b..48b8d6a682 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -1992,7 +1992,7 @@ static void accel_reset_pcre_cache(void)
ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) {
/* Remove PCRE cache entries with inconsistent keys */
- if (ZSTR_IS_INTERNED(p->key)) {
+ if (zend_accel_in_shm(p->key)) {
p->key = NULL;
zend_hash_del_bucket(&PCRE_G(pcre_cache), p);
}
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index b65abca225..3187412423 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -132,8 +132,13 @@ static int zend_file_cache_flock(int fd, int type)
} else { \
ZEND_ASSERT(IS_SERIALIZED(ptr)); \
(ptr) = (void*)((char*)buf + (size_t)(ptr)); \
- GC_FLAGS(ptr) |= IS_STR_INTERNED; \
- GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \
+ /* script->corrupted shows if the script in SHM or not */ \
+ if (EXPECTED(!script->corrupted)) { \
+ GC_FLAGS(ptr) |= IS_STR_INTERNED | IS_STR_PERMANENT; \
+ } else { \
+ GC_FLAGS(ptr) |= IS_STR_INTERNED; \
+ GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \
+ } \
} \
} \
} while (0)
@@ -223,8 +228,7 @@ static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
ret = accel_new_interned_string(str);
if (ret == str) {
/* String wasn't interned but we will use it as interned anyway */
- GC_FLAGS(ret) |= IS_STR_INTERNED;
- GC_FLAGS(ret) &= ~IS_STR_PERMANENT;
+ GC_FLAGS(ret) |= IS_STR_INTERNED | IS_STR_PERMANENT;
}
} else {
ret = str;
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index d616c7d62f..6625fe23c3 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -507,3 +507,16 @@ void zend_accel_shared_protect(int mode)
}
#endif
}
+
+int zend_accel_in_shm(void *ptr)
+{
+ int i;
+
+ for (i = 0; i < ZSMMG(shared_segments_count); i++) {
+ if ((char*)ptr >= (char*)ZSMMG(shared_segments)[i]->p &&
+ (char*)ptr < (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->size) {
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h
index 3993b0689e..03b82d16ac 100644
--- a/ext/opcache/zend_shared_alloc.h
+++ b/ext/opcache/zend_shared_alloc.h
@@ -128,6 +128,8 @@ void *zend_shared_alloc(size_t size);
void *_zend_shared_memdup(void *p, size_t size, zend_bool free_source);
int zend_shared_memdup_size(void *p, size_t size);
+int zend_accel_in_shm(void *ptr);
+
typedef union _align_test {
void *ptr;
double dbl;