Skip to content

Commit

Permalink
Remove support for preloading on Windows
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Jan 6, 2020
1 parent 846b647 commit 59c3dda
Show file tree
Hide file tree
Showing 37 changed files with 147 additions and 141 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
24 changes: 0 additions & 24 deletions ext/ffi/tests/300-win32.phpt

This file was deleted.

5 changes: 4 additions & 1 deletion ext/ffi/tests/bug78761.phpt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
69 changes: 5 additions & 64 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -4637,7 +4583,6 @@ static int accel_finish_startup(void)
return SUCCESS;
}

#ifndef ZEND_WIN32
if (geteuid() == 0) {
pid_t pid;
struct passwd *pw;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -4792,17 +4734,16 @@ static int accel_finish_startup(void)

sapi_activate();

#ifndef ZEND_WIN32
if (in_child) {
if (ret == SUCCESS) {
exit(0);
} else {
exit(2);
}
}
#endif

return ret;
#endif
}

return SUCCESS;
Expand Down
5 changes: 4 additions & 1 deletion ext/opcache/tests/bug78014.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 4 additions & 1 deletion ext/opcache/tests/bug78175.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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--
Expand Down
5 changes: 4 additions & 1 deletion ext/opcache/tests/bug78175_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down
7 changes: 5 additions & 2 deletions ext/opcache/tests/bug78376.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
5 changes: 4 additions & 1 deletion ext/opcache/tests/bug78937_1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 5 additions & 2 deletions ext/opcache/tests/bug78937_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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) {
}
}
5 changes: 4 additions & 1 deletion ext/opcache/tests/bug78937_3.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
7 changes: 5 additions & 2 deletions ext/opcache/tests/bug78937_4.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
7 changes: 5 additions & 2 deletions ext/opcache/tests/bug78937_5.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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) {
}
}
5 changes: 4 additions & 1 deletion ext/opcache/tests/bug78937_6.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 4 additions & 1 deletion ext/opcache/tests/preload_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down
5 changes: 4 additions & 1 deletion ext/opcache/tests/preload_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion ext/opcache/tests/preload_003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading

0 comments on commit 59c3dda

Please sign in to comment.