diff options
author | Dmitry Stogov <dmitry@zend.com> | 2016-02-24 23:46:11 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2016-02-24 23:46:11 +0300 |
commit | 6842a3674d8eadf9fac40411d21dd8b015e132f5 (patch) | |
tree | f110eeb209e42aab3137afec85f05b0f666ac216 /ext/opcache | |
parent | 43366f8ba82a68e74ccb568951ae809533d6d672 (diff) | |
download | php-git-6842a3674d8eadf9fac40411d21dd8b015e132f5.tar.gz |
Fixed possible crash at PCRE on MSHUTDOWN
Diffstat (limited to 'ext/opcache')
-rw-r--r-- | ext/opcache/ZendAccelerator.c | 2 | ||||
-rw-r--r-- | ext/opcache/zend_file_cache.c | 12 | ||||
-rw-r--r-- | ext/opcache/zend_shared_alloc.c | 13 | ||||
-rw-r--r-- | ext/opcache/zend_shared_alloc.h | 2 |
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; |