Bug #75579 [Ana]: All Interned Strings Free memory used and PHP crashes

From: Date: Wed, 20 Dec 2017 17:38:02 +0000
Subject: Bug #75579 [Ana]: All Interned Strings Free memory used and PHP crashes
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-213188@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75579&edit=1 ID: 75579 Updated by: nikic@php.net Reported by: post at minhost dot no Summary: All Interned Strings Free memory used and PHP crashes Status: Analyzed Type: Bug Package: opcache Operating System: CentOS 7.4 PHP Version: 7.1.12 Assigned To: dmitry Block user comment: N Private report: N New Comment: @post at minhost dot no: How did you apply the patch? It looks to me like you copy&pasted the entire file from the master branch maybe? Here's a variant of the patch that should work on 7.1: https://gist.github.com/nikic/31e8e4510a0ed84cea543b50d78ae431 It can be applied using "git apply" or "patch". Previous Comments: ------------------------------------------------------------------------ [2017-12-20 17:27:40] post at minhost dot no @dmitry: I applied your patch to PHP 7.1.13RC1, but I get errors when compiling PHP with your patch, so I am not able to compile it. Please try to compile it your self to see the problem. Please look into this. Here is the complete output with errors: /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c: In function 'zend_file_cache_serialize_ast': /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:286:49: error: 'ZEND_AST_CONSTANT' undeclared (first use in this function) if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:286:49: note: each undeclared identifier is reported only once for each function it appears in /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c: In function 'zend_file_cache_serialize_zval': /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:349:5: warning: passing argument 1 of 'zend_file_cache_serialize_ast' makes pointer from integer without a cast [enabled by default] zend_file_cache_serialize_ast(GC_AST(ast), script, info, buf); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:278:13: note: expected 'struct zend_ast *' but argument is of type 'int' static void zend_file_cache_serialize_ast(zend_ast *ast, ^ In file included from /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:21:0: /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c: In function 'zend_file_cache_serialize_op_array': /usr/local/directadmin/custombuild/php-7.1.13RC1/Zend/zend_compile.h:657:27: error: 'zend_op' has no member named 'literals' RT_CONSTANT_EX((op_array)->literals, node) ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/Zend/zend_compile.h:622:20: note: in definition of macro 'RT_CONSTANT_EX' ((zval*)(((char*)(base)) + (node).constant)) ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:423:28: note: in expansion of macro 'RT_CONSTANT' opline->op1.constant = RT_CONSTANT(opline, opline->op1) - literals; ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/Zend/zend_compile.h:657:27: error: 'zend_op' has no member named 'literals' RT_CONSTANT_EX((op_array)->literals, node) ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/Zend/zend_compile.h:622:20: note: in definition of macro 'RT_CONSTANT_EX' ((zval*)(((char*)(base)) + (node).constant)) ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:426:28: note: in expansion of macro 'RT_CONSTANT' opline->op2.constant = RT_CONSTANT(opline, opline->op2) - literals; ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:479:29: error: 'zend_arg_info' has no member named 'type' if (ZEND_TYPE_IS_CLASS(p->type)) { ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:480:51: error: 'zend_arg_info' has no member named 'type' zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(p->type); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:481:47: error: 'zend_arg_info' has no member named 'type' zend_string *type_name = ZEND_TYPE_NAME(p->type); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:484:7: error: 'zend_arg_info' has no member named 'type' p->type = ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:485:27: error: 'zend_type' undeclared (first use in this function) (Z_UL(1) << (sizeof(zend_type)*8-1)) | /* type is class */ ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:487:18: error: expected ';' before 'type_name' (zend_type)type_name; ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c: In function 'zend_file_cache_unserialize_ast': /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:908:49: error: 'ZEND_AST_CONSTANT' undeclared (first use in this function) if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) { ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c: In function 'zend_file_cache_unserialize_op_array': /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1024:64: error: macro "ZEND_PASS_TWO_UPDATE_CONSTANT" passed 3 arguments, but takes just 2 ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1024:5: error: 'ZEND_PASS_TWO_UPDATE_CONSTANT' undeclared (first use in this function) ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1027:64: error: macro "ZEND_PASS_TWO_UPDATE_CONSTANT" passed 3 arguments, but takes just 2 ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1079:10: error: 'zend_arg_info' has no member named 'type' if (p->type & (Z_UL(1) << (sizeof(zend_type)*8-1))) { /* type is class */ ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1079:39: error: 'zend_type' undeclared (first use in this function) if (p->type & (Z_UL(1) << (sizeof(zend_type)*8-1))) { /* type is class */ ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1080:31: error: 'zend_arg_info' has no member named 'type' zend_bool allow_null = (p->type & (Z_UL(1) << (sizeof(zend_type)*8-2))) != 0; /* type allow null */ ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1081:47: error: 'zend_arg_info' has no member named 'type' zend_string *type_name = (zend_string*)(p->type & ~(((Z_UL(1) << (sizeof(zend_type)*8-1))) | ((Z_UL(1) << (sizeof(zend_type)*8-2))))); ^ /usr/local/directadmin/custombuild/php-7.1.13RC1/ext/opcache/zend_file_cache.c:1084:7: error: 'zend_arg_info' has no member named 'type' p->type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null); ^ make: *** [ext/opcache/zend_file_cache.lo] Error 1 make: *** Waiting for unfinished jobs.... ------------------------------------------------------------------------ [2017-12-19 11:17:44] post at minhost dot no Thank you both, @nikic and @dmitry! I want to test the patch, however can I apply the patch from @dmitry directly into PHP 7.1.12? Or is it needed to use the 7.1.13 branch from https://github.com/php/php-src/tree/PHP-7.1.13 ? ------------------------------------------------------------------------ [2017-12-18 18:10:22] dmitry@php.net I committed a fix into the master branch https://github.com/php/php-src/commit/ce4fb228e033ef896517aea3d01eb8d9ac055366 Could you please verify, if this completely fixes the problem. Then, I'll backport it into PHP-7.* ------------------------------------------------------------------------ [2017-12-17 21:19:06] nikic@php.net @dmitry: Can you please take a look at this issue? I'm not sure what the best way to fix this is. Can we just zend_shared_alloc() the string in case the accel_new_interned_string() fails? An easy way to reproduce this is to enable the file cache, cache some files with opcache.interned_strings_buffer=8 and then load them using opcache.interned_strings_buffer=0. ------------------------------------------------------------------------ [2017-12-17 21:11:44] nikic@php.net The issue (presumably) is https://github.com/php/php-src/blob/master/ext/opcache/zend_file_cache.c#L229. If the script in the file cache uses an interned string, the string is not already in the interned string buffer, and the interned string buffer has run full, this simply directly returns the string from the string segment of the cached script. However, the string segment will be freed in https://github.com/php/php-src/blob/master/ext/opcache/zend_file_cache.c#L1467. The reason why you are only seeing this issue now is due to https://github.com/php/php-src/commit/d82805f097564558d94e3062e87b17d6ccae893f and the fact that you use revalidate_path=1. Prior to this fix, if revalidate_path=1 opcache accidentally did not use the interned string buffer for most things, which is why the file cache also did not contain interned strings. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=75579 -- Edit this bug report at https://bugs.php.net/bug.php?id=75579&edit=1

« previous php.bugs (#213188) next »