Bug #70656 [Asn]: require() statement broken after opcache_reset() or a few hours of use

From: Date: Sun, 01 Nov 2015 03:30:38 +0000
Subject: Bug #70656 [Asn]: require() statement broken after opcache_reset() or a few hours of use
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-196950@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=70656&edit=1

 ID:                 70656
 Updated by:         laruence@php.net
 Reported by:        p at wspnr dot com
 Summary:            require() statement broken after opcache_reset() or
                     a few hours of use
 Status:             Assigned
 Type:               Bug
 Package:            opcache
 Operating System:   Debian (x86_64 and i686)
 PHP Version:        7.0Git-2015-10-07 (Git)
 Assigned To:        laruence
 Block user comment: N
 Private report:     N

 New Comment:

actually, it's intentional only copy Z_STRLEN, please verify this fix:

diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index eaadac6..18862b3 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -249,24 +249,27 @@ static void accel_interned_strings_restore_state(void)
     uint nIndex;
     Bucket *p;

-	ZCSG(interned_strings_top) = ZCSG(interned_strings_saved_top);
-    while (idx > 0) {
-    	idx--;
-		p = ZCSG(interned_strings).arData + idx;
-		if ((char*)p->key < ZCSG(interned_strings_top)) break;
-		ZCSG(interned_strings).nNumUsed--;
-		ZCSG(interned_strings).nNumOfElements--;
-
-		nIndex = p->h | ZCSG(interned_strings).nTableMask;
-		if (HT_HASH(&ZCSG(interned_strings), nIndex) == HT_IDX_TO_HASH(idx)) {
-			HT_HASH(&ZCSG(interned_strings), nIndex) = Z_NEXT(p->val);
-		} else {
-			uint32_t prev = HT_HASH(&ZCSG(interned_strings), nIndex);
-			while (Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val) != idx) {
-				prev = Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val);
- 			}
-			Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val) = Z_NEXT(p->val);
- 		}
+	if (EXPECTED(ZCSG(interned_strings_top) > ZCSG(interned_strings_saved_top))) {
+		memset(ZCSG(interned_strings_saved_top),0, ZCSG(interned_strings_top) -
ZCSG(interned_strings_saved_top));
+		ZCSG(interned_strings_top) = ZCSG(interned_strings_saved_top);
+		while (idx > 0) {
+			idx--;
+			p = ZCSG(interned_strings).arData + idx;
+			if ((char*)p->key < ZCSG(interned_strings_top)) break;
+			ZCSG(interned_strings).nNumUsed--;
+			ZCSG(interned_strings).nNumOfElements--;
+
+			nIndex = p->h | ZCSG(interned_strings).nTableMask;
+			if (HT_HASH(&ZCSG(interned_strings), nIndex) == HT_IDX_TO_HASH(idx)) {
+				HT_HASH(&ZCSG(interned_strings), nIndex) = Z_NEXT(p->val);
+			} else {
+				uint32_t prev = HT_HASH(&ZCSG(interned_strings), nIndex);
+				while (Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val) != idx) {
+					prev = Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val);
+				}
+				Z_NEXT(HT_HASH_TO_BUCKET(&ZCSG(interned_strings), prev)->val) = Z_NEXT(p->val);
+			}
+		}
 	}
 }


Previous Comments:
------------------------------------------------------------------------
[2015-10-31 17:49:34] kalle@php.net

Hey Xinchen, can you confirm this fix is proper or clarify the behavior? Thanks

------------------------------------------------------------------------
[2015-10-31 08:09:31] tony dot levi at blackboard dot com

I can confirm that workaround and proposed fix solve the issue for me.

It looks like the right solution - based on pattern elsewhere - but I'm not an expert either.

------------------------------------------------------------------------
[2015-10-30 17:45:43] p at wspnr dot com

I spent some time today tracing this bug as it is preventing our migration to PHP 7.

The bug is caused by the opcache interned strings functionality. A simple workaround is to set

opcache.interned_strings_buffer = 0

in php.ini.

Looking at the code, I believe that the bug might be caused by this [0] call to memcpy(). Changing
this to 

memcpy(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str) + 1);

has made the issue go away. However I am not familiar enough with opcache to determine whether this
is an acceptable change.

[0] http://lxr.php.net/xref/PHP_MASTER/ext/opcache/ZendAccelerator.c#374

------------------------------------------------------------------------
[2015-10-30 12:36:25] machin dot dmitry at gmail dot com

The same bug.
Ubuntu 14.04.3 LTS
PHP 7.0.1-dev (cli) (built: Oct 29 2015 10:15:42) ( NTS )

from PHP-7.0 branch

------------------------------------------------------------------------
[2015-10-25 15:55:10] p at wspnr dot com

Updated bug summary

------------------------------------------------------------------------


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=70656


--
Edit this bug report at https://bugs.php.net/bug.php?id=70656&edit=1


Thread (13 messages)

« previous php.bugs (#196950) next »