Skip to content

Instantly share code, notes, and snippets.

@nikic
Created March 1, 2021 13:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikic/1675c810004567265411baa1e1c3ae4f to your computer and use it in GitHub Desktop.
Save nikic/1675c810004567265411baa1e1c3ae4f to your computer and use it in GitHub Desktop.
commit 0c9c19300346c58836c8ba073240a041817fb199
Author: Nikita Popov <nikita.ppv@gmail.com>
Date: Mon Mar 1 12:51:53 2021 +0100
Fixed bug #80815
Suppress redefined function error if the function was defined
during preloading (that is, exactly that function was defined,
not some other under the same name).
diff --git a/NEWS b/NEWS
index 46aa23e007..48242a1ee7 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,8 @@ PHP NEWS
- OPcache:
. Fixed bug #80682 (opcache doesn't honour pcre.jit option). (Remi)
+ . Fixed bug #80815 (opcache.preload duplicate definition with conditionally
+ defined function). (Nikita)
- OpenSSL:
. Fixed bug #80747 (Providing RSA key size < 512 generates key that crash
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index df4cd4b2f3..1794565f1c 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1046,6 +1046,13 @@ ZEND_API int do_bind_function(zval *lcname) /* {{{ */
rtd_key = lcname + 1;
zv = zend_hash_find_ex(EG(function_table), Z_STR_P(rtd_key), 1);
if (UNEXPECTED(!zv)) {
+ zv = zend_hash_find(EG(function_table), Z_STR_P(lcname));
+ function = Z_PTR_P(zv);
+ if (function->common.fn_flags & ZEND_ACC_PRELOADED) {
+ /* This dynamic function declaration was already defined during preloading. */
+ return SUCCESS;
+ }
+
do_bind_function_error(Z_STR_P(lcname), NULL, 0);
return FAILURE;
}
diff --git a/ext/opcache/tests/preload_bug80815.inc b/ext/opcache/tests/preload_bug80815.inc
new file mode 100644
index 0000000000..a9b4ce1a35
--- /dev/null
+++ b/ext/opcache/tests/preload_bug80815.inc
@@ -0,0 +1,17 @@
+<?php
+
+if (false) {
+ function myFunction() {
+ return 1;
+ }
+} else {
+ function myFunction() {
+ return 2;
+ }
+}
+
+function declareMyFunction() {
+ function myFunction() {
+ return 3;
+ }
+}
diff --git a/ext/opcache/tests/preload_bug80815.phpt b/ext/opcache/tests/preload_bug80815.phpt
new file mode 100644
index 0000000000..69f1b04cb4
--- /dev/null
+++ b/ext/opcache/tests/preload_bug80815.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #80815: opcache.preload duplicate definition with conditionally defined function
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.preload={PWD}/preload_bug80815.inc
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
+?>
+--FILE--
+<?php
+require __DIR__ . '/preload_bug80815.inc';
+var_dump(myFunction());
+declareMyFunction();
+?>
+--EXPECTF--
+int(2)
+
+Fatal error: Cannot redeclare myFunction() (previously declared in %s:9) in %s on line 14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment