]> granicus.if.org Git - php/commitdiff
Fixed bug #75579 (Interned strings buffer overflow may cause crash)
authorDmitry Stogov <dmitry@zend.com>
Thu, 21 Dec 2017 20:34:21 +0000 (23:34 +0300)
committerAnatol Belski <ab@php.net>
Fri, 22 Dec 2017 17:22:08 +0000 (18:22 +0100)
(cherry picked from commit 37bf8bdc1494abb2ce5cac40e0be80e23682f851)

NEWS
ext/opcache/zend_file_cache.c

diff --git a/NEWS b/NEWS
index 14fd16a2f8cfaf1f8cf40d5022549576ad255715..954f8bf4a1a3b690f78b81147e4f041186e5d848 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,9 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2017 PHP 7.0.28
 
-
+- Opcache:
+  . Fixed bug #75579 (Interned strings buffer overflow may cause crash).
+    (Dmitry)
 
 04 Jan 2017 PHP 7.0.27
 
index 2b65685d21db155e310a55aefee5b4dfbeab9879..4b8ee9583176447c011ce709ccb68fea2e618d5e 100644 (file)
@@ -227,8 +227,17 @@ static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
        if (in_shm) {
                ret = accel_new_interned_string(str);
                if (ret == str) {
+                       /* We have to create new SHM allocated string */
+                       size_t size = _ZSTR_STRUCT_SIZE(ZSTR_LEN(str));
+                       ret = zend_shared_alloc(size);
+                       if (!ret) {
+                               zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
+                               LONGJMP(*EG(bailout), FAILURE);
+                       }
+                       memcpy(ret, str, size);
                        /* String wasn't interned but we will use it as interned anyway */
-                       GC_FLAGS(ret) |= IS_STR_INTERNED | IS_STR_PERMANENT;
+                       GC_REFCOUNT(ret) = 1;
+                       GC_TYPE_INFO(ret) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERSISTENT | IS_STR_PERMANENT) << 8);
                }
        } else {
                ret = str;
@@ -1251,6 +1260,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
        zend_accel_hash_entry *bucket;
        void *mem, *checkpoint, *buf;
        int cache_it = 1;
+       int ok;
 
        if (!full_path) {
                return NULL;
@@ -1343,6 +1353,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
 
        if (!ZCG(accel_directives).file_cache_only &&
            !ZCSG(restart_in_progress) &&
+               !ZSMMG(memory_exhausted) &&
            accelerator_shm_read_lock() == SUCCESS) {
                /* exclusive lock */
                zend_shared_alloc_lock();
@@ -1392,7 +1403,24 @@ use_process_mem:
        ZCG(mem) = ((char*)mem + info.mem_size);
        script = (zend_persistent_script*)((char*)buf + info.script_offset);
        script->corrupted = !cache_it; /* used to check if script restored to SHM or process memory */
-       zend_file_cache_unserialize(script, buf);
+
+       ok = 1;
+       zend_try {
+               zend_file_cache_unserialize(script, buf);
+       } zend_catch {
+               ok = 0;
+       } zend_end_try();
+       if (!ok) {
+               if (cache_it) {
+                       zend_shared_alloc_unlock();
+                       goto use_process_mem;
+               } else {
+                       zend_arena_release(&CG(arena), checkpoint);
+                       efree(filename);
+                       return NULL;
+               }
+       }
+
        script->corrupted = 0;
 
        if (cache_it) {