]> granicus.if.org Git - php/commitdiff
Fixed possible crash at PCRE on MSHUTDOWN
authorDmitry Stogov <dmitry@zend.com>
Wed, 24 Feb 2016 20:46:11 +0000 (23:46 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 24 Feb 2016 20:46:11 +0000 (23:46 +0300)
ext/opcache/ZendAccelerator.c
ext/opcache/zend_file_cache.c
ext/opcache/zend_shared_alloc.c
ext/opcache/zend_shared_alloc.h

index cd91dfbc4b4e8ef53bac8fe22001bde533acc3d5..48b8d6a682f7b62ddaef4a500d1a46a1cb9f512b 100644 (file)
@@ -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);
                }
index b65abca2254a149b641da1dd83d82862bdbf3990..31874124239224b3d98c2c836412de65014992d6 100644 (file)
@@ -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;
index d616c7d62f443d6f6bb1e79dbf3277b2c05e468d..6625fe23c314acddbae810ae2ecfc8cfbc23f34d 100644 (file)
@@ -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;
+}
index 3993b0689efcd9d1e515d8c4126b738472e3b97a..03b82d16ac306056d806f6a97ece11f776e49ad7 100644 (file)
@@ -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;