Remove support for preloading on Windows

Due to ASLR restrictions, preloading on Windows does not work with
any code that has preloading dependencies on internal classes.
This effectively makes it unusable for any non-trivial codebase.

Instead of pretending like preloading is going to work, only to
make people realize that it really doesn't once they get beyond
a dummy example, we disable support for preloading on Windows
entirely.

Closes GH-4999.
This commit is contained in:
Nikita Popov 2019-12-10 14:29:58 +01:00
parent 846b647953
commit 59c3ddab13
37 changed files with 147 additions and 141 deletions

1
NEWS
View File

@ -4,6 +4,7 @@ PHP NEWS
?? ??? ????, PHP 7.4.2
- Core:
. Preloading support on Windows has been disabled. (Nikita)
. Fixed bug #79022 (class_exists returns True for classes that are not ready
to be used). (Laruence)
. Fixed bug #78929 (plus signs in cookie values are converted to spaces).

View File

@ -1,24 +0,0 @@
--TEST--
FFI 300: FFI preloading on Windows
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php if (!extension_loaded('Zend OPcache')) die('skip Zend OPcache extension not available'); ?>
<?php if (substr(PHP_OS, 0, 3) != 'WIN') die('skip for Windows only'); ?>
--INI--
ffi.enable=1
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--FILE--
<?php
$ffi = FFI::scope("TEST_300_WIN32");
$ffi->php_printf("Hello World from %s!\n", "PHP");
?>
--CLEAN--
<?php
$fn = __DIR__ . "/300-win32.h";
unlink($fn);
?>
--EXPECT--
Hello World from PHP!

View File

@ -1,7 +1,10 @@
--TEST--
Bug #78761 (Zend memory heap corruption with preload and casting)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--INI--
opcache.enable_cli=1
opcache.preload={PWD}/bug78761_preload.php

View File

@ -3397,13 +3397,6 @@ static void get_unlinked_dependency(zend_class_entry *ce, const char **kind, con
*name = ZSTR_VAL(ce->parent_name);
return;
}
#ifdef ZEND_WIN32
if (p->type == ZEND_INTERNAL_CLASS) {
*kind = "Windows can't link to internal parent ";
*name = ZSTR_VAL(ce->parent_name);
return;
}
#endif
if (!(p->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
*kind = "Parent with unresolved initializers ";
*name = ZSTR_VAL(ce->parent_name);
@ -3523,13 +3516,6 @@ static zend_bool preload_try_resolve_property_types(zend_class_entry *ce)
continue;
}
if (p != ce) {
#ifdef ZEND_WIN32
/* On Windows we can't link with internal class, because of ASLR */
if (p->type == ZEND_INTERNAL_CLASS) {
ok = 0;
continue;
}
#endif
if (!(p->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
ok = 0;
continue;
@ -3666,10 +3652,6 @@ static void preload_link(void)
parent = zend_hash_find_ptr(EG(class_table), key);
zend_string_release(key);
if (!parent) continue;
#ifdef ZEND_WIN32
/* On Windows we can't link with internal class, because of ASLR */
if (parent->type == ZEND_INTERNAL_CLASS) continue;
#endif
if (!(parent->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
continue;
}
@ -3686,13 +3668,6 @@ static void preload_link(void)
found = 0;
break;
}
#ifdef ZEND_WIN32
/* On Windows we can't link with internal class, because of ASLR */
if (p->type == ZEND_INTERNAL_CLASS) {
found = 0;
break;
}
#endif
if (!(p->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
found = 0;
break;
@ -3709,13 +3684,6 @@ static void preload_link(void)
found = 0;
break;
}
#ifdef ZEND_WIN32
/* On Windows we can't link with internal class, because of ASLR */
if (p->type == ZEND_INTERNAL_CLASS) {
found = 0;
break;
}
#endif
}
if (!found) continue;
}
@ -3859,26 +3827,6 @@ static void preload_link(void)
} ZEND_HASH_FOREACH_END();
}
#ifdef ZEND_WIN32
static void preload_check_windows_restriction(zend_class_entry *scope, zend_class_entry *ce) {
if (ce && ce->type == ZEND_INTERNAL_CLASS) {
zend_error_noreturn(E_ERROR,
"Class %s uses internal class %s during preloading, which is not supported on Windows",
ZSTR_VAL(scope->name), ZSTR_VAL(ce->name));
}
}
static void preload_check_windows_restrictions(zend_class_entry *scope) {
uint32_t i;
preload_check_windows_restriction(scope, scope->parent);
for (i = 0; i < scope->num_interfaces; i++) {
preload_check_windows_restriction(scope, scope->interfaces[i]);
}
}
#endif
static inline int preload_update_class_constants(zend_class_entry *ce) {
/* This is a separate function to work around what appears to be a bug in GCC
* maybe-uninitialized analysis. */
@ -3931,10 +3879,6 @@ static void preload_ensure_classes_loadable() {
continue;
}
#ifdef ZEND_WIN32
preload_check_windows_restrictions(ce);
#endif
if (!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
if (preload_update_class_constants(ce) == FAILURE) {
zend_error_noreturn(E_ERROR,
@ -4601,9 +4545,11 @@ static int accel_finish_startup(void)
}
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
#ifndef ZEND_WIN32
#ifdef ZEND_WIN32
zend_accel_error(ACCEL_LOG_ERROR, "Preloading is not supported on Windows");
return FAILURE;
#else
int in_child = 0;
#endif
int ret = SUCCESS;
int rc;
int orig_error_reporting;
@ -4637,7 +4583,6 @@ static int accel_finish_startup(void)
return SUCCESS;
}
#ifndef ZEND_WIN32
if (geteuid() == 0) {
pid_t pid;
struct passwd *pw;
@ -4701,7 +4646,6 @@ static int accel_finish_startup(void)
zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
}
}
#endif
sapi_module.activate = NULL;
sapi_module.deactivate = NULL;
@ -4713,11 +4657,9 @@ static int accel_finish_startup(void)
sapi_module.ub_write = preload_ub_write;
sapi_module.flush = preload_flush;
#ifndef ZEND_WIN32
if (in_child) {
CG(compiler_options) |= ZEND_COMPILE_PRELOAD_IN_CHILD;
}
#endif
CG(compiler_options) |= ZEND_COMPILE_PRELOAD;
CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES;
@ -4792,7 +4734,6 @@ static int accel_finish_startup(void)
sapi_activate();
#ifndef ZEND_WIN32
if (in_child) {
if (ret == SUCCESS) {
exit(0);
@ -4800,9 +4741,9 @@ static int accel_finish_startup(void)
exit(2);
}
}
#endif
return ret;
#endif
}
return SUCCESS;

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78014.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
class B extends A {

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78175.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
OK
--EXPECT--

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78175_2.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(get_class(Loader::getLoader()));

View File

@ -6,10 +6,13 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78376.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(\A::$a);
?>
--EXPECT--
string(4) "aaaa"
string(4) "aaaa"

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78937.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
class Bar {

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78937.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
include(__DIR__ . "/preload_bug78937.inc");
@ -19,4 +22,4 @@ Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
object(class@anonymous)#%d (0) {
}
}

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78937.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
include(__DIR__ . "/preload_bug78937.inc");

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78937.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
class Bar {
@ -19,4 +22,4 @@ Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6
Fatal error: Class foo wasn't preloaded in %spreload_bug78937.inc on line 6

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78937.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
include(__DIR__ . "/preload_bug78937.inc");
@ -20,4 +23,4 @@ Warning: Can't preload unlinked class Foo: Unknown parent Bar in %spreload_bug78
Warning: Can't preload unlinked class class@anonymous: Unknown parent Bar in %spreload_bug78937.inc on line 3
object(Foo)#%d (0) {
}
}

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_bug78937.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
include(__DIR__ . "/preload_bug78937.inc");

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(function_exists("f1"));

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump((new ReflectionMethod('x', 'foo'))->getPrototype()->class);

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
Y::foo();

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_undef_const.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(class_exists('Foo'));

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_globals.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
$x = 123;

