|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2017-06-23 15:47 UTC] nikic@php.net
-Status: Open
+Status: Not a bug
[2017-06-23 15:47 UTC] nikic@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 09:00:02 2025 UTC |
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 }