php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74540 use-after-free bug
Submitted: 2017-05-04 07:49 UTC Modified: 2017-06-23 15:47 UTC
From: yanhuacs at gmail dot com Assigned:
Status: Not a bug Package: opcache
PHP Version: 5.6.30 OS: Ubuntu14.04
Private report: No CVE-ID: None
 [2017-05-04 07:49 UTC] yanhuacs at gmail dot com
Description:
------------
I'd like to report potential a use-after-free bug in PHP-5.6.30 as follows.

Step 1, in ext/opcache/zend_persist.c,
function zend_ast *zend_persist_ast calls function _zend_shared_memdup in line 153.
Step 2, in ext/opcache/zend_shared_alloc.c,
function _zend_shared_memdup frees "source", which is a pointer aliased with "ast" (due to parameter passing) in line 153 in ext/opcache/zend_persist.c.
Step 3, _zend_shared_memdup returns to its call site in line 153 in ext/opcache/zend_persist.c.
Step 4, in line 154, "ast" is dereferenced, which is a use-after-free.


/*--- ext/opcache/zend_persist.c ---*/
143 static zend_ast *zend_persist_ast(zend_ast *ast TSRMLS_DC)
144 {
145         int i;
146         zend_ast *node;
147
148         if (ast->kind == ZEND_CONST) {
149                 node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zval));
150                 node->u.val = (zval*)(node + 1);
151                 zend_persist_zval(node->u.val TSRMLS_CC);
152         } else {
153                 node = zend_accel_memdup(ast, sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1));
154                 for (i = 0; i < ast->children; i++) {
155                         if ((&node->u.child)[i]) {
156                                 (&node->u.child)[i] = zend_persist_ast((&node->u.child)[i] TSRMLS_CC);
157                         }
158                 }
159         }
160         efree(ast);
161         return node;
162 }


/*--- ext/opcache/zend_shared_alloc.c ---*/
338 void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRMLS_DC)
339 {
340         void **old_p, *retval;
341
342         if (zend_hash_index_find(&xlat_table, (ulong)source, (void **)&old_p) == SUCCESS) {
343                 /* we already duplicated this pointer */
344                 return *old_p;
345         }
346         retval = ZCG(mem);;
347         ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
348         memcpy(retval, source, size);
349         zend_shared_alloc_register_xlat_entry(source, retval);
350         if (free_source) {
351                 interned_efree((char*)source);
352         }
353         return retval;
354 }



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-06-23 15:47 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2017-06-23 15:47 UTC] nikic@php.net
Closing as not a bug, as this is essentially the same as bug #74539, but for PHP 5.6 and the same comments apply.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 23:01:28 2024 UTC