View File

@ -8,6 +8,7 @@ opcache.preload={PWD}/preload_inheritance_error_ind.inc
--SKIPIF--
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
if (getenv('SKIP_ASAN')) die('xfail Startup failure leak');
?>
--FILE--

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_include.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
echo "Foobar";

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(get_anon());

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_undef_const_2.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(trait_exists('T'));

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_overwritten_prop_init.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump((new Bar)->prop);

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_variance_ind.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
interface K {}

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_const_autoload.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
===DONE===
--EXPECTF--

View File

@ -7,7 +7,10 @@ opcache.optimization_level=-1
opcache.preload={PWD}/preload_nested_function.inc
opcache.interned_strings_buffer=0
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
test();

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_class_alias.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(class_exists('A'));

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_class_alias_2.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(class_exists('B'));

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_loadable_classes_1.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
var_dump(class_exists('Test'));

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_loadable_classes_2.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
Unreachable
--EXPECTF--

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_loadable_classes_3.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
Unreachable
--EXPECTF--

View File

@ -1,3 +0,0 @@
<?php
class Test extends Exception {}

View File

@ -1,16 +0,0 @@
--TEST--
Preloading: Loadable class checking (4)
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_loadable_classes_4.inc
--SKIPIF--
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY != 'Windows') die('skip Windows only');
?>
--FILE--
Unreachable
--EXPECTF--
Fatal error: Class Test uses internal class Exception during preloading, which is not supported on Windows in Unknown on line 0

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_trait_static.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
$bar = new Bar;

View File

@ -6,7 +6,10 @@ opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload_unresolved_prop_type.inc
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
===DONE===
--EXPECTF--

View File

@ -0,0 +1,16 @@
--TEST--
Preloading is not supported on Windows
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/preload.inc
--SKIPIF--
<?php
require_once('skipif.inc');
if (PHP_OS_FAMILY != 'Windows') die('skip Windows only test');
?>
--FILE--
Unreachable
--EXPECTF--
%s: Error Preloading is not supported on Windows